This commit is contained in:
2025-11-11 00:04:55 -06:00
parent a76ad41fde
commit 40538eddfd
6405 changed files with 1289756 additions and 0 deletions

127
build/error.d.ts vendored Normal file
View File

@ -0,0 +1,127 @@
export type Jsonable = string | number | boolean | object | null | undefined | readonly Jsonable[] | {
readonly [key: string]: Jsonable;
} | {
toJSON(): Jsonable;
};
export declare class BaseError extends Error {
readonly context?: Jsonable;
constructor(message: string, options?: {
cause?: Error;
context?: Jsonable;
});
}
export declare function ensureError(value: unknown): BaseError;
export declare class InvalidCountryCodeError extends BaseError {
constructor(message: string, options?: {
cause?: Error;
context?: Jsonable;
});
}
export declare class InvalidLanguageCodeError extends BaseError {
constructor(message: string, options?: {
cause?: Error;
context?: Jsonable;
});
}
export declare class StationNotFoundError extends BaseError {
constructor(message: string, options?: {
cause?: Error;
context?: Jsonable;
});
}
export declare class DeviceNotFoundError extends BaseError {
constructor(message: string, options?: {
cause?: Error;
context?: Jsonable;
});
}
export declare class NotSupportedError extends BaseError {
constructor(message: string, options?: {
cause?: Error;
context?: Jsonable;
});
}
export declare class WrongStationError extends BaseError {
constructor(message: string, options?: {
cause?: Error;
context?: Jsonable;
});
}
export declare class RTSPPropertyNotEnabledError extends BaseError {
constructor(message: string, options?: {
cause?: Error;
context?: Jsonable;
});
}
export declare class InvalidPropertyValueError extends BaseError {
constructor(message: string, options?: {
cause?: Error;
context?: Jsonable;
});
}
export declare class InvalidCommandValueError extends BaseError {
constructor(message: string, options?: {
cause?: Error;
context?: Jsonable;
});
}
export declare class ReadOnlyPropertyError extends BaseError {
constructor(message: string, options?: {
cause?: Error;
context?: Jsonable;
});
}
export declare class LivestreamError extends BaseError {
constructor(message: string, options?: {
cause?: Error;
context?: Jsonable;
});
}
export declare class TalkbackError extends BaseError {
constructor(message: string, options?: {
cause?: Error;
context?: Jsonable;
});
}
export declare class StationConnectTimeoutError extends BaseError {
constructor(message: string, options?: {
cause?: Error;
context?: Jsonable;
});
}
export declare class AddUserError extends BaseError {
constructor(message: string, options?: {
cause?: Error;
context?: Jsonable;
});
}
export declare class DeleteUserError extends BaseError {
constructor(message: string, options?: {
cause?: Error;
context?: Jsonable;
});
}
export declare class UpdateUserUsernameError extends BaseError {
constructor(message: string, options?: {
cause?: Error;
context?: Jsonable;
});
}
export declare class UpdateUserScheduleError extends BaseError {
constructor(message: string, options?: {
cause?: Error;
context?: Jsonable;
});
}
export declare class UpdateUserPasscodeError extends BaseError {
constructor(message: string, options?: {
cause?: Error;
context?: Jsonable;
});
}
export declare class PinNotVerifiedError extends BaseError {
constructor(message: string, options?: {
cause?: Error;
context?: Jsonable;
});
}

178
build/error.js Normal file
View File

@ -0,0 +1,178 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.PinNotVerifiedError = exports.UpdateUserPasscodeError = exports.UpdateUserScheduleError = exports.UpdateUserUsernameError = exports.DeleteUserError = exports.AddUserError = exports.StationConnectTimeoutError = exports.TalkbackError = exports.LivestreamError = exports.ReadOnlyPropertyError = exports.InvalidCommandValueError = exports.InvalidPropertyValueError = exports.RTSPPropertyNotEnabledError = exports.WrongStationError = exports.NotSupportedError = exports.DeviceNotFoundError = exports.StationNotFoundError = exports.InvalidLanguageCodeError = exports.InvalidCountryCodeError = exports.BaseError = void 0;
exports.ensureError = ensureError;
class BaseError extends Error {
context;
constructor(message, options = {}) {
const { cause, context } = options;
super(message, { cause }); //NodeJs 16.9.0
this.name = this.constructor.name;
this.context = context;
}
}
exports.BaseError = BaseError;
function ensureError(value) {
if (value instanceof Error)
return value;
let stringified = "[Unable to stringify the thrown value]";
try {
stringified = JSON.stringify(value);
}
catch { }
const error = new Error(`This value was thrown as is, not through an Error: ${stringified}`);
return error;
}
class InvalidCountryCodeError extends BaseError {
constructor(message, options = {}) {
super(message, options);
Object.setPrototypeOf(this, new.target.prototype);
this.name = InvalidCountryCodeError.name;
}
}
exports.InvalidCountryCodeError = InvalidCountryCodeError;
class InvalidLanguageCodeError extends BaseError {
constructor(message, options = {}) {
super(message, options);
Object.setPrototypeOf(this, new.target.prototype);
this.name = InvalidLanguageCodeError.name;
}
}
exports.InvalidLanguageCodeError = InvalidLanguageCodeError;
class StationNotFoundError extends BaseError {
constructor(message, options = {}) {
super(message, options);
Object.setPrototypeOf(this, new.target.prototype);
this.name = StationNotFoundError.name;
}
}
exports.StationNotFoundError = StationNotFoundError;
class DeviceNotFoundError extends BaseError {
constructor(message, options = {}) {
super(message, options);
Object.setPrototypeOf(this, new.target.prototype);
this.name = DeviceNotFoundError.name;
}
}
exports.DeviceNotFoundError = DeviceNotFoundError;
class NotSupportedError extends BaseError {
constructor(message, options = {}) {
super(message, options);
Object.setPrototypeOf(this, new.target.prototype);
this.name = NotSupportedError.name;
}
}
exports.NotSupportedError = NotSupportedError;
class WrongStationError extends BaseError {
constructor(message, options = {}) {
super(message, options);
Object.setPrototypeOf(this, new.target.prototype);
this.name = WrongStationError.name;
}
}
exports.WrongStationError = WrongStationError;
class RTSPPropertyNotEnabledError extends BaseError {
constructor(message, options = {}) {
super(message, options);
Object.setPrototypeOf(this, new.target.prototype);
this.name = RTSPPropertyNotEnabledError.name;
}
}
exports.RTSPPropertyNotEnabledError = RTSPPropertyNotEnabledError;
class InvalidPropertyValueError extends BaseError {
constructor(message, options = {}) {
super(message, options);
Object.setPrototypeOf(this, new.target.prototype);
this.name = InvalidPropertyValueError.name;
}
}
exports.InvalidPropertyValueError = InvalidPropertyValueError;
class InvalidCommandValueError extends BaseError {
constructor(message, options = {}) {
super(message, options);
Object.setPrototypeOf(this, new.target.prototype);
this.name = InvalidCommandValueError.name;
}
}
exports.InvalidCommandValueError = InvalidCommandValueError;
class ReadOnlyPropertyError extends BaseError {
constructor(message, options = {}) {
super(message, options);
Object.setPrototypeOf(this, new.target.prototype);
this.name = ReadOnlyPropertyError.name;
}
}
exports.ReadOnlyPropertyError = ReadOnlyPropertyError;
class LivestreamError extends BaseError {
constructor(message, options = {}) {
super(message, options);
Object.setPrototypeOf(this, new.target.prototype);
this.name = LivestreamError.name;
}
}
exports.LivestreamError = LivestreamError;
class TalkbackError extends BaseError {
constructor(message, options = {}) {
super(message, options);
Object.setPrototypeOf(this, new.target.prototype);
this.name = TalkbackError.name;
}
}
exports.TalkbackError = TalkbackError;
class StationConnectTimeoutError extends BaseError {
constructor(message, options = {}) {
super(message, options);
Object.setPrototypeOf(this, new.target.prototype);
this.name = StationConnectTimeoutError.name;
}
}
exports.StationConnectTimeoutError = StationConnectTimeoutError;
class AddUserError extends BaseError {
constructor(message, options = {}) {
super(message, options);
Object.setPrototypeOf(this, new.target.prototype);
this.name = AddUserError.name;
}
}
exports.AddUserError = AddUserError;
class DeleteUserError extends BaseError {
constructor(message, options = {}) {
super(message, options);
Object.setPrototypeOf(this, new.target.prototype);
this.name = DeleteUserError.name;
}
}
exports.DeleteUserError = DeleteUserError;
class UpdateUserUsernameError extends BaseError {
constructor(message, options = {}) {
super(message, options);
Object.setPrototypeOf(this, new.target.prototype);
this.name = UpdateUserUsernameError.name;
}
}
exports.UpdateUserUsernameError = UpdateUserUsernameError;
class UpdateUserScheduleError extends BaseError {
constructor(message, options = {}) {
super(message, options);
Object.setPrototypeOf(this, new.target.prototype);
this.name = UpdateUserScheduleError.name;
}
}
exports.UpdateUserScheduleError = UpdateUserScheduleError;
class UpdateUserPasscodeError extends BaseError {
constructor(message, options = {}) {
super(message, options);
Object.setPrototypeOf(this, new.target.prototype);
this.name = UpdateUserPasscodeError.name;
}
}
exports.UpdateUserPasscodeError = UpdateUserPasscodeError;
class PinNotVerifiedError extends BaseError {
constructor(message, options = {}) {
super(message, options);
Object.setPrototypeOf(this, new.target.prototype);
this.name = PinNotVerifiedError.name;
}
}
exports.PinNotVerifiedError = PinNotVerifiedError;
//# sourceMappingURL=error.js.map

1
build/error.js.map Normal file

File diff suppressed because one or more lines are too long

179
build/eufysecurity.d.ts vendored Normal file
View File

@ -0,0 +1,179 @@
import { TypedEmitter } from "tiny-typed-emitter";
import { EufySecurityEvents, EufySecurityConfig } from "./interfaces";
import { HTTPApi } from "./http/api";
import { LoginOptions, Schedule } from "./http/interfaces";
import { Station } from "./http/station";
import { PushNotificationService } from "./push/service";
import { Credentials } from "./push/models";
import { Device } from "./http/device";
import { P2PConnectionType } from "./p2p/types";
import { Logger, LoggingCategories } from "./logging";
import { LogLevel } from "typescript-logging";
export declare class EufySecurity extends TypedEmitter<EufySecurityEvents> {
private config;
private api;
private houses;
private stations;
private devices;
private readonly P2P_REFRESH_INTERVAL_MIN;
private cameraMaxLivestreamSeconds;
private cameraStationLivestreamTimeout;
private pushService;
private mqttService;
private pushCloudRegistered;
private pushCloudChecked;
private persistentFile;
private persistentData;
private connected;
private retries;
private refreshEufySecurityCloudTimeout?;
private refreshEufySecurityP2PTimeout;
private deviceSnoozeTimeout;
private loadingEmitter;
private stationsLoaded?;
private devicesLoaded?;
private constructor();
static initialize(config: EufySecurityConfig, log?: Logger): Promise<EufySecurity>;
protected _initializeInternals(): Promise<void>;
private initMQTT;
setLoggingLevel(category: LoggingCategories, level: LogLevel): void;
getLoggingLevel(category: LoggingCategories): number;
setInternalLogger(logger: Logger): void;
getInternalLogger(): Logger | undefined;
getPushService(): PushNotificationService;
private addStation;
private removeStation;
private updateStation;
private addDevice;
private removeDevice;
private updateDevice;
getDevices(): Promise<Array<Device>>;
getDevicesFromStation(stationSN: string): Promise<Array<Device>>;
getDevice(deviceSN: string): Promise<Device>;
getStationDevice(stationSN: string, channel: number): Promise<Device>;
getStations(): Promise<Array<Station>>;
getStation(stationSN: string): Promise<Station>;
getApi(): HTTPApi;
connectToStation(stationSN: string, p2pConnectionType?: P2PConnectionType): Promise<void>;
isStationConnected(stationSN: string): Promise<boolean>;
isStationEnergySavingDevice(stationSN: string): Promise<boolean>;
private handleHouses;
private handleHubs;
private refreshP2PData;
private onStationConnect;
private onStationConnectionError;
private onStationClose;
private handleDevices;
refreshCloudData(): Promise<void>;
close(): void;
setCameraMaxLivestreamDuration(seconds: number): void;
getCameraMaxLivestreamDuration(): number;
registerPushNotifications(credentials?: Credentials, persistentIds?: string[]): Promise<void>;
connect(options?: LoginOptions): Promise<void>;
getPushPersistentIds(): string[];
private updateDeviceProperties;
private onAPIClose;
private onAPIConnect;
private onAPIConnectionError;
startStationLivestream(deviceSN: string): Promise<void>;
stopStationLivestream(deviceSN: string): Promise<void>;
private writePersistentData;
private saveCloudToken;
private savePushCredentials;
private savePushPersistentIds;
getVersion(): string;
isPushConnected(): boolean;
isMQTTConnected(): boolean;
isConnected(): boolean;
private processInvitations;
private onPushMessage;
startStationDownload(deviceSN: string, path: string, cipherID: number): Promise<void>;
cancelStationDownload(deviceSN: string): Promise<void>;
getConfig(): EufySecurityConfig;
setDeviceProperty(deviceSN: string, name: string, value: unknown): Promise<void>;
setStationProperty(stationSN: string, name: string, value: unknown): Promise<void>;
private onStartStationLivestream;
private onStopStationLivestream;
private onErrorStationLivestream;
private onStartStationRTSPLivestream;
private onStopStationRTSPLivestream;
private onStationStartDownload;
private onStationFinishDownload;
private onStationCommandResult;
private onStationSecondaryCommandResult;
private onStationRtspUrl;
private onStationGuardMode;
private onStationCurrentMode;
private onStationPropertyChanged;
private onStationRawPropertyChanged;
private onStationAlarmEvent;
private onStationAlarmDelayEvent;
private onStationArmDelayEvent;
private onStationAlarmArmedEvent;
private onDevicePropertyChanged;
private onDeviceRawPropertyChanged;
private onDeviceCryingDetected;
private onDeviceSoundDetected;
private onDevicePetDetected;
private onDeviceVehicleDetected;
private onDeviceMotionDetected;
private onDevicePersonDetected;
private onDeviceRings;
private onDeviceLocked;
private onDeviceOpen;
private onDevicePackageDelivered;
private onDevicePackageStranded;
private onDevicePackageTaken;
private onDeviceSomeoneLoitering;
private onDeviceRadarMotionDetected;
private onDevice911Alarm;
private onDeviceShakeAlarm;
private onDeviceWrongTryProtectAlarm;
private onDeviceLongTimeNotClose;
private onDeviceLowBattery;
private onDeviceJammed;
private onDeviceStrangerPersonDetected;
private onDeviceDogDetected;
private onDeviceDogLickDetected;
private onDeviceDogPoopDetected;
private onDeviceReady;
private onStationRuntimeState;
private onStationChargingState;
private onStationWifiRssi;
private onCaptchaRequest;
private onFloodlightManualSwitch;
private onAuthTokenInvalidated;
private onTfaRequest;
private onStationTalkbackStart;
private onStationTalkbackStop;
private onStationTalkbackError;
startStationTalkback(deviceSN: string): Promise<void>;
stopStationTalkback(deviceSN: string): Promise<void>;
private onStationDeviceShakeAlarm;
private onStationDevice911Alarm;
private onStationDeviceJammed;
private onStationDeviceLowBattery;
private onStationDeviceWrongTryProtectAlarm;
addUser(deviceSN: string, username: string, passcode: string, schedule?: Schedule): Promise<void>;
deleteUser(deviceSN: string, username: string): Promise<void>;
updateUser(deviceSN: string, username: string, newUsername: string): Promise<void>;
updateUserPasscode(deviceSN: string, username: string, passcode: string): Promise<void>;
updateUserSchedule(deviceSN: string, username: string, schedule: Schedule): Promise<void>;
private onStationDevicePinVerified;
private onStationSdInfoEx;
private _emitStationImageDownload;
private onStationImageDownload;
private onStationDatabaseQueryLatest;
private onStationDatabaseQueryLocal;
private onStationDatabaseCountByDate;
private onStationDatabaseDelete;
private onStationSensorStatus;
private onStationGarageDoorStatus;
private onStorageInfoHb3;
private onDeviceTampering;
private onDeviceLowTemperature;
private onDeviceHighTemperature;
private onDevicePinIncorrect;
private onDeviceLidStuck;
private onDeviceBatteryFullyCharged;
}

2634
build/eufysecurity.js Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

90
build/http/api.d.ts vendored Normal file
View File

@ -0,0 +1,90 @@
import { TypedEmitter } from "tiny-typed-emitter";
import { TrustDevice, Cipher, EventRecordResponse, ConfirmInvite, SensorHistoryEntry, ApiResponse, HouseDetail, DeviceListResponse, StationListResponse, HouseInviteListResponse, HouseListResponse, PassportProfileResponse, User, AddUserResponse } from "./models";
import { HTTPApiEvents, Ciphers, FullDevices, Hubs, Voices, Invites, HTTPApiRequest, HTTPApiPersistentData, LoginOptions, Schedule } from "./interfaces";
import { EventFilterType, PublicKeyType, VerfyCodeTypes } from "./types";
export declare class HTTPApi extends TypedEmitter<HTTPApiEvents> {
private static apiDomainBase;
private readonly SERVER_PUBLIC_KEY;
private apiBase;
private username;
private password;
private ecdh;
private token;
private tokenExpiration;
private renewAuthTokenJob?;
private connected;
private requestEufyCloud;
private throttle;
private devices;
private hubs;
private houses;
private persistentData;
private headers;
private constructor();
static getApiBaseFromCloud(country: string): Promise<string>;
private loadLibraries;
static initialize(country: string, username: string, password: string, persistentData?: HTTPApiPersistentData): Promise<HTTPApi>;
private clearScheduleRenewAuthToken;
private scheduleRenewAuthToken;
private invalidateToken;
setPhoneModel(model: string): void;
getPhoneModel(): string;
getCountry(): string;
setLanguage(language: string): void;
getLanguage(): string;
login(options?: LoginOptions): Promise<void>;
sendVerifyCode(type?: VerfyCodeTypes): Promise<boolean>;
listTrustDevice(): Promise<Array<TrustDevice>>;
addTrustDevice(verifyCode: string): Promise<boolean>;
getStationList(): Promise<Array<StationListResponse>>;
getDeviceList(): Promise<Array<DeviceListResponse>>;
refreshHouseData(): Promise<void>;
refreshStationData(): Promise<void>;
refreshDeviceData(): Promise<void>;
refreshAllData(): Promise<void>;
request(request: HTTPApiRequest, withoutUrlPrefix?: boolean): Promise<ApiResponse>;
checkPushToken(): Promise<boolean>;
registerPushToken(token: string): Promise<boolean>;
setParameters(stationSN: string, deviceSN: string, params: {
paramType: number;
paramValue: any;
}[]): Promise<boolean>;
getCiphers(/*stationSN: string, */ cipherIDs: Array<number>, userID: string): Promise<Ciphers>;
getVoices(deviceSN: string): Promise<Voices>;
getCipher(/*stationSN: string, */ cipherID: number, userID: string): Promise<Cipher>;
getDevices(): FullDevices;
getHubs(): Hubs;
getToken(): string | null;
getTokenExpiration(): Date | null;
setToken(token: string): void;
setTokenExpiration(tokenExpiration: Date): void;
getAPIBase(): string;
setOpenUDID(openudid: string): void;
setSerialNumber(serialnumber: string): void;
private _getEvents;
getVideoEvents(startTime: Date, endTime: Date, filter?: EventFilterType, maxResults?: number): Promise<Array<EventRecordResponse>>;
getAlarmEvents(startTime: Date, endTime: Date, filter?: EventFilterType, maxResults?: number): Promise<Array<EventRecordResponse>>;
getHistoryEvents(startTime: Date, endTime: Date, filter?: EventFilterType, maxResults?: number): Promise<Array<EventRecordResponse>>;
getAllVideoEvents(filter?: EventFilterType, maxResults?: number): Promise<Array<EventRecordResponse>>;
getAllAlarmEvents(filter?: EventFilterType, maxResults?: number): Promise<Array<EventRecordResponse>>;
getAllHistoryEvents(filter?: EventFilterType, maxResults?: number): Promise<Array<EventRecordResponse>>;
isConnected(): boolean;
getInvites(): Promise<Invites>;
confirmInvites(confirmInvites: Array<ConfirmInvite>): Promise<boolean>;
getPublicKey(deviceSN: string, type: PublicKeyType): Promise<string>;
decryptAPIData(data?: string, json?: boolean): any;
getSensorHistory(stationSN: string, deviceSN: string): Promise<Array<SensorHistoryEntry>>;
getHouseDetail(houseID: string): Promise<HouseDetail | null>;
getHouseList(): Promise<Array<HouseListResponse>>;
getHouseInviteList(isInviter?: number): Promise<Array<HouseInviteListResponse>>;
confirmHouseInvite(houseID: string, inviteID: number): Promise<boolean>;
getPersistentData(): HTTPApiPersistentData | undefined;
getPassportProfile(): Promise<PassportProfileResponse | null>;
addUser(deviceSN: string, nickname: string, stationSN?: string): Promise<AddUserResponse | null>;
deleteUser(deviceSN: string, shortUserId: string, stationSN?: string): Promise<boolean>;
getUsers(deviceSN: string, stationSN: string): Promise<Array<User> | null>;
getUser(deviceSN: string, stationSN: string, shortUserId: string): Promise<User | null>;
updateUser(deviceSN: string, stationSN: string, shortUserId: string, nickname: string): Promise<boolean>;
getImage(deviceSN: string, url: string): Promise<Buffer>;
updateUserPassword(deviceSN: string, shortUserId: string, passwordId: string, schedule: Schedule, stationSN?: string): Promise<boolean>;
}

1578
build/http/api.js Normal file

File diff suppressed because it is too large Load Diff

1
build/http/api.js.map Normal file

File diff suppressed because one or more lines are too long

8
build/http/cache.d.ts vendored Normal file
View File

@ -0,0 +1,8 @@
export declare class Cache extends Map {
private ttl;
private schedules;
constructor(ttl?: number);
delete(key: any): boolean;
set(key: any, value: any, ttl?: number): this;
get(key: any): any;
}

34
build/http/cache.js Normal file
View File

@ -0,0 +1,34 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Cache = void 0;
class Cache extends Map {
ttl = 60000;
schedules = new Map();
constructor(ttl) {
super();
if (ttl !== undefined)
this.ttl = ttl;
}
delete(key) {
const result = super.delete(key);
clearTimeout(this.schedules.get(key));
this.schedules.delete(key);
return result;
}
set(key, value, ttl = this.ttl) {
super.set(key, value);
if (this.schedules.has(key)) {
clearTimeout(this.schedules.get(key));
}
const schedule = setTimeout(() => {
this.delete(key);
}, ttl);
this.schedules.set(key, schedule);
return this;
}
get(key) {
return super.get(key);
}
}
exports.Cache = Cache;
//# sourceMappingURL=cache.js.map

1
build/http/cache.js.map Normal file
View File

@ -0,0 +1 @@
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/http/cache.ts"],"names":[],"mappings":";;;AAAA,MAAa,KAAM,SAAQ,GAAG;IAElB,GAAG,GAAG,KAAK,CAAC;IACZ,SAAS,GAAI,IAAI,GAAG,EAAE,CAAC;IAE/B,YAAY,GAAY;QACpB,KAAK,EAAE,CAAC;QACR,IAAI,GAAG,KAAK,SAAS;YACjB,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;IACvB,CAAC;IAEM,MAAM,CAAC,GAAQ;QAClB,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACjC,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;QACtC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC3B,OAAO,MAAM,CAAC;IAClB,CAAC;IAEM,GAAG,CAAC,GAAQ,EAAE,KAAU,EAAE,GAAG,GAAG,IAAI,CAAC,GAAG;QAC3C,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACtB,IAAI,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YAC1B,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;QAC1C,CAAC;QAED,MAAM,QAAQ,GAAG,UAAU,CAAC,GAAG,EAAE;YAC7B,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACrB,CAAC,EAAE,GAAG,CAAC,CAAC;QACR,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;QAClC,OAAO,IAAI,CAAC;IAChB,CAAC;IAEM,GAAG,CAAC,GAAQ;QACf,OAAO,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC1B,CAAC;CACJ;AAlCD,sBAkCC"}

3
build/http/const.d.ts vendored Normal file
View File

@ -0,0 +1,3 @@
import { EufyTimezone } from "./utils";
export declare const PhoneModels: Array<string>;
export declare const timeZoneData: Array<EufyTimezone>;

8546
build/http/const.js Normal file

File diff suppressed because it is too large Load Diff

1
build/http/const.js.map Normal file

File diff suppressed because one or more lines are too long

474
build/http/device.d.ts vendored Normal file
View File

@ -0,0 +1,474 @@
import { TypedEmitter } from "tiny-typed-emitter";
import { HTTPApi } from "./api";
import { CommandName, DeviceEvent, SourceType, TrackerType } from "./types";
import { DeviceListResponse } from "./models";
import { DeviceEvents, PropertyValue, PropertyValues, PropertyMetadataAny, IndexedProperty, RawValues, Schedule, Voices, DeviceConfig } from "./interfaces";
import { PushMessage } from "../push/models";
import { DeviceSmartLockNotifyData } from "../mqtt/model";
import { Station } from "./station";
export declare class Device extends TypedEmitter<DeviceEvents> {
protected api: HTTPApi;
protected rawDevice: DeviceListResponse;
protected eventTimeouts: Map<DeviceEvent, NodeJS.Timeout>;
protected pictureEventTimeouts: Map<string, NodeJS.Timeout>;
protected properties: PropertyValues;
protected config: DeviceConfig;
private rawProperties;
private ready;
protected constructor(api: HTTPApi, device: DeviceListResponse, deviceConfig: DeviceConfig);
protected initializeState(): void;
initialize(): void;
getRawDevice(): DeviceListResponse;
update(device: DeviceListResponse): void;
updateProperty(name: string, value: PropertyValue, force?: boolean): boolean;
updateRawProperties(values: RawValues): void;
protected handlePropertyChange(metadata: PropertyMetadataAny, oldValue: PropertyValue, newValue: PropertyValue): void;
updateRawProperty(type: number, value: string, source: SourceType): boolean;
protected convertRawPropertyValue(property: PropertyMetadataAny, value: string): PropertyValue;
getPropertyMetadata(name: string, hidden?: boolean): PropertyMetadataAny;
getPropertyValue(name: string): PropertyValue;
hasPropertyValue(name: string): boolean;
getRawProperty(type: number): string | undefined;
getRawProperties(): RawValues;
getProperties(): PropertyValues;
getPropertiesMetadata(hidden?: boolean): IndexedProperty;
hasProperty(name: string, hidden?: boolean): boolean;
getCommands(): Array<CommandName>;
hasCommand(name: CommandName): boolean;
processPushNotification(_station: Station, _message: PushMessage, _eventDurationSeconds: number): void;
setCustomPropertyValue(name: string, value: PropertyValue): void;
destroy(): void;
protected clearEventTimeout(eventType: DeviceEvent): void;
static isSupported(type: number): boolean;
static isCamera(type: number): boolean;
static hasBattery(type: number): boolean;
static isStation(type: number): boolean;
static isCamera1(type: number): boolean;
static isCameraE(type: number): boolean;
static isSensor(type: number): boolean;
static isKeyPad(type: number): boolean;
static isDoorbell(type: number): boolean;
static isWiredDoorbell(type: number): boolean;
static isWiredDoorbellT8200X(type: number, serialnumber: string): boolean;
static isWiredDoorbellDual(type: number): boolean;
static isIndoorCamera(type: number): boolean;
static isPanAndTiltCamera(type: number): boolean;
static isOutdoorPanAndTiltCamera(type: number): boolean;
static isIndoorPanAndTiltCameraS350(type: number): boolean;
static isFloodLight(type: number): boolean;
static isFloodLightT8420X(type: number, serialnumber: string): boolean;
static isFloodLightT8423(type: number): boolean;
static isFloodLightT8425(type: number): boolean;
static isWallLightCam(type: number): boolean;
static isLock(type: number): boolean;
static isLockKeypad(type: number): boolean;
static isLockBle(type: number): boolean;
static isLockBleNoFinger(type: number): boolean;
static isLockWifi(type: number, serialnumber: string): boolean;
static isLockWifiNoFinger(type: number): boolean;
static isLockWifiR10(type: number): boolean;
static isLockWifiR20(type: number): boolean;
static isLockWifiVideo(type: number): boolean;
static isLockWifiR10Keypad(type: number): boolean;
static isLockWifiR20Keypad(type: number): boolean;
static isLockWifiT8506(type: number): boolean;
static isLockWifiT8502(type: number): boolean;
static isLockWifiT8510P(type: number, serialnumber: string): boolean;
static isLockWifiT8520P(type: number, serialnumber: string): boolean;
static isBatteryDoorbell1(type: number): boolean;
static isBatteryDoorbell2(type: number): boolean;
static isBatteryDoorbellDual(type: number): boolean;
static isBatteryDoorbellDualE340(type: number): boolean;
static isBatteryDoorbellC30(type: number): boolean;
static isBatteryDoorbellC31(type: number): boolean;
static isDoorbellDual(type: number): boolean;
static isBatteryDoorbell(type: number): boolean;
static isSoloCamera(type: number): boolean;
static isSoloCameraPro(type: number): boolean;
static isSoloCameraSpotlight1080(type: number): boolean;
static isSoloCameraSpotlight2k(type: number): boolean;
static isSoloCameraSpotlightSolar(type: number): boolean;
static isSoloCameraSolar(type: number): boolean;
static isSoloCameraC210(type: number): boolean;
static isSoloCameraE30(type: number): boolean;
static isSoloCameras(type: number): boolean;
static isStarlight4GLTE(type: number): boolean;
static isIndoorOutdoorCamera1080p(type: number): boolean;
static isIndoorOutdoorCamera1080pNoLight(type: number): boolean;
static isIndoorOutdoorCamera2k(type: number): boolean;
static isIndoorCamMini(type: number): boolean;
static isCamera1Product(type: number): boolean;
static isCamera2(type: number): boolean;
static isCamera2C(type: number): boolean;
static isCamera2Pro(type: number): boolean;
static isCamera2CPro(type: number): boolean;
static isCamera2Product(type: number): boolean;
static isCamera3(type: number): boolean;
static isCamera3C(type: number): boolean;
static isCamera3Pro(type: number): boolean;
static isCameraProfessional247(type: number): boolean;
static isCamera3Product(type: number): boolean;
static isEntrySensor(type: number): boolean;
static isMotionSensor(type: number): boolean;
static isSmartDrop(type: number): boolean;
static isSmartSafe(type: number): boolean;
static isGarageCamera(type: number): boolean;
static isIntegratedDeviceBySn(sn: string): boolean;
static isSoloCameraBySn(sn: string): boolean;
static isSmartDropBySn(sn: string): boolean;
static isLockBySn(sn: string): boolean;
static isGarageCameraBySn(sn: string): boolean;
static isFloodlightBySn(sn: string): boolean;
static isIndoorCameraBySn(sn: string): boolean;
static is4GCameraBySn(sn: string): boolean;
static isSmartSafeBySn(sn: string): boolean;
static isSmartTrackCard(type: number): boolean;
static isSmartTrackLink(type: number): boolean;
static isSmartTrack(type: number): boolean;
isCamera(): boolean;
isFloodLight(): boolean;
isFloodLightT8420X(): boolean;
isFloodLightT8423(): boolean;
isFloodLightT8425(): boolean;
isWallLightCam(): boolean;
isDoorbell(): boolean;
isWiredDoorbell(): boolean;
isWiredDoorbellT8200X(): boolean;
isWiredDoorbellDual(): boolean;
isLock(): boolean;
isLockKeypad(): boolean;
isLockBle(): boolean;
isLockBleNoFinger(): boolean;
isLockWifi(): boolean;
isLockWifiNoFinger(): boolean;
isLockWifiR10(): boolean;
isLockWifiR20(): boolean;
isLockWifiVideo(): boolean;
isLockWifiR10Keypad(): boolean;
isLockWifiR20Keypad(): boolean;
isLockWifiT8506(): boolean;
isLockWifiT8502(): boolean;
isLockWifiT8510P(): boolean;
isLockWifiT8520P(): boolean;
isBatteryDoorbell1(): boolean;
isBatteryDoorbell2(): boolean;
isBatteryDoorbellDual(): boolean;
isBatteryDoorbellDualE340(): boolean;
isBatteryDoorbellC30(): boolean;
isBatteryDoorbellC31(): boolean;
isDoorbellDual(): boolean;
isBatteryDoorbell(): boolean;
isSoloCamera(): boolean;
isSoloCameraPro(): boolean;
isSoloCameraSpotlight1080(): boolean;
isSoloCameraSpotlight2k(): boolean;
isSoloCameraSpotlightSolar(): boolean;
isSoloCameraSolar(): boolean;
isSoloCameraC210(): boolean;
isSoloCameraE30(): boolean;
isStarlight4GLTE(): boolean;
isIndoorOutdoorCamera1080p(): boolean;
isIndoorOutdoorCamera1080pNoLight(): boolean;
isIndoorOutdoorCamera2k(): boolean;
isIndoorCamMini(): boolean;
isSoloCameras(): boolean;
isCamera2(): boolean;
isCamera2C(): boolean;
isCamera2Pro(): boolean;
isCamera2CPro(): boolean;
isCamera2Product(): boolean;
isCamera3(): boolean;
isCamera3C(): boolean;
isCameraProfessional247(): boolean;
isCamera3Pro(): boolean;
isCamera3Product(): boolean;
isEntrySensor(): boolean;
isKeyPad(): boolean;
isMotionSensor(): boolean;
isIndoorCamera(): boolean;
isPanAndTiltCamera(): boolean;
isOutdoorPanAndTiltCamera(): boolean;
isIndoorPanAndTiltCameraS350(): boolean;
isSmartDrop(): boolean;
isSmartSafe(): boolean;
isGarageCamera(): boolean;
isIntegratedDevice(): boolean;
isSmartTrack(): boolean;
isSmartTrackCard(): boolean;
isSmartTrackLink(): boolean;
hasBattery(): boolean;
getDeviceKey(): string;
getDeviceType(): number;
getHardwareVersion(): string;
getSoftwareVersion(): string;
getModel(): string;
getName(): string;
getSerial(): string;
getStationSerial(): string;
setParameters(params: {
paramType: number;
paramValue: any;
}[]): Promise<boolean>;
getChannel(): number;
getStateID(state: string, level?: number): string;
getStateChannel(): string;
getWifiRssi(): PropertyValue;
getStoragePath(filename: string): string;
isEnabled(): PropertyValue;
}
export declare class Camera extends Device {
protected constructor(api: HTTPApi, device: DeviceListResponse, deviceConfig: DeviceConfig);
static getInstance(api: HTTPApi, device: DeviceListResponse, deviceConfig: DeviceConfig): Promise<Camera>;
getStateChannel(): string;
protected convertRawPropertyValue(property: PropertyMetadataAny, value: string): PropertyValue;
getLastCameraImageURL(): PropertyValue;
getMACAddress(): string;
startDetection(): Promise<void>;
stopDetection(): Promise<void>;
getState(): PropertyValue;
close(): Promise<void>;
getLastChargingDays(): number;
getLastChargingFalseEvents(): number;
getLastChargingRecordedEvents(): number;
getLastChargingTotalEvents(): number;
getBatteryValue(): PropertyValue;
getBatteryTemperature(): PropertyValue;
isMotionDetectionEnabled(): PropertyValue;
isLedEnabled(): PropertyValue;
isAutoNightVisionEnabled(): PropertyValue;
isRTSPStreamEnabled(): PropertyValue;
isAntiTheftDetectionEnabled(): PropertyValue;
getWatermark(): PropertyValue;
isMotionDetected(): boolean;
isPersonDetected(): boolean;
getDetectedPerson(): string;
protected handlePropertyChange(metadata: PropertyMetadataAny, oldValue: PropertyValue, newValue: PropertyValue): void;
processPushNotification(station: Station, message: PushMessage, eventDurationSeconds: number): void;
}
export declare class SoloCamera extends Camera {
static getInstance(api: HTTPApi, device: DeviceListResponse, deviceConfig: DeviceConfig): Promise<SoloCamera>;
isLedEnabled(): PropertyValue;
isMotionDetectionEnabled(): PropertyValue;
protected convertRawPropertyValue(property: PropertyMetadataAny, value: string): PropertyValue;
processPushNotification(station: Station, message: PushMessage, eventDurationSeconds: number): void;
}
export declare class IndoorCamera extends Camera {
protected constructor(api: HTTPApi, device: DeviceListResponse, deviceConfig: DeviceConfig);
static getInstance(api: HTTPApi, device: DeviceListResponse, deviceConfig: DeviceConfig): Promise<IndoorCamera>;
isLedEnabled(): PropertyValue;
isMotionDetectionEnabled(): PropertyValue;
isPetDetectionEnabled(): PropertyValue;
isSoundDetectionEnabled(): PropertyValue;
isPetDetected(): boolean;
isSoundDetected(): boolean;
isCryingDetected(): boolean;
processPushNotification(station: Station, message: PushMessage, eventDurationSeconds: number): void;
destroy(): void;
}
export declare class DoorbellCamera extends Camera {
protected voices: Voices;
protected constructor(api: HTTPApi, device: DeviceListResponse, voices: Voices, deviceConfig: DeviceConfig);
static getInstance(api: HTTPApi, device: DeviceListResponse, deviceConfig: DeviceConfig): Promise<DoorbellCamera>;
private loadMetadataVoiceStates;
getVoiceName(id: number): string;
getVoices(): Voices;
getPropertiesMetadata(hidden?: boolean): IndexedProperty;
isRinging(): boolean;
protected handlePropertyChange(metadata: PropertyMetadataAny, oldValue: PropertyValue, newValue: PropertyValue): void;
processPushNotification(station: Station, message: PushMessage, eventDurationSeconds: number): void;
}
export declare class WiredDoorbellCamera extends DoorbellCamera {
static getInstance(api: HTTPApi, device: DeviceListResponse, deviceConfig: DeviceConfig): Promise<WiredDoorbellCamera>;
isLedEnabled(): PropertyValue;
isAutoNightVisionEnabled(): PropertyValue;
isMotionDetectionEnabled(): PropertyValue;
}
export declare class BatteryDoorbellCamera extends DoorbellCamera {
static getInstance(api: HTTPApi, device: DeviceListResponse, deviceConfig: DeviceConfig): Promise<BatteryDoorbellCamera>;
isLedEnabled(): PropertyValue;
}
export declare class FloodlightCamera extends Camera {
static getInstance(api: HTTPApi, device: DeviceListResponse, deviceConfig: DeviceConfig): Promise<FloodlightCamera>;
isLedEnabled(): PropertyValue;
isMotionDetectionEnabled(): PropertyValue;
protected convertRawPropertyValue(property: PropertyMetadataAny, value: string): PropertyValue;
processPushNotification(station: Station, message: PushMessage, eventDurationSeconds: number): void;
}
export declare class WallLightCam extends Camera {
static getInstance(api: HTTPApi, device: DeviceListResponse, deviceConfig: DeviceConfig): Promise<WallLightCam>;
isLedEnabled(): PropertyValue;
isMotionDetectionEnabled(): PropertyValue;
protected convertRawPropertyValue(property: PropertyMetadataAny, value: string): PropertyValue;
getPropertiesMetadata(hidden?: boolean): IndexedProperty;
processPushNotification(station: Station, message: PushMessage, eventDurationSeconds: number): void;
}
export declare class GarageCamera extends Camera {
static getInstance(api: HTTPApi, device: DeviceListResponse, deviceConfig: DeviceConfig): Promise<GarageCamera>;
isLedEnabled(): PropertyValue;
isMotionDetectionEnabled(): PropertyValue;
protected convertRawPropertyValue(property: PropertyMetadataAny, value: string): PropertyValue;
processPushNotification(station: Station, message: PushMessage, eventDurationSeconds: number): void;
}
export declare class Sensor extends Device {
static getInstance(api: HTTPApi, device: DeviceListResponse, deviceConfig: DeviceConfig): Promise<Sensor>;
getStateChannel(): string;
getState(): PropertyValue;
}
export declare class EntrySensor extends Sensor {
static getInstance(api: HTTPApi, device: DeviceListResponse, deviceConfig: DeviceConfig): Promise<EntrySensor>;
isSensorOpen(): PropertyValue;
getSensorChangeTime(): PropertyValue;
isBatteryLow(): PropertyValue;
processPushNotification(station: Station, message: PushMessage, eventDurationSeconds: number): void;
protected handlePropertyChange(metadata: PropertyMetadataAny, oldValue: PropertyValue, newValue: PropertyValue): void;
}
export declare class MotionSensor extends Sensor {
static readonly MOTION_COOLDOWN_MS = 120000;
protected constructor(api: HTTPApi, device: DeviceListResponse, deviceConfig: DeviceConfig);
static getInstance(api: HTTPApi, device: DeviceListResponse, deviceConfig: DeviceConfig): Promise<MotionSensor>;
isMotionDetected(): boolean;
getMotionSensorPIREvent(): PropertyValue;
isBatteryLow(): PropertyValue;
protected handlePropertyChange(metadata: PropertyMetadataAny, oldValue: PropertyValue, newValue: PropertyValue): void;
processPushNotification(station: Station, message: PushMessage, eventDurationSeconds: number): void;
}
export declare class Lock extends Device {
static readonly VERSION_CODE_SMART_LOCK = 3;
static readonly VERSION_CODE_LOCKV12 = 18;
static getInstance(api: HTTPApi, device: DeviceListResponse, deviceConfig: DeviceConfig): Promise<Lock>;
getStateChannel(): string;
protected handlePropertyChange(metadata: PropertyMetadataAny, oldValue: PropertyValue, newValue: PropertyValue): void;
getState(): PropertyValue;
getBatteryValue(): PropertyValue;
getWifiRssi(): PropertyValue;
isLocked(): PropertyValue;
getLockStatus(): PropertyValue;
static encodeESLCmdOnOff(short_user_id: number, nickname: string, lock: boolean): Buffer;
static encodeESLCmdQueryStatus(admin_user_id: string): Buffer;
processPushNotification(station: Station, message: PushMessage, eventDurationSeconds: number): void;
processMQTTNotification(message: DeviceSmartLockNotifyData, eventDurationSeconds: number): void;
private processNotification;
private static getCurrentTimeInSeconds;
private static getUInt8Buffer;
private static getUint16LEBuffer;
private static getUint16BEBuffer;
static encodeCmdStatus(user_id: string): Buffer;
static encodeCmdUnlock(short_user_id: string, value: number, username: string): Buffer;
static encodeCmdCalibrate(user_id: string): Buffer;
static encodeCmdAddUser(short_user_id: string, passcode: string, username: string, schedule?: Schedule, user_permission?: number): Buffer;
static encodeCmdAddTemporaryUser(schedule?: Schedule, unlimited?: boolean): Buffer;
static encodeCmdDeleteTemporaryUser(password_id: string): Buffer;
static encodeCmdDeleteUser(short_user_id: string): Buffer;
static encodeCmdVerifyPw(password: string): Buffer;
static encodeCmdQueryLockRecord(index: number): Buffer;
static encodeCmdQueryUser(short_user_id: string): Buffer;
static encodeCmdQueryPassword(password_id: string): Buffer;
static encodeCmdModifyPassword(password_id: string, passcode: string): Buffer;
static encodeCmdUpdateSchedule(short_user_id: string, schedule: Schedule): Buffer;
static encodeCmdModifyUsername(username: string, password_id: string): Buffer;
static encodeCmdGetLockParam(user_id: string): Buffer;
static encodeCmdSetLockParamAutoLock(enabled: boolean, lockTimeSeconds: number): Buffer;
private static hexTime;
static encodeCmdSetLockParamAutoLockSchedule(enabled: boolean, schedule_start: string, schedule_end: string): Buffer;
static encodeCmdSetLockParamOneTouchLock(enabled: boolean): Buffer;
static encodeCmdSetLockParamWrongTryProtect(enabled: boolean, lockdownTime: number, attempts: number): Buffer;
static encodeCmdSetLockParamScramblePasscode(enabled: boolean): Buffer;
static encodeCmdSetLockParamSound(value: number): Buffer;
protected convertRawPropertyValue(property: PropertyMetadataAny, value: string): PropertyValue;
static encodeCmdSmartLockUnlock(adminUserId: string, lock: boolean, username: string, shortUserId: string): Buffer;
static encodeCmdSmartLockCalibrate(adminUserId: string): Buffer;
static encodeCmdSetSmartLockParamWrongTryProtect(adminUserId: string, enabled: boolean, attempts: number, lockdownTime: number): Buffer;
private static hexTimeSmartLock;
static encodeCmdSetSmartLockParamAutoLock(adminUserId: string, enabled: boolean, lockTimeSeconds: number, schedule: boolean, scheduleStart: string, scheduleEnd: string): Buffer;
static encodeCmdSetSmartLockParamOneTouchLock(adminUserId: string, enabled: boolean): Buffer;
static encodeCmdSetSmartLockParamScramblePasscode(adminUserId: string, enabled: boolean): Buffer;
static encodeCmdSetSmartLockParamSound(adminUserId: string, value: number): Buffer;
static encodeCmdSmartLockAddUser(adminUserId: string, shortUserId: string, passcode: string, username: string, schedule?: Schedule, userPermission?: number): Buffer;
static encodeCmdSmartLockDeleteUser(adminUserId: string, shortUserId: string): Buffer;
static encodeCmdSmartLockUpdateSchedule(adminUserId: string, shortUserId: string, username: string, schedule: Schedule, userPermission?: number): Buffer;
static encodeCmdSmartLockModifyPassword(adminUserId: string, passwordId: string, passcode: string): Buffer;
static encodeCmdSmartLockGetUserList(adminUserId: string): Buffer;
static encodeCmdSmartLockStatus(adminUserId: string): Buffer;
static encodeCmdSmartLockGetParams(adminUserId: string): Buffer;
}
export declare class LockKeypad extends Device {
static getInstance(api: HTTPApi, device: DeviceListResponse, deviceConfig: DeviceConfig): Promise<LockKeypad>;
getStateChannel(): string;
}
export declare class Keypad extends Device {
static getInstance(api: HTTPApi, device: DeviceListResponse, deviceConfig: DeviceConfig): Promise<Keypad>;
getStateChannel(): string;
getState(): PropertyValue;
isBatteryLow(): PropertyValue;
isBatteryCharging(): PropertyValue;
protected convertRawPropertyValue(property: PropertyMetadataAny, value: string): PropertyValue;
}
export declare class SmartSafe extends Device {
static readonly IV = "052E19EB3F880512E99EBB684D4DC1FE";
static readonly DATA_HEADER: number[];
static readonly VERSION_CODE = 1;
static readonly PUSH_NOTIFICATION_POSITION: {
[index: string]: number;
};
static getInstance(api: HTTPApi, device: DeviceListResponse, deviceConfig: DeviceConfig): Promise<SmartSafe>;
getStateChannel(): string;
private static getCurrentTimeInSeconds;
private static getUInt8Buffer;
private static getUint16LEBuffer;
private static encodeCmdSingleUInt8;
static encodeCmdWrongTryProtect(user_id: string, enabled: boolean, attempts: number, lockdownTime: number): Buffer;
static encodeCmdLeftOpenAlarm(user_id: string, enabled: boolean, duration: number): Buffer;
static encodeCmdDualUnlock(user_id: string, enabled: boolean): Buffer;
static encodeCmdScramblePIN(user_id: string, enabled: boolean): Buffer;
static encodeCmdPowerSave(user_id: string, enabled: boolean): Buffer;
static encodeCmdInteriorBrightness(user_id: string, interiorBrightness: number, duration: number): Buffer;
static encodeCmdTamperAlarm(user_id: string, option: number): Buffer;
static encodeCmdRemoteUnlock(user_id: string, option: number): Buffer;
static encodeCmdAlertVolume(user_id: string, volume: number): Buffer;
static encodeCmdPromptVolume(user_id: string, volume: number): Buffer;
static encodeCmdPushNotification(user_id: string, modes: number): Buffer;
static encodeCmdUnlock(user_id: string): Buffer;
static encodeCmdVerifyPIN(user_id: string, pin: string): Buffer;
protected convertRawPropertyValue(property: PropertyMetadataAny, value: string): PropertyValue;
shakeEvent(event: number, eventDurationSeconds: number): void;
alarm911Event(event: number, eventDurationSeconds: number): void;
jammedEvent(eventDurationSeconds: number): void;
lowBatteryEvent(eventDurationSeconds: number): void;
wrongTryProtectAlarmEvent(eventDurationSeconds: number): void;
processPushNotification(station: Station, message: PushMessage, eventDurationSeconds: number): void;
protected handlePropertyChange(metadata: PropertyMetadataAny, oldValue: PropertyValue, newValue: PropertyValue): void;
getState(): PropertyValue;
getBatteryValue(): PropertyValue;
getWifiRssi(): PropertyValue;
isLocked(): boolean;
}
export declare class Tracker extends Device {
static getInstance(api: HTTPApi, device: DeviceListResponse, deviceConfig: DeviceConfig): Promise<Tracker>;
getStateChannel(): string;
protected convertRawPropertyValue(property: PropertyMetadataAny, value: string): PropertyValue;
setFindPhone(value: boolean): Promise<boolean>;
setLeftBehindAlarm(value: boolean): Promise<boolean>;
setTrackerType(value: TrackerType): Promise<boolean>;
}
export declare class DoorbellLock extends DoorbellCamera {
static getInstance(api: HTTPApi, device: DeviceListResponse, deviceConfig: DeviceConfig): Promise<DoorbellLock>;
getStateChannel(): string;
protected handlePropertyChange(metadata: PropertyMetadataAny, oldValue: PropertyValue, newValue: PropertyValue): void;
protected convertRawPropertyValue(property: PropertyMetadataAny, value: string): PropertyValue;
getState(): PropertyValue;
getBatteryValue(): PropertyValue;
getWifiRssi(): PropertyValue;
isLocked(): PropertyValue;
getLockStatus(): PropertyValue;
processPushNotification(station: Station, message: PushMessage, eventDurationSeconds: number): void;
}
export declare class SmartDrop extends Camera {
static getInstance(api: HTTPApi, device: DeviceListResponse, deviceConfig: DeviceConfig): Promise<SmartDrop>;
getStateChannel(): string;
processPushNotification(station: Station, message: PushMessage, eventDurationSeconds: number): void;
protected handlePropertyChange(metadata: PropertyMetadataAny, oldValue: PropertyValue, newValue: PropertyValue): void;
}
export declare class UnknownDevice extends Device {
static getInstance(api: HTTPApi, device: DeviceListResponse, deviceConfig: DeviceConfig): Promise<UnknownDevice>;
getStateChannel(): string;
}

4306
build/http/device.js Normal file

File diff suppressed because it is too large Load Diff

1
build/http/device.js.map Normal file

File diff suppressed because one or more lines are too long

73
build/http/error.d.ts vendored Normal file
View File

@ -0,0 +1,73 @@
import { BaseError, Jsonable } from "../error";
export declare class InvalidPropertyError extends BaseError {
constructor(message: string, options?: {
cause?: Error;
context?: Jsonable;
});
}
export declare class LivestreamAlreadyRunningError extends BaseError {
constructor(message: string, options?: {
cause?: Error;
context?: Jsonable;
});
}
export declare class LivestreamNotRunningError extends BaseError {
constructor(message: string, options?: {
cause?: Error;
context?: Jsonable;
});
}
export declare class PropertyNotSupportedError extends BaseError {
constructor(message: string, options?: {
cause?: Error;
context?: Jsonable;
});
}
export declare class ApiResponseCodeError extends BaseError {
constructor(message: string, options?: {
cause?: Error;
context?: Jsonable;
});
}
export declare class ApiInvalidResponseError extends BaseError {
constructor(message: string, options?: {
cause?: Error;
context?: Jsonable;
});
}
export declare class ApiHTTPResponseCodeError extends BaseError {
constructor(message: string, options?: {
cause?: Error;
context?: Jsonable;
});
}
export declare class ApiGenericError extends BaseError {
constructor(message: string, options?: {
cause?: Error;
context?: Jsonable;
});
}
export declare class ApiBaseLoadError extends BaseError {
constructor(message: string, options?: {
cause?: Error;
context?: Jsonable;
});
}
export declare class ApiRequestError extends BaseError {
constructor(message: string, options?: {
cause?: Error;
context?: Jsonable;
});
}
export declare class ImageBaseCodeError extends BaseError {
constructor(message: string, options?: {
cause?: Error;
context?: Jsonable;
});
}
export declare class ImageSeedError extends BaseError {
constructor(message: string, options?: {
cause?: Error;
context?: Jsonable;
});
}

101
build/http/error.js Normal file
View File

@ -0,0 +1,101 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ImageSeedError = exports.ImageBaseCodeError = exports.ApiRequestError = exports.ApiBaseLoadError = exports.ApiGenericError = exports.ApiHTTPResponseCodeError = exports.ApiInvalidResponseError = exports.ApiResponseCodeError = exports.PropertyNotSupportedError = exports.LivestreamNotRunningError = exports.LivestreamAlreadyRunningError = exports.InvalidPropertyError = void 0;
const error_1 = require("../error");
class InvalidPropertyError extends error_1.BaseError {
constructor(message, options = {}) {
super(message, options);
Object.setPrototypeOf(this, new.target.prototype);
this.name = InvalidPropertyError.name;
}
}
exports.InvalidPropertyError = InvalidPropertyError;
class LivestreamAlreadyRunningError extends error_1.BaseError {
constructor(message, options = {}) {
super(message, options);
Object.setPrototypeOf(this, new.target.prototype);
this.name = LivestreamAlreadyRunningError.name;
}
}
exports.LivestreamAlreadyRunningError = LivestreamAlreadyRunningError;
class LivestreamNotRunningError extends error_1.BaseError {
constructor(message, options = {}) {
super(message, options);
Object.setPrototypeOf(this, new.target.prototype);
this.name = LivestreamNotRunningError.name;
}
}
exports.LivestreamNotRunningError = LivestreamNotRunningError;
class PropertyNotSupportedError extends error_1.BaseError {
constructor(message, options = {}) {
super(message, options);
Object.setPrototypeOf(this, new.target.prototype);
this.name = PropertyNotSupportedError.name;
}
}
exports.PropertyNotSupportedError = PropertyNotSupportedError;
class ApiResponseCodeError extends error_1.BaseError {
constructor(message, options = {}) {
super(message, options);
Object.setPrototypeOf(this, new.target.prototype);
this.name = ApiResponseCodeError.name;
}
}
exports.ApiResponseCodeError = ApiResponseCodeError;
class ApiInvalidResponseError extends error_1.BaseError {
constructor(message, options = {}) {
super(message, options);
Object.setPrototypeOf(this, new.target.prototype);
this.name = ApiInvalidResponseError.name;
}
}
exports.ApiInvalidResponseError = ApiInvalidResponseError;
class ApiHTTPResponseCodeError extends error_1.BaseError {
constructor(message, options = {}) {
super(message, options);
Object.setPrototypeOf(this, new.target.prototype);
this.name = ApiHTTPResponseCodeError.name;
}
}
exports.ApiHTTPResponseCodeError = ApiHTTPResponseCodeError;
class ApiGenericError extends error_1.BaseError {
constructor(message, options = {}) {
super(message, options);
Object.setPrototypeOf(this, new.target.prototype);
this.name = ApiGenericError.name;
}
}
exports.ApiGenericError = ApiGenericError;
class ApiBaseLoadError extends error_1.BaseError {
constructor(message, options = {}) {
super(message, options);
Object.setPrototypeOf(this, new.target.prototype);
this.name = ApiBaseLoadError.name;
}
}
exports.ApiBaseLoadError = ApiBaseLoadError;
class ApiRequestError extends error_1.BaseError {
constructor(message, options = {}) {
super(message, options);
Object.setPrototypeOf(this, new.target.prototype);
this.name = ApiRequestError.name;
}
}
exports.ApiRequestError = ApiRequestError;
class ImageBaseCodeError extends error_1.BaseError {
constructor(message, options = {}) {
super(message, options);
Object.setPrototypeOf(this, new.target.prototype);
this.name = ImageBaseCodeError.name;
}
}
exports.ImageBaseCodeError = ImageBaseCodeError;
class ImageSeedError extends error_1.BaseError {
constructor(message, options = {}) {
super(message, options);
Object.setPrototypeOf(this, new.target.prototype);
this.name = ImageSeedError.name;
}
}
exports.ImageSeedError = ImageSeedError;
//# sourceMappingURL=error.js.map

1
build/http/error.js.map Normal file
View File

@ -0,0 +1 @@
{"version":3,"file":"error.js","sourceRoot":"","sources":["../../src/http/error.ts"],"names":[],"mappings":"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"}

10
build/http/index.d.ts vendored Normal file
View File

@ -0,0 +1,10 @@
export * from "./api";
export * from "./cache";
export * from "./device";
export * from "./interfaces";
export * from "./models";
export * from "./parameter";
export * from "./station";
export * from "./types";
export * from "./error";
export { isGreaterEqualMinVersion, getAbsoluteFilePath } from "./utils";

30
build/http/index.js Normal file
View File

@ -0,0 +1,30 @@
"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 __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getAbsoluteFilePath = exports.isGreaterEqualMinVersion = void 0;
__exportStar(require("./api"), exports);
__exportStar(require("./cache"), exports);
__exportStar(require("./device"), exports);
__exportStar(require("./interfaces"), exports);
__exportStar(require("./models"), exports);
__exportStar(require("./parameter"), exports);
__exportStar(require("./station"), exports);
__exportStar(require("./types"), exports);
__exportStar(require("./error"), exports);
var utils_1 = require("./utils");
Object.defineProperty(exports, "isGreaterEqualMinVersion", { enumerable: true, get: function () { return utils_1.isGreaterEqualMinVersion; } });
Object.defineProperty(exports, "getAbsoluteFilePath", { enumerable: true, get: function () { return utils_1.getAbsoluteFilePath; } });
//# sourceMappingURL=index.js.map

1
build/http/index.js.map Normal file
View File

@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/http/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,wCAAsB;AACtB,0CAAwB;AACxB,2CAAyB;AACzB,+CAA6B;AAC7B,2CAAyB;AACzB,8CAA4B;AAC5B,4CAA0B;AAC1B,0CAAwB;AACxB,0CAAwB;AACxB,iCAAuE;AAA9D,iHAAA,wBAAwB,OAAA;AAAE,4GAAA,mBAAmB,OAAA"}

241
build/http/interfaces.d.ts vendored Normal file
View File

@ -0,0 +1,241 @@
import { Readable } from "stream";
import type { Method } from "got" with {
"resolution-mode": "import"
};
import type { ImageFileExtension } from "image-type" with {
"resolution-mode": "import"
};
import { DatabaseCountByDate, DatabaseQueryLatestInfo, DatabaseQueryLocal, StreamMetadata } from "../p2p/interfaces";
import { CommandResult, StorageInfoBodyHB3 } from "../p2p/models";
import { AlarmEvent, DatabaseReturnCode, SmartSafeAlarm911Event, SmartSafeShakeAlarmEvent, TFCardStatus } from "../p2p/types";
import { Camera, Device } from "./device";
import { Cipher, Voice, Invite, DeviceListResponse, StationListResponse, HouseListResponse } from "./models";
import { Station } from "./station";
import { CommandName, PropertyName, SourceType } from "./types";
import { TalkbackStream } from "../p2p/talkback";
export type PropertyValue = number | boolean | string | object;
export interface PropertyValues {
[index: string]: PropertyValue;
}
export interface DeviceConfig {
simultaneousDetections?: boolean;
}
export interface RawValue {
value: string;
source: SourceType;
}
export interface RawValues {
[index: number]: RawValue;
}
export interface Devices {
[index: string]: Device;
}
export interface Cameras {
[index: string]: Camera;
}
export interface Stations {
[index: string]: Station;
}
export interface Houses {
[index: string]: HouseListResponse;
}
export interface Hubs {
[index: string]: StationListResponse;
}
export interface FullDevices {
[index: string]: DeviceListResponse;
}
export interface Ciphers {
[index: number]: Cipher;
}
export interface Voices {
[index: number]: Voice;
}
export interface Invites {
[index: number]: Invite;
}
export interface HTTPApiRequest {
method: Method;
endpoint: string | URL;
responseType?: "text" | "json" | "buffer";
data?: any;
}
export type PropertyMetadataType = "number" | "boolean" | "string" | "object";
export interface PropertyMetadataAny {
key: number | string;
name: PropertyName;
type: PropertyMetadataType;
default?: any;
readable: boolean;
writeable: boolean;
description?: string;
label?: string;
commandId?: number;
}
export interface PropertyMetadataNumeric extends PropertyMetadataAny {
type: "number";
min?: number;
max?: number;
steps?: number;
default?: number;
states?: Record<number, string>;
unit?: string;
}
export interface PropertyMetadataBoolean extends PropertyMetadataAny {
type: "boolean";
default?: boolean;
}
export interface PropertyMetadataString extends PropertyMetadataAny {
type: "string";
minLength?: number;
maxLength?: number;
default?: string;
format?: RegExp;
}
export interface PropertyMetadataObject extends PropertyMetadataAny {
type: "object";
isValidObject?: (obj: any) => boolean;
default?: any;
}
export interface IndexedProperty {
[index: string]: PropertyMetadataAny;
}
export interface Properties {
[index: number]: IndexedProperty;
}
export interface Commands {
[index: number]: Array<CommandName>;
}
export interface HTTPApiPersistentData {
user_id: string;
email: string;
nick_name: string;
device_public_keys: {
[index: string]: string;
};
clientPrivateKey: string;
serverPublicKey: string;
}
export interface CaptchaOptions {
captchaCode: string;
captchaId: string;
}
export interface LoginOptions {
verifyCode?: string;
captcha?: CaptchaOptions;
force: boolean;
}
export interface Schedule {
startDateTime?: Date;
endDateTime?: Date;
week?: {
monday: boolean;
tuesday: boolean;
wednesday: boolean;
thursday: boolean;
friday: boolean;
saturday: boolean;
sunday: boolean;
};
}
export interface ImageType {
ext: ImageFileExtension | "unknown";
mime: string;
}
export interface Picture {
data: Buffer;
type: ImageType;
}
export interface HTTPApiEvents {
"devices": (devices: FullDevices) => void;
"hubs": (hubs: Hubs) => void;
"houses": (houses: Houses) => void;
"connect": () => void;
"close": () => void;
"connection error": (error: Error) => void;
"tfa request": () => void;
"captcha request": (id: string, captcha: string) => void;
"auth token invalidated": () => void;
}
export interface StationEvents {
"connect": (station: Station) => void;
"close": (station: Station) => void;
"connection error": (station: Station, error: Error) => void;
"raw device property changed": (deviceSN: string, params: RawValues) => void;
"property changed": (station: Station, name: string, value: PropertyValue, ready: boolean) => void;
"raw property changed": (station: Station, type: number, value: string) => void;
"command result": (station: Station, result: CommandResult) => void;
"download start": (station: Station, channel: number, metadata: StreamMetadata, videostream: Readable, audiostream: Readable) => void;
"download finish": (station: Station, channel: number) => void;
"livestream start": (station: Station, channel: number, metadata: StreamMetadata, videostream: Readable, audiostream: Readable) => void;
"livestream stop": (station: Station, channel: number) => void;
"livestream error": (station: Station, channel: number, error: Error) => void;
"rtsp livestream start": (station: Station, channel: number) => void;
"rtsp livestream stop": (station: Station, channel: number) => void;
"rtsp url": (station: Station, channel: number, value: string) => void;
"guard mode": (station: Station, guardMode: number) => void;
"current mode": (station: Station, currentMode: number) => void;
"alarm event": (station: Station, alarmEvent: AlarmEvent) => void;
"ready": (station: Station) => void;
"runtime state": (station: Station, channel: number, batteryLevel: number, temperature: number) => void;
"charging state": (station: Station, channel: number, chargeType: number, batteryLevel: number) => void;
"wifi rssi": (station: Station, channel: number, rssi: number) => void;
"floodlight manual switch": (station: Station, channel: number, enabled: boolean) => void;
"alarm delay event": (station: Station, alarmDelayEvent: AlarmEvent, alarmDelay: number) => void;
"alarm arm delay event": (station: Station, armDelay: number) => void;
"alarm armed event": (station: Station) => void;
"talkback started": (station: Station, channel: number, talkbackStream: TalkbackStream) => void;
"talkback stopped": (station: Station, channel: number) => void;
"talkback error": (station: Station, channel: number, error: Error) => void;
"secondary command result": (station: Station, result: CommandResult) => void;
"device shake alarm": (deviceSN: string, event: SmartSafeShakeAlarmEvent) => void;
"device 911 alarm": (deviceSN: string, event: SmartSafeAlarm911Event) => void;
"device jammed": (deviceSN: string) => void;
"device low battery": (deviceSN: string) => void;
"device wrong try-protect alarm": (deviceSN: string) => void;
"device pin verified": (deviceSN: string, successfull: boolean) => void;
"sd info ex": (station: Station, sdStatus: TFCardStatus, sdCapacity: number, sdCapacityAvailable: number) => void;
"image download": (station: Station, file: string, image: Buffer) => void;
"database query latest": (station: Station, returnCode: DatabaseReturnCode, data: Array<DatabaseQueryLatestInfo>) => void;
"database query local": (station: Station, returnCode: DatabaseReturnCode, data: Array<DatabaseQueryLocal>) => void;
"database count by date": (station: Station, returnCode: DatabaseReturnCode, data: Array<DatabaseCountByDate>) => void;
"database delete": (station: Station, returnCode: DatabaseReturnCode, failedIds: Array<unknown>) => void;
"sensor status": (station: Station, channel: number, status: number) => void;
"garage door status": (station: Station, channel: number, doorId: number, status: number) => void;
"storage info hb3": (station: Station, channel: number, storageInfo: StorageInfoBodyHB3) => void;
}
export interface DeviceEvents {
"property changed": (device: Device, name: string, value: PropertyValue, ready: boolean) => void;
"raw property changed": (device: Device, type: number, value: string) => void;
"motion detected": (device: Device, state: boolean) => void;
"person detected": (device: Device, state: boolean, person: string) => void;
"pet detected": (device: Device, state: boolean) => void;
"sound detected": (device: Device, state: boolean) => void;
"crying detected": (device: Device, state: boolean) => void;
"vehicle detected": (device: Device, state: boolean) => void;
"dog detected": (device: Device, state: boolean) => void;
"dog lick detected": (device: Device, state: boolean) => void;
"dog poop detected": (device: Device, state: boolean) => void;
"stranger person detected": (device: Device, state: boolean) => void;
"rings": (device: Device, state: boolean) => void;
"locked": (device: Device, state: boolean) => void;
"open": (device: Device, state: boolean) => void;
"ready": (device: Device) => void;
"package delivered": (device: Device, state: boolean) => void;
"package stranded": (device: Device, state: boolean) => void;
"package taken": (device: Device, state: boolean) => void;
"someone loitering": (device: Device, state: boolean) => void;
"radar motion detected": (device: Device, state: boolean) => void;
"911 alarm": (device: Device, state: boolean, detail: SmartSafeAlarm911Event) => void;
"shake alarm": (device: Device, state: boolean, detail: SmartSafeShakeAlarmEvent) => void;
"wrong try-protect alarm": (device: Device, state: boolean) => void;
"long time not close": (device: Device, state: boolean) => void;
"low battery": (device: Device, state: boolean) => void;
"jammed": (device: Device, state: boolean) => void;
"tampering": (device: Device, state: boolean) => void;
"low temperature": (device: Device, state: boolean) => void;
"high temperature": (device: Device, state: boolean) => void;
"pin incorrect": (device: Device, state: boolean) => void;
"lid stuck": (device: Device, state: boolean) => void;
"battery fully charged": (device: Device, state: boolean) => void;
}

3
build/http/interfaces.js Normal file
View File

@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=interfaces.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"interfaces.js","sourceRoot":"","sources":["../../src/http/interfaces.ts"],"names":[],"mappings":""}

608
build/http/models.d.ts vendored Normal file
View File

@ -0,0 +1,608 @@
import { UserPasswordType, UserType } from "./types";
export interface ApiResponse {
status: number;
statusText: string;
data: any;
headers: any;
}
export interface ResultResponse {
code: number;
msg: string;
data?: any;
outline?: any;
}
export interface LoginResultResponse {
user_id: string;
email: string;
nick_name: string;
auth_token: string;
token_expires_at: number;
avatar: string;
invitation_code: string;
inviter_code: string;
verify_code_url: string;
mac_addr: string;
domain: string;
ab_code: string;
geo_key: string;
privilege: number;
phone: string;
phone_code: string;
server_secret_info: {
public_key: string;
} | null;
params: Array<{
param_type: number;
param_value: string;
}> | null;
trust_list: Array<TrustDevice>;
}
export interface CaptchaResponse {
captcha_id: string;
item: string;
}
export interface LoginRequest {
ab: string;
client_secret_info: {
public_key: string;
};
enc: number;
email: string;
password: string;
time_zone: number;
verify_code?: string;
captcha_id?: string;
answer?: string;
transaction: string;
}
export interface Member {
family_id: number;
station_sn: string;
admin_user_id: string;
member_user_id: string;
short_user_id: string;
member_type: number;
permissions: number;
member_nick: string;
action_user_id: string;
fence_state: number;
extra: string;
member_avatar: string;
house_id: string;
create_time: number;
update_time: number;
status: number;
email: string;
nick_name: string;
avatar: string;
action_user_email: string;
action_user_name: string;
}
export interface StationListDevice {
device_id: number;
is_init_complete: boolean;
device_sn: string;
device_name: string;
device_model: string;
time_zone: string;
device_type: number;
device_channel: number;
station_sn: string;
schedule: string;
schedulex: string;
wifi_mac: string;
sub1g_mac: string;
main_sw_version: string;
main_hw_version: string;
sec_sw_version: string;
sec_hw_version: string;
sector_id: number;
event_num: number;
wifi_ssid: string;
ip_addr: string;
main_sw_time: number;
sec_sw_time: number;
bind_time: number;
local_ip: string;
language: string;
sku_number: string;
lot_number: string;
cpu_id: string;
create_time: number;
update_time: number;
status: number;
}
export interface StationListResponse {
readonly [index: string]: unknown;
station_id: number;
station_sn: string;
station_name: string;
station_model: string;
time_zone: string;
wifi_ssid: string;
ip_addr: string;
wifi_mac: string;
sub1g_mac: string;
main_sw_version: string;
main_hw_version: string;
sec_sw_version: string;
sec_hw_version: string;
volume: string;
main_sw_time: number;
sec_sw_time: number;
bt_mac: string;
setup_code: string;
setup_id: string;
device_type: number;
event_num: number;
sku_number: string;
lot_number: string;
create_time: number;
update_time: number;
status: number;
station_status: number;
status_change_time: number;
p2p_did: string;
push_did: string;
p2p_license: string;
push_license: string;
ndt_did: string;
ndt_license: string;
wakeup_flag: number;
p2p_conn: string;
app_conn: string;
wipn_enc_dec_key: string;
wipn_ndt_aes128key: string;
query_server_did: string;
prefix: string;
wakeup_key: string;
member: Member;
params: Array<ParameterResponse>;
devices: Array<StationListDevice>;
sensor_info: null;
is_init_complete: boolean;
virtual_version: string;
house_id?: string;
}
export interface ParameterResponse {
param_id: number;
station_sn: string;
param_type: number;
param_value: string;
create_time: number;
update_time: number;
status: number;
}
export interface DeviceResponse {
device_id: number;
is_init_complete: boolean;
device_sn: string;
device_name: string;
device_model: string;
time_zone: string;
device_type: number;
device_channel: number;
station_sn: string;
schedule: string;
schedulex: string;
wifi_mac: string;
sub1g_mac: string;
main_sw_version: string;
main_hw_version: string;
sec_sw_version: string;
sec_hw_version: string;
sector_id: number;
event_num: number;
wifi_ssid: string;
ip_addr: string;
main_sw_time: number;
sec_sw_time: number;
bind_time: number;
cover_path: string;
cover_time: number;
local_ip: string;
language: string;
sku_number: string;
lot_number: string;
create_time: number;
update_time: number;
status: number;
}
export interface DeviceRequest {
device_sn: string;
num: number;
orderby: string;
page: number;
station_sn: string;
}
export interface DeviceListResponse {
readonly [index: string]: unknown;
device_id: number;
is_init_complete: boolean;
device_sn: string;
device_name: string;
device_model: string;
time_zone: string;
device_type: number;
device_channel: number;
station_sn: string;
schedule: string;
schedulex: string;
wifi_mac: string;
sub1g_mac: string;
main_sw_version: string;
main_hw_version: string;
sec_sw_version: string;
sec_hw_version: string;
sector_id: number;
event_num: number;
wifi_ssid: string;
ip_addr: string;
volume: string;
main_sw_time: number;
sec_sw_time: number;
bind_time: number;
bt_mac: string;
cover_path: string;
cover_time: number;
local_ip: string;
language: string;
sku_number: string;
lot_number: string;
cpu_id: string;
create_time: number;
update_time: number;
status: number;
svr_domain: string;
svr_port: number;
station_conn: {
station_sn: string;
station_name: string;
station_model: string;
main_sw_version: string;
main_hw_version: string;
p2p_did: string;
push_did: string;
ndt_did: string;
p2p_conn: string;
app_conn: string;
binded: false;
setup_code: string;
setup_id: string;
bt_mac: string;
wifi_mac: string;
dsk_key: string;
expiration: number;
};
family_num: number;
member: Member;
permission: any;
params: Array<ParameterResponse>;
pir_total: number;
pir_none: number;
pir_missing: number;
week_pir_total: number;
week_pir_none: number;
month_pir_total: number;
month_pir_none: number;
charging_days: number;
charing_total: number;
charging_reserve: number;
charging_missing: number;
battery_usage_last_week: number;
virtual_version: string;
relate_devices: any;
house_id?: string;
}
export interface DskKeyResponse {
enabled: boolean;
dsk_keys: Array<{
station_sn: string;
dsk_key: string;
expiration: number;
about_to_be_replaced: boolean;
}>;
}
export interface EventRecordResponse {
monitor_id: number;
transfer_monitor_id: number;
station_sn: string;
device_sn: string;
storage_type: number;
storage_path: string;
hevc_storage_path: string;
cloud_path: string;
frame_num: number;
thumb_path: string;
thumb_data: string;
start_time: number;
end_time: number;
cipher_id: number;
cipher_user_id: string;
has_human: number;
volume: string;
vision: number;
device_name: string;
device_type: number;
video_type: number;
extra: string;
user_range_id: number;
viewed: boolean;
create_time: number;
update_time: number;
status: number;
station_name: string;
p2p_did: string;
push_did: string;
p2p_license: string;
push_license: string;
ndt_did: string;
ndt_license: string;
wakeup_flag: number;
p2p_conn: string;
app_conn: string;
wipn_enc_dec_key: string;
wipn_ndt_aes128key: string;
query_server_did: string;
prefix: string;
wakeup_key: string;
ai_faces: Array<{
is_stranger: number;
face_url: string;
owner_id: string;
user_range_id: number;
}>;
is_favorite: boolean;
storage_alias: number;
}
export interface EventRecordRequest {
device_sn: string;
end_time: number;
id: number;
id_type: number;
is_favorite: boolean;
num: number;
pullup: boolean;
shared: boolean;
start_time: number;
station_sn: string;
storage: number;
}
export interface StreamRequest {
device_sn: string;
station_sn: string;
proto?: number;
}
export interface TrustDevice {
open_udid: string;
phone_model: string;
is_current_device: number;
}
export interface Cipher {
cipher_id: number;
user_id: string;
private_key: string;
}
export interface Voice {
voice_id: number;
user_id: string;
desc: string;
device_sn: string;
voice_link: string;
voice_type: number;
key_prefix: string;
}
export interface DeviceInvite {
device_sn: string;
checked: boolean;
}
export interface Invite {
invite_id: number;
station_sn: string;
email: string;
devices: Array<DeviceInvite>;
action_user_id: string;
member_nick: string;
member_type: number;
permissions: number;
create_time: number;
update_time: number;
status: number;
action_user_email: string;
action_user_nick: string;
}
export interface ConfirmInvite {
device_sns: Array<string>;
invite_id: number;
station_sn: string;
}
export interface SensorHistoryEntry {
trigger_time: number;
create_time: number;
status: string;
}
export interface HouseUser {
id: number;
house_id: string;
email: string;
avatar: string;
user_id: string;
admin_user_id: string;
state: string;
role_type: number;
}
export interface HouseDetail {
house_id: string;
house_name: string;
is_default: number;
id: number;
geofence_id: number;
address: string;
latitude: number;
longitude: number;
radius_range: number;
away_mode: number;
home_mode: number;
location_msg: number;
create_time: number;
house_users: Array<HouseUser>;
house_stations: any;
}
export interface HouseListResponse {
readonly [index: string]: unknown;
house_id: string;
user_id: string;
admin_user_id: string;
role_type: number;
house_name: string;
is_default: number;
geofence_id: number;
address: string;
latitude: number;
longitude: number;
radius_range: number;
location_msg: number;
create_time: number;
away_mode: number;
home_mode: number;
}
export interface HouseInviteListResponse {
readonly [index: string]: unknown;
id: number;
house_name: string;
action_user_nick: string;
action_user_email: string;
house_id: string;
email: string;
user_id: string;
role_type: number;
}
export interface ConfirmHouseInvite {
house_id: string;
invite_id: number;
is_inviter: number;
user_id: string;
}
export interface PassportProfileResponse {
user_id: string;
email: string;
nick_name: string;
avatar: string;
invitation_code: string;
inviter_code: string;
verify_code_url: string;
mac_addr: string;
country: {
id: number;
name: string;
code: string;
};
}
export interface StationSecuritySettings {
account_id: string;
count_down_alarm: StationSecuritySettingsDelayDetails;
count_down_arm: StationSecuritySettingsDelayDetails;
devices: StationSecuritySettingsDeviceDetails;
}
export interface StationSecuritySettingsDelayDetails {
account_id: string;
channel_list: number[];
delay_time: number;
}
export interface StationSecuritySettingsDeviceDetails {
action: number;
device_channel: number;
}
export interface SnoozeDetail {
snooze_time: number;
snooze_chime?: boolean;
snooze_motion?: boolean;
snooze_homebase?: boolean;
}
export interface RawSchedule {
endDay: string;
week: string;
startDay: string;
startTime: string;
endTime: string;
}
export interface UserPassword {
expiration_time: number;
is_permanent: number;
password: string;
password_id: string;
password_type: UserPasswordType;
name: string;
schedule: RawSchedule;
}
export interface User {
avatar: string;
password_list: Array<UserPassword>;
user_id: string;
short_user_id: string;
user_name: string;
user_type: UserType;
is_show: boolean;
}
export interface UsersResponse {
device_sn: string;
user_list: Array<User>;
}
export interface AddUserResponse {
user_id: string;
short_user_id: string;
}
export interface GarageDoorSensorsProperty {
cmd: number;
data: {
door_1: {
power: number;
mac_address: string;
version: string;
name: string;
sn: string;
playalarm: number;
ota: number;
needota: number;
};
door_2: {
power: number;
mac_address: string;
version: string;
name: string;
sn: string;
playalarm: number;
ota: number;
needota: number;
};
};
}
export interface FloodlightDetectionRangeT8425Property {
cur_mode: number;
test_mode: number;
mode0: Array<{
id: number;
sst: number;
}>;
mode1: Array<{
id: number;
sst: number;
}>;
mode2: Array<{
id: number;
sst: number;
}>;
}
export interface FloodlightLightSettingsBrightnessScheduleT8425Property {
sunset2rise: number;
longtitude: string;
latitude: string;
brightness: number;
schedule: Array<unknown>;
}
export interface FloodlightLightSettingsMotionT8425Property {
brightness: number;
enable: number;
mode: number;
time: number;
}

3
build/http/models.js Normal file
View File

@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=models.js.map

1
build/http/models.js.map Normal file
View File

@ -0,0 +1 @@
{"version":3,"file":"models.js","sourceRoot":"","sources":["../../src/http/models.ts"],"names":[],"mappings":""}

5
build/http/parameter.d.ts vendored Normal file
View File

@ -0,0 +1,5 @@
import { Category } from "typescript-logging-category-style";
export declare class ParameterHelper {
static readValue(serialNumber: string, type: number, value: string, log: Category): string | undefined;
static writeValue(type: number, value: string): string;
}

103
build/http/parameter.js Normal file
View File

@ -0,0 +1,103 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ParameterHelper = void 0;
const types_1 = require("../p2p/types");
const utils_1 = require("../p2p/utils");
const utils_2 = require("../utils");
const types_2 = require("./types");
const utils_3 = require("./utils");
const error_1 = require("../error");
class ParameterHelper {
static readValue(serialNumber, type, value, log) {
if (value) {
if (type === types_2.ParamType.SNOOZE_MODE ||
type === types_2.ParamType.CAMERA_MOTION_ZONES ||
type === types_1.CommandType.CMD_SET_DOORSENSOR_ALWAYS_OPEN_DELAY ||
type === types_1.CommandType.CMD_SET_DOORSENSOR_ALWAYS_OPEN ||
type === types_1.CommandType.ARM_DELAY_HOME ||
type === types_1.CommandType.ARM_DELAY_AWAY ||
type === types_1.CommandType.ARM_DELAY_CUS1 ||
type === types_1.CommandType.ARM_DELAY_CUS2 ||
type === types_1.CommandType.ARM_DELAY_CUS3 ||
type === types_1.CommandType.ARM_DELAY_OFF ||
type === types_1.CommandType.CELLULAR_INFO ||
type === types_1.CommandType.CMD_WALL_LIGHT_SETTINGS_MANUAL_COLORED_LIGHTING ||
type === types_1.CommandType.CMD_WALL_LIGHT_SETTINGS_SCHEDULE_COLORED_LIGHTING ||
type === types_1.CommandType.CMD_WALL_LIGHT_SETTINGS_MANUAL_COLORED_LIGHTING ||
type === types_1.CommandType.CMD_WALL_LIGHT_SETTINGS_COLORED_LIGHTING_COLORS ||
type === types_1.CommandType.CMD_WALL_LIGHT_SETTINGS_DYNAMIC_LIGHTING_THEMES ||
type === types_1.CommandType.CMD_INDOOR_DET_SET_ACTIVE_ZONE ||
type === types_1.CommandType.CMD_SET_PRIVACYPARAM ||
type === types_1.CommandType.CMD_BAT_DOORBELL_VIDEO_QUALITY2 ||
type === types_1.CommandType.CMD_BAT_DOORBELL_RECORD_QUALITY2 ||
type === types_1.CommandType.CMD_SET_CROSS_TRACKING_CAMERA_LIST ||
type === types_1.CommandType.CMD_SET_CROSS_TRACKING_GROUP_LIST ||
type === types_1.CommandType.CMD_FLOODLIGHT_SET_DETECTION_RANGE_T8425 ||
type === types_1.CommandType.CMD_SET_LIGHT_CTRL_BRIGHT_PIR_T8425 ||
type === types_1.CommandType.CMD_SET_LIGHT_CTRL_BRIGHT_SCH_T8425) {
if (typeof value === "string") {
const parsedValue = (0, utils_2.parseJSON)((0, utils_1.getNullTerminatedString)((0, utils_1.decodeBase64)(value), "utf-8"), log);
if (parsedValue === undefined) {
log.debug("Non-parsable parameter value received from eufy cloud. Will be ignored.", { serialNumber: serialNumber, type: type, value: value });
}
return parsedValue;
}
else {
return value; //return object
}
}
else if (type === types_1.CommandType.CMD_BAT_DOORBELL_SET_NOTIFICATION_MODE ||
type === types_1.CommandType.CMD_DOORBELL_DUAL_RADAR_WD_DETECTION_SENSITIVITY ||
type === types_1.CommandType.CMD_DOORBELL_DUAL_RADAR_WD_AUTO_RESPONSE ||
type === types_1.CommandType.CMD_DOORBELL_DUAL_PACKAGE_STRAND_TIME ||
type === types_1.CommandType.CMD_DOORBELL_DUAL_RING_AUTO_RESPONSE ||
type === types_1.CommandType.CMD_DOORBELL_DUAL_PACKAGE_GUARD_TIME ||
type === types_1.CommandType.CMD_DOORBELL_DUAL_RADAR_WD_DISTANCE ||
type === types_1.CommandType.CMD_DOORBELL_DUAL_RADAR_WD_TIME ||
type === types_1.CommandType.CMD_DOORBELL_DUAL_DELIVERY_GUARD_SWITCH ||
type === types_1.CommandType.CMD_DOORBELL_DUAL_PACKAGE_GUARD_VOICE ||
type === types_1.CommandType.CMD_CAMERA_GARAGE_DOOR_SENSORS ||
type === types_1.CommandType.CMD_MOTION_SET_LEAVING_REACTIONS) {
if (typeof value === "string") {
const parsedValue = (0, utils_2.parseJSON)(value, log);
if (parsedValue === undefined) {
log.debug("Non-parsable parameter value received from eufy cloud. Will be ignored.", { serialNumber: serialNumber, type: type, value: value });
}
return parsedValue;
}
else {
return value; //return object
}
}
else if (type === types_1.TrackerCommandType.COMMAND_NEW_LOCATION ||
type === types_1.TrackerCommandType.LOCATION_NEW_ADDRESS) {
try {
const decrypted = (0, utils_3.decryptTrackerData)(Buffer.from(value, "hex"), Buffer.from(serialNumber));
if (decrypted !== undefined) {
return decrypted.toString("utf8").trim();
}
}
catch (err) {
const error = (0, error_1.ensureError)(err);
log.debug("Non-parsable parameter value received from eufy cloud. Will be ignored.", { serialNumber: serialNumber, type: type, value: value, error: (0, utils_2.getError)(error) });
}
return "";
}
}
return value;
}
static writeValue(type, value) {
if (value) {
if (type === types_2.ParamType.SNOOZE_MODE ||
type === types_2.ParamType.CAMERA_MOTION_ZONES ||
type === types_1.CommandType.CMD_SET_DOORSENSOR_ALWAYS_OPEN_DELAY ||
type === types_1.CommandType.CMD_SET_DOORSENSOR_ALWAYS_OPEN) {
return Buffer.from(JSON.stringify(value)).toString("base64");
}
return value;
}
return "";
}
}
exports.ParameterHelper = ParameterHelper;
//# sourceMappingURL=parameter.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"parameter.js","sourceRoot":"","sources":["../../src/http/parameter.ts"],"names":[],"mappings":"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"}

364
build/http/station.d.ts vendored Normal file
View File

@ -0,0 +1,364 @@
import { TypedEmitter } from "tiny-typed-emitter";
import { HTTPApi } from "./api";
import { AlarmTone, NotificationSwitchMode, DeviceType, FloodlightMotionTriggeredDistance, GuardMode, NotificationType, PowerSource, PropertyName, TimeFormat, CommandName, VideoTypeStoreToNAS, HB3DetectionTypes, WalllightNotificationType, DailyLightingType, MotionActivationMode, LightingActiveMode, SourceType, T8170DetectionTypes, IndoorS350NotificationTypes, SoloCameraDetectionTypes, MotionDetectionRangeType, ViewModeType, FloodlightT8425NotificationTypes, PresetPositionType, IndoorS350DetectionTypes } from "./types";
import { SnoozeDetail, StationListResponse } from "./models";
import { IndexedProperty, PropertyMetadataAny, PropertyValue, PropertyValues, RawValues, StationEvents, Schedule } from "./interfaces";
import { CrossTrackingGroupEntry, DynamicLighting, MotionZone, RGBColor } from "../p2p/interfaces";
import { CalibrateGarageType, FilterDetectType, FilterEventType, FilterStorageType, P2PConnectionType, PanTiltDirection, VideoCodec, WatermarkSetting1, WatermarkSetting2, WatermarkSetting3, WatermarkSetting4, WatermarkSetting5 } from "../p2p/types";
import { Device } from "./device";
import { PushMessage } from "../push/models";
export declare class Station extends TypedEmitter<StationEvents> {
private api;
private rawStation;
private p2pSession;
private properties;
private rawProperties;
private ready;
private lockPublicKey;
private currentDelay;
private reconnectTimeout?;
private terminating;
private p2pConnectionType;
static readonly CHANNEL: number;
static readonly CHANNEL_INDOOR: number;
private pinVerified;
protected constructor(api: HTTPApi, station: StationListResponse, ipAddress?: string, listeningPort?: number, publicKey?: string, enableEmbeddedPKCS1Support?: boolean);
protected initializeState(): void;
initialize(): void;
static getInstance(api: HTTPApi, stationData: StationListResponse, ipAddress?: string, listeningPort?: number, enableEmbeddedPKCS1Support?: boolean): Promise<Station>;
getStateID(state: string, level?: number): string;
getStateChannel(): string;
getRawStation(): StationListResponse;
update(station: StationListResponse): void;
updateProperty(name: string, value: PropertyValue, force?: boolean): boolean;
updateRawProperties(values: RawValues): void;
protected handlePropertyChange(metadata: PropertyMetadataAny, oldValue: PropertyValue, newValue: PropertyValue): void;
updateRawProperty(type: number, value: string, source: SourceType): boolean;
protected convertRawPropertyValue(property: PropertyMetadataAny, value: string): PropertyValue;
getPropertyMetadata(name: string, hidden?: boolean): PropertyMetadataAny;
getPropertyValue(name: string): PropertyValue;
hasPropertyValue(name: string): boolean;
getRawProperty(type: number): string | undefined;
getRawProperties(): RawValues;
getProperties(): PropertyValues;
getPropertiesMetadata(hidden?: boolean): IndexedProperty;
hasProperty(name: string, hidden?: boolean): boolean;
getCommands(): Array<CommandName>;
hasCommand(name: CommandName): boolean;
static getChannel(type: number): number;
static isStation(type: number): boolean;
isStation(): boolean;
static isStationHomeBase3(type: number): boolean;
static isStationHomeBase3BySn(sn: string): boolean;
isStationHomeBase3(): boolean;
isIntegratedDevice(): boolean;
isP2PConnectableDevice(): boolean;
getDeviceType(): number;
getHardwareVersion(): string;
getMACAddress(): string;
getModel(): string;
getName(): string;
getSerial(): string;
getSoftwareVersion(): string;
getIPAddress(): string;
getLANIPAddress(): PropertyValue;
getGuardMode(): PropertyValue;
getCurrentMode(): PropertyValue;
processPushNotification(message: PushMessage): void;
isConnected(): boolean;
close(): void;
isEnergySavingDevice(): boolean;
connect(): Promise<void>;
private onFinishDownload;
private onStartDownload;
private onStopLivestream;
private onErrorLivestream;
private onStartLivestream;
private onStopRTSPLivestream;
private onStartRTSPLivestream;
private onWifiRssiChanged;
private onRTSPUrl;
private onParameter;
private onAlarmDelay;
private onAlarmArmed;
private onAlarmEvent;
setGuardMode(mode: GuardMode): void;
getCameraInfo(): void;
getStorageInfoEx(): void;
private onAlarmMode;
private getArmDelay;
private _getDeviceSerial;
private _handleCameraInfoParameters;
private onCameraInfo;
private onCommandResponse;
private onSecondaryCommandResponse;
private onConnect;
private onDisconnect;
private onTimeout;
private getCurrentDelay;
private resetCurrentDelay;
private scheduleReconnect;
rebootHUB(): void;
setStatusLed(device: Device, value: boolean): void;
setAutoNightVision(device: Device, value: boolean): void;
setNightVision(device: Device, value: number): void;
setMotionDetection(device: Device, value: boolean): void;
setSoundDetection(device: Device, value: boolean): void;
setSoundDetectionType(device: Device, value: number): void;
setSoundDetectionSensitivity(device: Device, value: number): void;
setPetDetection(device: Device, value: boolean): void;
panAndTilt(device: Device, direction: PanTiltDirection, command?: number): void;
switchLight(device: Device, value: boolean): void;
setMotionDetectionSensitivity(device: Device, value: number): void;
setMotionDetectionType(device: Device, value: number): void;
setMotionDetectionTypeHB3(device: Device, type: HB3DetectionTypes | T8170DetectionTypes | SoloCameraDetectionTypes | IndoorS350DetectionTypes, value: boolean): void;
setMotionZone(device: Device, value: MotionZone): void;
setMotionTracking(device: Device, value: boolean): void;
setPanAndTiltRotationSpeed(device: Device, value: number): void;
setMicMute(device: Device, value: boolean): void;
setAudioRecording(device: Device, value: boolean): void;
enableSpeaker(device: Device, value: boolean): void;
setSpeakerVolume(device: Device, value: number): void;
setRingtoneVolume(device: Device, value: number): void;
enableIndoorChime(device: Device, value: boolean): void;
enableHomebaseChime(device: Device, value: boolean): void;
setHomebaseChimeRingtoneVolume(device: Device, value: number): void;
setHomebaseChimeRingtoneType(device: Device, value: number): void;
setNotificationType(device: Device, value: NotificationType | WalllightNotificationType): void;
setNotificationPerson(device: Device, value: boolean): void;
setNotificationPet(device: Device, value: boolean): void;
setNotificationAllOtherMotion(device: Device, value: boolean): void;
setNotificationAllSound(device: Device, value: boolean): void;
setNotificationCrying(device: Device, value: boolean): void;
setNotificationRing(device: Device, value: boolean): void;
setNotificationMotion(device: Device, value: boolean): void;
setPowerSource(device: Device, value: PowerSource): void;
setPowerWorkingMode(device: Device, value: number): void;
setRecordingClipLength(device: Device, value: number): void;
setRecordingRetriggerInterval(device: Device, value: number): void;
setRecordingEndClipMotionStops(device: Device, value: boolean): void;
setVideoStreamingQuality(device: Device, value: number): void;
setVideoRecordingQuality(device: Device, value: number): void;
setWDR(device: Device, value: boolean): void;
setFloodlightLightSettingsEnable(device: Device, value: boolean): void;
setFloodlightLightSettingsBrightnessManual(device: Device, value: number): void;
setFloodlightLightSettingsBrightnessMotion(device: Device, value: number): void;
setFloodlightLightSettingsBrightnessSchedule(device: Device, value: number): void;
setFloodlightLightSettingsMotionTriggered(device: Device, value: boolean): void;
setFloodlightLightSettingsMotionTriggeredDistance(device: Device, value: FloodlightMotionTriggeredDistance): void;
setFloodlightLightSettingsMotionTriggeredTimer(device: Device, seconds: number): void;
triggerStationAlarmSound(seconds: number): void;
resetStationAlarmSound(): void;
triggerDeviceAlarmSound(device: Device, seconds: number): void;
resetDeviceAlarmSound(device: Device): void;
setStationAlarmRingtoneVolume(value: number): void;
setStationAlarmTone(value: AlarmTone): void;
setStationPromptVolume(value: number): void;
setStationNotificationSwitchMode(mode: NotificationSwitchMode, value: boolean): void;
setStationNotificationStartAlarmDelay(value: boolean): void;
setStationTimeFormat(value: TimeFormat): void;
setRTSPStream(device: Device, value: boolean): void;
setAntiTheftDetection(device: Device, value: boolean): void;
setWatermark(device: Device, value: WatermarkSetting1 | WatermarkSetting2 | WatermarkSetting3 | WatermarkSetting4 | WatermarkSetting5): void;
enableDevice(device: Device, value: boolean): void;
startDownload(device: Device, path: string, cipher_id?: number): Promise<void>;
cancelDownload(device: Device): void;
startLivestream(device: Device, videoCodec?: VideoCodec): void;
stopLivestream(device: Device): void;
isLiveStreaming(device: Device): boolean;
isDownloading(device: Device): boolean;
quickResponse(device: Device, voice_id: number): void;
setChirpVolume(device: Device, value: number): void;
setChirpTone(device: Device, value: number): void;
setHDR(device: Device, value: boolean): void;
setDistortionCorrection(device: Device, value: boolean): void;
setRingRecord(device: Device, value: number): void;
lockDevice(device: Device, value: boolean): void;
setStationSwitchModeWithAccessCode(value: boolean): void;
setStationAutoEndAlarm(value: boolean): void;
setStationTurnOffAlarmWithButton(value: boolean): void;
startRTSPStream(device: Device): void;
stopRTSPStream(device: Device): void;
setMotionDetectionRange(device: Device, type: MotionDetectionRangeType): void;
setMotionDetectionRangeStandardSensitivity(device: Device, sensitivity: number): void;
setMotionDetectionRangeAdvancedLeftSensitivity(device: Device, sensitivity: number): void;
setMotionDetectionRangeAdvancedMiddleSensitivity(device: Device, sensitivity: number): void;
setMotionDetectionRangeAdvancedRightSensitivity(device: Device, sensitivity: number): void;
setMotionDetectionTestMode(device: Device, enabled: boolean): void;
setMotionTrackingSensitivity(device: Device, sensitivity: number): void;
setMotionAutoCruise(device: Device, enabled: boolean): void;
setMotionOutOfViewDetection(device: Device, enabled: boolean): void;
setLightSettingsColorTemperatureManual(device: Device, value: number): void;
setLightSettingsColorTemperatureMotion(device: Device, value: number): void;
setLightSettingsColorTemperatureSchedule(device: Device, value: number): void;
setLightSettingsMotionActivationMode(device: Device, value: MotionActivationMode): void;
setVideoNightvisionImageAdjustment(device: Device, enabled: boolean): void;
setVideoColorNightvision(device: Device, enabled: boolean): void;
setAutoCalibration(device: Device, enabled: boolean): void;
isRTSPLiveStreaming(device: Device): boolean;
setConnectionType(type: P2PConnectionType): void;
getConnectionType(): P2PConnectionType;
private onRuntimeState;
private onChargingState;
hasDevice(deviceSN: string): boolean;
hasDeviceWithType(deviceType: DeviceType): boolean;
private onFloodlightManualSwitch;
calibrateLock(device: Device): void;
private convertAdvancedLockSettingValue;
private convertAdvancedLockSettingValueT8530;
private getAdvancedLockSettingsPayload;
private getAdvancedLockSettingsPayloadT8530;
private getAdvancedLockSettingName;
private getAdvancedLockSettingNameT8530;
setAdvancedLockParams(device: Device, property: PropertyName, value: PropertyValue): void;
setLoiteringDetection(device: Device, value: boolean): void;
setLoiteringDetectionRange(device: Device, value: number): void;
setLoiteringDetectionLength(device: Device, value: number): void;
private _setMotionDetectionSensitivity;
private _getMotionDetectionSensitivityAdvanced;
setMotionDetectionSensitivityMode(device: Device, value: number): void;
setMotionDetectionSensitivityStandard(device: Device, value: number): void;
setMotionDetectionSensitivityAdvancedA(device: Device, value: number): void;
setMotionDetectionSensitivityAdvancedB(device: Device, value: number): void;
setMotionDetectionSensitivityAdvancedC(device: Device, value: number): void;
setMotionDetectionSensitivityAdvancedD(device: Device, value: number): void;
setMotionDetectionSensitivityAdvancedE(device: Device, value: number): void;
setMotionDetectionSensitivityAdvancedF(device: Device, value: number): void;
setMotionDetectionSensitivityAdvancedG(device: Device, value: number): void;
setMotionDetectionSensitivityAdvancedH(device: Device, value: number): void;
private _setLoiteringCustomResponse;
setLoiteringCustomResponseAutoVoiceResponse(device: Device, value: boolean): void;
setLoiteringCustomResponseAutoVoiceResponseVoice(device: Device, value: number): void;
setLoiteringCustomResponseHomeBaseNotification(device: Device, value: boolean): void;
setLoiteringCustomResponsePhoneNotification(device: Device, value: boolean): void;
setLoiteringCustomResponseTimeFrom(device: Device, value: string): void;
setLoiteringCustomResponseTimeTo(device: Device, value: string): void;
setDeliveryGuard(device: Device, value: boolean): void;
setDeliveryGuardPackageGuarding(device: Device, value: boolean): void;
setDeliveryGuardPackageGuardingVoiceResponseVoice(device: Device, value: number): void;
private setDeliveryGuardPackageGuardingActivatedTime;
setDeliveryGuardPackageGuardingActivatedTimeFrom(device: Device, value: string): void;
setDeliveryGuardPackageGuardingActivatedTimeTo(device: Device, value: string): void;
setDeliveryGuardUncollectedPackageAlert(device: Device, value: boolean): void;
setDeliveryGuardUncollectedPackageAlertTimeToCheck(device: Device, value: string): void;
setDeliveryGuardPackageLiveCheckAssistance(device: Device, value: boolean): void;
setDualCamWatchViewMode(device: Device, value: ViewModeType): void;
private _setRingAutoResponse;
setRingAutoResponse(device: Device, value: boolean): void;
setRingAutoResponseVoiceResponse(device: Device, value: boolean): void;
setRingAutoResponseVoiceResponseVoice(device: Device, value: number): void;
setRingAutoResponseTimeFrom(device: Device, value: string): void;
setRingAutoResponseTimeTo(device: Device, value: string): void;
setNotificationRadarDetector(device: Device, value: boolean): void;
calibrate(device: Device): void;
setContinuousRecording(device: Device, value: boolean): void;
setContinuousRecordingType(device: Device, value: number): void;
enableDefaultAngle(device: Device, value: boolean): void;
setDefaultAngleIdleTime(device: Device, value: number): void;
setDefaultAngle(device: Device): void;
setPrivacyAngle(device: Device): void;
setNotificationIntervalTime(device: Device, value: number): void;
setSoundDetectionRoundLook(device: Device, value: boolean): void;
startTalkback(device: Device): void;
stopTalkback(device: Device): void;
private onTalkbackStarted;
private onTalkbackStopped;
private onTalkbackError;
isTalkbackOngoing(device: Device): boolean;
setScramblePasscode(device: Device, value: boolean): void;
setWrongTryProtection(device: Device, value: boolean): void;
setWrongTryAttempts(device: Device, value: number): void;
setWrongTryLockdownTime(device: Device, value: number): void;
private _sendSmartSafeCommand;
setSmartSafeParams(device: Device, property: PropertyName, value: PropertyValue): void;
unlock(device: Device): void;
verifyPIN(device: Device, pin: string): void;
private onDeviceShakeAlarm;
private onDevice911Alarm;
private onDeviceJammed;
private onDeviceLowBattery;
private onDeviceWrongTryProtectAlarm;
private onSdInfoEx;
setVideoTypeStoreToNAS(device: Device, value: VideoTypeStoreToNAS): void;
snooze(device: Device, value: SnoozeDetail): void;
addUser(device: Device, username: string, shortUserId: string, passcode: string, schedule?: Schedule): void;
deleteUser(device: Device, username: string, shortUserId: string): void;
updateUserSchedule(device: Device, username: string, shortUserId: string, schedule: Schedule): void;
updateUserPasscode(device: Device, username: string, passwordId: string, passcode: string): void;
setLockV12Params(device: Device, property: PropertyName, value: PropertyValue): void;
setSmartLockParams(device: Device, property: PropertyName, value: PropertyValue): void;
setAutoLock(device: Device, value: boolean): void;
setAutoLockSchedule(device: Device, value: boolean): void;
setAutoLockScheduleStartTime(device: Device, value: string): void;
setAutoLockScheduleEndTime(device: Device, value: string): void;
setAutoLockTimer(device: Device, value: number): void;
setOneTouchLocking(device: Device, value: boolean): void;
setSound(device: Device, value: number): void;
setNotification(device: Device, value: boolean): void;
setNotificationLocked(device: Device, value: boolean): void;
setNotificationUnlocked(device: Device, value: boolean): void;
private _sendLockV12P2PCommand;
queryAllUserId(device: Device): void;
chimeHomebase(value: number): void;
private onImageDownload;
downloadImage(cover_path: string): void;
private onTFCardStatus;
databaseQueryLatestInfo(failureCallback?: () => void): void;
databaseQueryLocal(serialNumbers: Array<string>, startDate: Date, endDate: Date, eventType?: FilterEventType, detectionType?: FilterDetectType, storageType?: FilterStorageType): void;
databaseDelete(ids: Array<number>): void;
databaseCountByDate(startDate: Date, endDate: Date): void;
private onDatabaseQueryLatest;
private onDatabaseQueryLocal;
private onDatabaseCountByDate;
private onDatabaseDelete;
private onSensorStatus;
setMotionDetectionTypeHuman(device: Device, value: boolean): void;
setMotionDetectionTypeAllOtherMotions(device: Device, value: boolean): void;
private _setLightSettingsLightingActiveMode;
setLightSettingsManualLightingActiveMode(device: Device, value: LightingActiveMode): void;
setLightSettingsManualDailyLighting(device: Device, value: DailyLightingType): void;
setLightSettingsManualColoredLighting(device: Device, value: RGBColor): void;
setLightSettingsManualDynamicLighting(device: Device, value: number): void;
setLightSettingsMotionLightingActiveMode(device: Device, value: LightingActiveMode): void;
setLightSettingsMotionDailyLighting(device: Device, value: DailyLightingType): void;
setLightSettingsMotionColoredLighting(device: Device, value: RGBColor): void;
setLightSettingsMotionDynamicLighting(device: Device, value: number): void;
setLightSettingsScheduleLightingActiveMode(device: Device, value: LightingActiveMode): void;
setLightSettingsScheduleDailyLighting(device: Device, value: DailyLightingType): void;
setLightSettingsScheduleColoredLighting(device: Device, value: RGBColor): void;
setLightSettingsScheduleDynamicLighting(device: Device, value: number): void;
setLightSettingsColoredLightingColors(device: Device, value: Array<RGBColor>): void;
setLightSettingsDynamicLightingThemes(device: Device, value: Array<DynamicLighting>): void;
setDoorControlWarning(device: Device, value: boolean): void;
openDoor(device: Device, value: boolean, doorId?: number): void;
private onGarageDoorStatus;
calibrateGarageDoor(device: Device, doorId: number, type: CalibrateGarageType): void;
private onStorageInfoHB3;
setMirrorMode(device: Device, value: boolean): void;
setFlickerAdjustment(device: Device, value: number): void;
setCrossCameraTracking(value: boolean): void;
setContinuousTrackingTime(value: number): void;
setTrackingAssistance(value: boolean): void;
setCrossTrackingCameraList(value: Array<string>): void;
setCrossTrackingGroupList(value: Array<CrossTrackingGroupEntry>): void;
setNotificationIndoor(device: Device, type: IndoorS350NotificationTypes, value: boolean): void;
setNotificationFloodlightT8425(device: Device, type: FloodlightT8425NotificationTypes, value: boolean): void;
presetPosition(device: Device, position: PresetPositionType): void;
savePresetPosition(device: Device, position: PresetPositionType): void;
deletePresetPosition(device: Device, position: PresetPositionType): void;
setLeavingDetection(device: Device, value: boolean): void;
private _setLeavingReactions;
setLeavingReactionNotification(device: Device, value: boolean): void;
setLeavingReactionStartTime(device: Device, value: string): void;
setLeavingReactionEndTime(device: Device, value: string): void;
setBeepVolume(device: Device, value: number): void;
setNightvisionOptimization(device: Device, value: boolean): void;
setNightvisionOptimizationSide(device: Device, value: number): void;
getLockParameters(): void;
getLockStatus(): void;
private onSequenceError;
updateUsername(device: Device, username: string, passwordId: string): void;
setOpenMethod(device: Device, value: number): void;
setMotionActivatedPrompt(device: Device, value: boolean): void;
open(device: Device): void;
}

10561
build/http/station.js Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

1333
build/http/types.d.ts vendored Normal file

File diff suppressed because it is too large Load Diff

9684
build/http/types.js Normal file

File diff suppressed because it is too large Load Diff

1
build/http/types.js.map Normal file

File diff suppressed because one or more lines are too long

79
build/http/utils.d.ts vendored Normal file
View File

@ -0,0 +1,79 @@
import { Device } from "./device";
import { Picture, Schedule } from "./interfaces";
import { NotificationSwitchMode, SignalLevel, HB3DetectionTypes, SourceType, T8170DetectionTypes, IndoorS350NotificationTypes, FloodlightT8425NotificationTypes, SmartLockNotification, IndoorS350DetectionTypes } from "./types";
import { HTTPApi } from "./api";
import { LockPushEvent } from "./../push/types";
import { Station } from "./station";
import { PushMessage } from "../push/models";
export declare const isGreaterEqualMinVersion: (minimal_version: string, current_version: string) => boolean;
export declare const pad: (num: number) => string;
export declare const getTimezoneGMTString: () => string;
export declare const getAbsoluteFilePath: (device_type: number, channel: number, filename: string) => string;
export declare const getImageFilePath: (device_type: number, channel: number, filename: string) => string;
export declare const isNotificationSwitchMode: (value: number, mode: NotificationSwitchMode) => boolean;
export declare const switchNotificationMode: (currentValue: number, mode: NotificationSwitchMode, enable: boolean) => number;
export declare const calculateWifiSignalLevel: (device: Device, rssi: number) => SignalLevel;
export declare const calculateCellularSignalLevel: (rssi: number) => SignalLevel;
export declare const encryptAPIData: (data: string, key: Buffer) => string;
export declare const decryptAPIData: (data: string, key: Buffer) => Buffer;
export declare const getBlocklist: (directions: Array<number>) => Array<number>;
export declare const getDistances: (blocklist: Array<number>) => Array<number>;
export declare const isHB3DetectionModeEnabled: (value: number, type: HB3DetectionTypes) => boolean;
export declare const getHB3DetectionMode: (value: number, type: HB3DetectionTypes, enable: boolean) => number;
export interface EufyTimezone {
timeZoneName: string;
timeId: string;
timeSn: string;
timeZoneGMT: string;
}
export declare const getEufyTimezone: () => EufyTimezone | undefined;
export declare const getAdvancedLockTimezone: (stationSN: string) => string;
export declare class WritePayload {
private split_byte;
private data;
write(bytes: Buffer): void;
getData(): Buffer;
}
export declare class ParsePayload {
private data;
constructor(data: Buffer);
readUint32BE(indexValue: number): number;
readUint32LE(indexValue: number): number;
readUint16BE(indexValue: number): number;
readUint16LE(indexValue: number): number;
readString(indexValue: number): string;
readStringHex(indexValue: number): string;
readInt8(indexValue: number): number;
readData(indexValue: number): Buffer;
private getDataPosition;
private getNextStep;
}
export declare const encodePasscode: (pass: string) => string;
export declare const hexDate: (date: Date) => string;
export declare const hexTime: (date: Date) => string;
export declare const hexWeek: (schedule: Schedule) => string;
export declare const hexStringScheduleToSchedule: (startDay: string, startTime: string, endDay: string, endTime: string, week: string) => Schedule;
export declare const randomNumber: (min: number, max: number) => number;
export declare const getIdSuffix: (p2pDid: string) => number;
export declare const getImageBaseCode: (serialnumber: string, p2pDid: string) => string;
export declare const getImageSeed: (p2pDid: string, code: string) => string;
export declare const getImageKey: (serialnumber: string, p2pDid: string, code: string) => string;
export declare const decodeImage: (p2pDid: string, data: Buffer) => Buffer;
export declare const getImagePath: (path: string) => string;
export declare const getImage: (api: HTTPApi, serial: string, url: string) => Promise<Picture>;
export declare const isPrioritySourceType: (current: SourceType | undefined, update: SourceType) => boolean;
export declare const decryptTrackerData: (data: Buffer, key: Buffer) => Buffer;
export declare const isT8170DetectionModeEnabled: (value: number, type: T8170DetectionTypes) => boolean;
export declare const getT8170DetectionMode: (value: number, type: T8170DetectionTypes, enable: boolean) => number;
export declare const isIndoorS350DetectionModeEnabled: (value: number, type: IndoorS350DetectionTypes) => boolean;
export declare const getIndoorS350DetectionMode: (value: number, type: IndoorS350DetectionTypes, enable: boolean) => number;
export declare const isIndoorNotitficationEnabled: (value: number, type: IndoorS350NotificationTypes) => boolean;
export declare const getIndoorNotification: (value: number, type: IndoorS350NotificationTypes, enable: boolean) => number;
export declare const isFloodlightT8425NotitficationEnabled: (value: number, type: FloodlightT8425NotificationTypes) => boolean;
export declare const getFloodLightT8425Notification: (value: number, type: FloodlightT8425NotificationTypes, enable: boolean) => number;
export declare const getLockEventType: (event: LockPushEvent) => number;
export declare const switchSmartLockNotification: (currentValue: number, mode: SmartLockNotification, enable: boolean) => number;
export declare const isSmartLockNotification: (value: number, mode: SmartLockNotification) => boolean;
export declare const getWaitSeconds: (device: Device) => number;
export declare const loadImageOverP2P: (station: Station, device: Device, id: string, p2pTimeouts: Map<string, NodeJS.Timeout>) => void;
export declare const loadEventImage: (station: Station, api: HTTPApi, device: Device, message: PushMessage, p2pTimeouts: Map<string, NodeJS.Timeout>) => void;

789
build/http/utils.js Normal file
View File

@ -0,0 +1,789 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.loadEventImage = exports.loadImageOverP2P = exports.getWaitSeconds = exports.isSmartLockNotification = exports.switchSmartLockNotification = exports.getLockEventType = exports.getFloodLightT8425Notification = exports.isFloodlightT8425NotitficationEnabled = exports.getIndoorNotification = exports.isIndoorNotitficationEnabled = exports.getIndoorS350DetectionMode = exports.isIndoorS350DetectionModeEnabled = exports.getT8170DetectionMode = exports.isT8170DetectionModeEnabled = exports.decryptTrackerData = exports.isPrioritySourceType = exports.getImage = exports.getImagePath = exports.decodeImage = exports.getImageKey = exports.getImageSeed = exports.getImageBaseCode = exports.getIdSuffix = exports.randomNumber = exports.hexStringScheduleToSchedule = exports.hexWeek = exports.hexTime = exports.hexDate = exports.encodePasscode = exports.ParsePayload = exports.WritePayload = exports.getAdvancedLockTimezone = exports.getEufyTimezone = exports.getHB3DetectionMode = exports.isHB3DetectionModeEnabled = exports.getDistances = exports.getBlocklist = exports.decryptAPIData = exports.encryptAPIData = exports.calculateCellularSignalLevel = exports.calculateWifiSignalLevel = exports.switchNotificationMode = exports.isNotificationSwitchMode = exports.getImageFilePath = exports.getAbsoluteFilePath = exports.getTimezoneGMTString = exports.pad = exports.isGreaterEqualMinVersion = void 0;
const crypto_1 = require("crypto");
const const_1 = require("./const");
const md5_1 = __importDefault(require("crypto-js/md5"));
const enc_hex_1 = __importDefault(require("crypto-js/enc-hex"));
const sha256_1 = __importDefault(require("crypto-js/sha256"));
const types_1 = require("./types");
const error_1 = require("../error");
const error_2 = require("./error");
const types_2 = require("./../push/types");
const logging_1 = require("../logging");
const utils_1 = require("../utils");
const normalizeVersionString = function (version) {
const trimmed = version ? version.replace(/^\s*(\S*(\s+\S+)*)\s*$/, "$1") : "";
const pieces = trimmed.split(RegExp("\\."));
const parts = [];
let value, piece, num, i;
for (i = 0; i < pieces.length; i += 1) {
piece = pieces[i].replace(RegExp("\\D"), "");
num = parseInt(piece, 10);
if (isNaN(num)) {
num = 0;
}
parts.push(num);
}
const partsLength = parts.length;
for (i = partsLength - 1; i >= 0; i -= 1) {
value = parts[i];
if (value === 0) {
parts.length -= 1;
}
else {
break;
}
}
return parts;
};
const isGreaterEqualMinVersion = function (minimal_version, current_version) {
const x = normalizeVersionString(minimal_version);
const y = normalizeVersionString(current_version);
const size = Math.min(x.length, y.length);
let i;
for (i = 0; i < size; i += 1) {
if (x[i] !== y[i]) {
return x[i] < y[i] ? true : false;
}
}
if (x.length === y.length) {
return true;
}
return (x.length < y.length) ? true : false;
};
exports.isGreaterEqualMinVersion = isGreaterEqualMinVersion;
const pad = function (num) {
const norm = Math.floor(Math.abs(num));
return (norm < 10 ? "0" : "") + norm;
};
exports.pad = pad;
const getTimezoneGMTString = function () {
const tzo = -new Date().getTimezoneOffset();
const dif = tzo >= 0 ? "+" : "-";
return `GMT${dif}${(0, exports.pad)(tzo / 60)}:${(0, exports.pad)(tzo % 60)}`;
};
exports.getTimezoneGMTString = getTimezoneGMTString;
const getAbsoluteFilePath = function (device_type, channel, filename) {
if (device_type === types_1.DeviceType.FLOODLIGHT) {
return `/mnt/data/Camera${String(channel).padStart(2, "0")}/${filename}.dat`;
}
return `/media/mmcblk0p1/Camera${String(channel).padStart(2, "0")}/${filename}.dat`;
};
exports.getAbsoluteFilePath = getAbsoluteFilePath;
const getImageFilePath = function (device_type, channel, filename) {
if (device_type === types_1.DeviceType.FLOODLIGHT) {
return `/mnt/data/video/${filename}_c${String(channel).padStart(2, "0")}.jpg`;
}
return `/media/mmcblk0p1/video/${filename}_c${String(channel).padStart(2, "0")}.jpg`;
};
exports.getImageFilePath = getImageFilePath;
const isNotificationSwitchMode = function (value, mode) {
if (value === 1)
value = 240;
return (value & mode) !== 0;
};
exports.isNotificationSwitchMode = isNotificationSwitchMode;
const switchNotificationMode = function (currentValue, mode, enable) {
let result = 0;
if (!enable && currentValue === 1 /* ALL */) {
currentValue = 240;
}
if (enable) {
result = mode | currentValue;
}
else {
result = ~mode & currentValue;
}
if ((0, exports.isNotificationSwitchMode)(result, types_1.NotificationSwitchMode.SCHEDULE) && (0, exports.isNotificationSwitchMode)(result, types_1.NotificationSwitchMode.APP) && (0, exports.isNotificationSwitchMode)(result, types_1.NotificationSwitchMode.GEOFENCE) && (0, exports.isNotificationSwitchMode)(result, types_1.NotificationSwitchMode.KEYPAD)) {
result = 1; /* ALL */
}
return result;
};
exports.switchNotificationMode = switchNotificationMode;
const calculateWifiSignalLevel = function (device, rssi) {
if (device.isWiredDoorbell()) {
if (rssi >= -65) {
return types_1.SignalLevel.FULL;
}
if (rssi >= -75) {
return types_1.SignalLevel.STRONG;
}
return rssi >= -80 ? types_1.SignalLevel.NORMAL : types_1.SignalLevel.WEAK;
}
else if (device.isCamera2Product()) {
if (rssi >= 0) {
return types_1.SignalLevel.NO_SIGNAL;
}
if (rssi >= -65) {
return types_1.SignalLevel.FULL;
}
if (rssi >= -75) {
return types_1.SignalLevel.STRONG;
}
return rssi >= -85 ? types_1.SignalLevel.NORMAL : types_1.SignalLevel.WEAK;
}
else if (device.isFloodLight()) {
if (rssi >= 0) {
return types_1.SignalLevel.NO_SIGNAL;
}
if (rssi >= -60) {
return types_1.SignalLevel.FULL;
}
if (rssi >= -70) {
return types_1.SignalLevel.STRONG;
}
return rssi >= -80 ? types_1.SignalLevel.NORMAL : types_1.SignalLevel.WEAK;
}
else if (device.isBatteryDoorbell()) {
if (rssi >= -65) {
return types_1.SignalLevel.FULL;
}
if (rssi >= -75) {
return types_1.SignalLevel.STRONG;
}
return rssi >= -85 ? types_1.SignalLevel.NORMAL : types_1.SignalLevel.WEAK;
}
else {
if (rssi >= 0) {
return types_1.SignalLevel.NO_SIGNAL;
}
if (rssi >= -65) {
return types_1.SignalLevel.FULL;
}
if (rssi >= -75) {
return types_1.SignalLevel.STRONG;
}
return rssi >= -85 ? types_1.SignalLevel.NORMAL : types_1.SignalLevel.WEAK;
}
};
exports.calculateWifiSignalLevel = calculateWifiSignalLevel;
const calculateCellularSignalLevel = function (rssi) {
if (rssi >= 0) {
return types_1.SignalLevel.NO_SIGNAL;
}
if (rssi >= -90) {
return types_1.SignalLevel.FULL;
}
if (rssi >= -95) {
return types_1.SignalLevel.STRONG;
}
return rssi >= -105 ? types_1.SignalLevel.NORMAL : types_1.SignalLevel.WEAK;
};
exports.calculateCellularSignalLevel = calculateCellularSignalLevel;
const encryptAPIData = (data, key) => {
const cipher = (0, crypto_1.createCipheriv)("aes-256-cbc", key, key.subarray(0, 16));
return (cipher.update(data, "utf8", "base64") +
cipher.final("base64"));
};
exports.encryptAPIData = encryptAPIData;
const decryptAPIData = (data, key) => {
const cipher = (0, crypto_1.createDecipheriv)("aes-256-cbc", key, key.subarray(0, 16));
return Buffer.concat([
cipher.update(data, "base64"),
cipher.final()
]);
};
exports.decryptAPIData = decryptAPIData;
const getBlocklist = function (directions) {
const result = [];
for (let distance = 1; distance <= 5; distance++) {
let i = 0;
let j = 0;
let k = 1;
for (const directionDistance of directions) {
if (directionDistance >= distance) {
j += k;
}
k <<= 1;
}
if (j == 0) {
i = 65535;
}
else if (!(j == 255 || j == 65535)) {
i = (j ^ 255) + 65280;
}
result.push(65535 & i);
}
return result;
};
exports.getBlocklist = getBlocklist;
const getDistances = function (blocklist) {
const result = [3, 3, 3, 3, 3, 3, 3, 3];
let calcDistance = 0;
for (const blockElement of blocklist) {
let valueOf = blockElement ^ 65535;
calcDistance++;
if (valueOf !== 0) {
for (let i = 0; i < result.length; i++) {
const intValue = valueOf & 1;
if (intValue > 0) {
result[i] = calcDistance;
}
valueOf = valueOf >> 1;
}
}
}
return result;
};
exports.getDistances = getDistances;
const isHB3DetectionModeEnabled = function (value, type) {
if (type === types_1.HB3DetectionTypes.HUMAN_RECOGNITION) {
return (type & value) == type && (value & 65536) == 65536;
}
else if (type === types_1.HB3DetectionTypes.HUMAN_DETECTION) {
return (type & value) == type && (value & 1) == 1;
}
return (type & value) == type;
};
exports.isHB3DetectionModeEnabled = isHB3DetectionModeEnabled;
const getHB3DetectionMode = function (value, type, enable) {
let result = 0;
if (!enable) {
if (type === types_1.HB3DetectionTypes.HUMAN_RECOGNITION) {
const tmp = (type & value) == type ? type ^ value : value;
result = (value & 65536) == 65536 ? tmp ^ 65536 : tmp;
}
else if (type === types_1.HB3DetectionTypes.HUMAN_DETECTION) {
const tmp = (type & value) == type ? type ^ value : value;
result = (value & 1) == 1 ? tmp ^ 1 : tmp;
}
else {
result = type ^ value;
}
}
else {
if (type === types_1.HB3DetectionTypes.HUMAN_RECOGNITION) {
result = type | value | 65536;
}
else if (type === types_1.HB3DetectionTypes.HUMAN_DETECTION) {
result = type | value | 1;
}
else {
result = type | value;
}
}
return result;
};
exports.getHB3DetectionMode = getHB3DetectionMode;
const getEufyTimezone = function () {
for (const timezone of const_1.timeZoneData) {
if (timezone.timeId === Intl.DateTimeFormat().resolvedOptions().timeZone) {
return timezone;
}
}
return undefined;
};
exports.getEufyTimezone = getEufyTimezone;
const getAdvancedLockTimezone = function (stationSN) {
const timezone = (0, exports.getEufyTimezone)();
if (timezone !== undefined) {
if (stationSN.startsWith("T8520") && (0, exports.isGreaterEqualMinVersion)("1.2.8.6", stationSN))
return `${timezone.timeZoneGMT}|1.${timezone.timeSn}`;
else
return timezone.timeZoneGMT;
}
return "";
};
exports.getAdvancedLockTimezone = getAdvancedLockTimezone;
class WritePayload {
split_byte = -95;
data = Buffer.from([]);
write(bytes) {
const tmp_data = Buffer.from(bytes);
this.data = Buffer.concat([this.data, Buffer.from([this.split_byte]), Buffer.from([tmp_data.length & 255]), tmp_data]);
this.split_byte += 1;
}
getData() {
return this.data;
}
}
exports.WritePayload = WritePayload;
class ParsePayload {
data;
constructor(data) {
this.data = data;
}
readUint32BE(indexValue) {
return this.readData(indexValue).readUint32BE();
}
readUint32LE(indexValue) {
return this.readData(indexValue).readUint32LE();
}
readUint16BE(indexValue) {
return this.readData(indexValue).readUint16BE();
}
readUint16LE(indexValue) {
return this.readData(indexValue).readUint16LE();
}
readString(indexValue) {
return this.readData(indexValue).toString();
}
readStringHex(indexValue) {
return this.readData(indexValue).toString("hex");
}
readInt8(indexValue) {
let dataPosition = this.getDataPosition(indexValue);
if (dataPosition == -1) {
return 0;
}
dataPosition = dataPosition + 2;
if (dataPosition >= this.data.length) {
return 0;
}
return this.data.readInt8(dataPosition);
}
readData(indexValue) {
let dataPosition = this.getDataPosition(indexValue);
if (dataPosition == -1) {
return Buffer.from("");
}
dataPosition++;
if (dataPosition >= this.data.length) {
return Buffer.from("");
}
const nextStep = this.getNextStep(indexValue, dataPosition, this.data);
let tmp;
if (nextStep == 1) {
tmp = this.data.readInt8(dataPosition);
}
else {
tmp = this.data.readUint16LE(dataPosition);
}
if (dataPosition + nextStep + tmp > this.data.length) {
return Buffer.from("");
}
return this.data.subarray(dataPosition + nextStep, dataPosition + nextStep + tmp);
}
getDataPosition(indexValue) {
if (this.data && this.data.length >= 1) {
for (let currentPosition = 0; currentPosition < this.data.length;) {
if (this.data.readInt8(currentPosition) == indexValue) {
return currentPosition;
}
else {
const value = this.data.readInt8(currentPosition);
currentPosition++;
if (currentPosition >= this.data.length) {
break;
}
const nextStep = this.getNextStep(value, currentPosition, this.data);
if ((currentPosition + nextStep) >= this.data.length) {
break;
}
if (nextStep == 1) {
currentPosition = this.data.readInt8(currentPosition) + currentPosition + nextStep;
}
else {
currentPosition = this.data.readUint16LE(currentPosition) + currentPosition + nextStep;
}
}
}
}
return -1;
}
getNextStep(indexValue, position, data) {
const newPosition = position + 1 + data.readUInt8(position);
return (newPosition == data.length || newPosition > data.length || data.readInt8(newPosition) == indexValue + 1) ? 1 : 2;
}
}
exports.ParsePayload = ParsePayload;
/*export const generateHash = function(data: Buffer): number {
let result = 0;
for (const value of data) {
result = result ^ value;
}
return result;
}
export const encodeSmartSafeData = function(command: number, payload: Buffer): Buffer {
const header = Buffer.from(SmartSafe.DATA_HEADER);
const size = Buffer.allocUnsafe(2);
size.writeInt16LE(payload.length + 9);
const versionCode = Buffer.from([SmartSafe.VERSION_CODE]);
const dataType = Buffer.from([-1]);
const commandCode = Buffer.from([command]);
const packageFlag = Buffer.from([-64]);
const data = Buffer.concat([header, size, versionCode, dataType, commandCode, packageFlag, payload]);
const hash = generateHash(data);
return Buffer.concat([data, Buffer.from([hash])]);
}*/
const encodePasscode = function (pass) {
let result = "";
for (let i = 0; i < pass.length; i++)
result += pass.charCodeAt(i).toString(16);
return result;
};
exports.encodePasscode = encodePasscode;
const hexDate = function (date) {
const buf = Buffer.allocUnsafe(4);
buf.writeUint8(date.getDate());
buf.writeUint8(date.getMonth() + 1, 1);
buf.writeUint16BE(date.getFullYear(), 2);
return buf.readUInt32LE().toString(16).padStart(8, "0");
};
exports.hexDate = hexDate;
const hexTime = function (date) {
const buf = Buffer.allocUnsafe(2);
buf.writeUint8(date.getHours());
buf.writeUint8(date.getMinutes(), 1);
return buf.readUInt16BE().toString(16).padStart(4, "0");
};
exports.hexTime = hexTime;
const hexWeek = function (schedule) {
const SUNDAY = 1;
const MONDAY = 2;
const TUESDAY = 4;
const WEDNESDAY = 8;
const THUERSDAY = 16;
const FRIDAY = 32;
const SATURDAY = 64;
let result = 0;
if (schedule.week !== undefined) {
if (schedule.week.sunday) {
result |= SUNDAY;
}
if (schedule.week.monday) {
result |= MONDAY;
}
if (schedule.week.tuesday) {
result |= TUESDAY;
}
if (schedule.week.wednesday) {
result |= WEDNESDAY;
}
if (schedule.week.thursday) {
result |= THUERSDAY;
}
if (schedule.week.friday) {
result |= FRIDAY;
}
if (schedule.week.saturday) {
result |= SATURDAY;
}
return result.toString(16);
}
return "ff";
};
exports.hexWeek = hexWeek;
const hexStringScheduleToSchedule = function (startDay, startTime, endDay, endTime, week) {
const SUNDAY = 1;
const MONDAY = 2;
const TUESDAY = 4;
const WEDNESDAY = 8;
const THUERSDAY = 16;
const FRIDAY = 32;
const SATURDAY = 64;
const weekNumber = Number.parseInt(week, 16);
return {
startDateTime: startDay === "00000000" ? undefined : new Date(Number.parseInt(`${startDay.substring(2, 4)}${startDay.substring(0, 2)}`, 16), Number.parseInt(startDay.substring(4, 6), 16) - 1, Number.parseInt(startDay.substring(6, 8), 16), Number.parseInt(startTime.substring(0, 2), 16), Number.parseInt(startTime.substring(2, 4), 16)),
endDateTime: endDay === "ffffffff" ? undefined : new Date(Number.parseInt(`${endDay.substring(2, 4)}${endDay.substring(0, 2)}`, 16), Number.parseInt(endDay.substring(4, 6), 16) - 1, Number.parseInt(endDay.substring(6, 8), 16), Number.parseInt(endTime.substring(0, 2), 16), Number.parseInt(endTime.substring(2, 4), 16)),
week: {
monday: (weekNumber & MONDAY) == MONDAY,
tuesday: (weekNumber & TUESDAY) == TUESDAY,
wednesday: (weekNumber & WEDNESDAY) == WEDNESDAY,
thursday: (weekNumber & THUERSDAY) == THUERSDAY,
friday: (weekNumber & FRIDAY) == FRIDAY,
saturday: (weekNumber & SATURDAY) == SATURDAY,
sunday: (weekNumber & SUNDAY) == SUNDAY,
},
};
};
exports.hexStringScheduleToSchedule = hexStringScheduleToSchedule;
const randomNumber = function (min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
};
exports.randomNumber = randomNumber;
const getIdSuffix = function (p2pDid) {
let result = 0;
const match = p2pDid.match(/^[A-Z]+-(\d+)-[A-Z]+$/);
if (match?.length == 2) {
const num1 = Number.parseInt(match[1][0]);
const num2 = Number.parseInt(match[1][1]);
const num3 = Number.parseInt(match[1][3]);
const num4 = Number.parseInt(match[1][5]);
result = num1 + num2 + num3;
if (num3 < 5) {
result = result + num3;
}
result = result + num4;
}
return result;
};
exports.getIdSuffix = getIdSuffix;
const getImageBaseCode = function (serialnumber, p2pDid) {
let nr = 0;
try {
nr = Number.parseInt(`0x${serialnumber[serialnumber.length - 1]}`);
}
catch (err) {
const error = (0, error_1.ensureError)(err);
throw new error_2.ImageBaseCodeError("Error generating image base code", { cause: error, context: { serialnumber: serialnumber, p2pDid: p2pDid } });
}
nr = (nr + 10) % 10;
const base = serialnumber.substring(nr);
return `${base}${(0, exports.getIdSuffix)(p2pDid)}`;
};
exports.getImageBaseCode = getImageBaseCode;
const getImageSeed = function (p2pDid, code) {
try {
const ncode = Number.parseInt(code.substring(2));
const prefix = 1000 - (0, exports.getIdSuffix)(p2pDid);
return (0, md5_1.default)(`${prefix}${ncode}`).toString(enc_hex_1.default).toUpperCase();
}
catch (err) {
const error = (0, error_1.ensureError)(err);
throw new error_2.ImageBaseCodeError("Error generating image seed", { cause: error, context: { p2pDid: p2pDid, code: code } });
}
};
exports.getImageSeed = getImageSeed;
const getImageKey = function (serialnumber, p2pDid, code) {
const basecode = (0, exports.getImageBaseCode)(serialnumber, p2pDid);
const seed = (0, exports.getImageSeed)(p2pDid, code);
const data = `01${basecode}${seed}`;
const hash = (0, sha256_1.default)(data);
const hashBytes = [...Buffer.from(hash.toString(enc_hex_1.default), "hex")];
const startByte = hashBytes[10];
for (let i = 0; i < 32; i++) {
const byte = hashBytes[i];
let fixed_byte = startByte;
if (i < 31) {
fixed_byte = hashBytes[i + 1];
}
if ((i == 31) || ((i & 1) != 0)) {
hashBytes[10] = fixed_byte;
if ((126 < byte) || (126 < hashBytes[10])) {
if (byte < hashBytes[10] || (byte - hashBytes[10]) == 0) {
hashBytes[i] = hashBytes[10] - byte;
}
else {
hashBytes[i] = byte - hashBytes[10];
}
}
}
else if ((byte < 125) || (fixed_byte < 125)) {
hashBytes[i] = fixed_byte + byte;
}
}
return `${Buffer.from(hashBytes.slice(16)).toString("hex").toUpperCase()}`;
};
exports.getImageKey = getImageKey;
const decodeImage = function (p2pDid, data) {
if (data.length >= 12) {
const header = data.subarray(0, 12).toString();
if (header === "eufysecurity") {
const serialnumber = data.subarray(13, 29).toString();
const code = data.subarray(30, 40).toString();
const imageKey = (0, exports.getImageKey)(serialnumber, p2pDid, code);
const otherData = data.subarray(41);
const encryptedData = otherData.subarray(0, 256);
const cipher = (0, crypto_1.createDecipheriv)("aes-128-ecb", Buffer.from(imageKey, "utf-8").subarray(0, 16), null);
cipher.setAutoPadding(false);
const decryptedData = Buffer.concat([
cipher.update(encryptedData),
cipher.final()
]);
decryptedData.copy(otherData);
return otherData;
}
}
return data;
};
exports.decodeImage = decodeImage;
const getImagePath = function (path) {
const splittedPath = path.split("~");
if (splittedPath.length === 2) {
return splittedPath[1];
}
return path;
};
exports.getImagePath = getImagePath;
const getImage = async function (api, serial, url) {
const { default: imageType } = await import("image-type");
const image = await api.getImage(serial, url);
const type = await imageType(image);
return {
data: image,
type: type !== null && type !== undefined ? type : { ext: "unknown", mime: "application/octet-stream" }
};
};
exports.getImage = getImage;
const isPrioritySourceType = function (current, update) {
if (((current === "http" || current === "p2p" || current === "push" || current === "mqtt" || current === undefined) && (update === "p2p" || update === "push" || update === "mqtt")) ||
((current === "http" || current === undefined) && update === "http")) {
return true;
}
return false;
};
exports.isPrioritySourceType = isPrioritySourceType;
const decryptTrackerData = (data, key) => {
const decipher = (0, crypto_1.createDecipheriv)("aes-128-ecb", key, null);
decipher.setAutoPadding(false);
return Buffer.concat([
decipher.update(data),
decipher.final()
]);
};
exports.decryptTrackerData = decryptTrackerData;
const isT8170DetectionModeEnabled = function (value, type) {
return (type & value) == type;
};
exports.isT8170DetectionModeEnabled = isT8170DetectionModeEnabled;
const getT8170DetectionMode = function (value, type, enable) {
let result = 0;
if ((Object.values(types_1.T8170DetectionTypes).includes(type) && Object.values(types_1.T8170DetectionTypes).includes(value)) && !enable)
return value;
if (!enable) {
result = type ^ value;
}
else {
result = type | value;
}
return result;
};
exports.getT8170DetectionMode = getT8170DetectionMode;
const isIndoorS350DetectionModeEnabled = function (value, type) {
return (type & value) == type;
};
exports.isIndoorS350DetectionModeEnabled = isIndoorS350DetectionModeEnabled;
const getIndoorS350DetectionMode = function (value, type, enable) {
let result = 0;
if ((Object.values(types_1.IndoorS350DetectionTypes).includes(type) && Object.values(types_1.IndoorS350DetectionTypes).includes(value)) && !enable)
return value;
if (!enable) {
result = type ^ value;
}
else {
result = type | value;
}
return result;
};
exports.getIndoorS350DetectionMode = getIndoorS350DetectionMode;
const isIndoorNotitficationEnabled = function (value, type) {
return (type & value) == type;
};
exports.isIndoorNotitficationEnabled = isIndoorNotitficationEnabled;
const getIndoorNotification = function (value, type, enable) {
let result = 0;
if (!enable) {
result = (type ^ value) + 800;
}
else {
result = type | value;
}
return result;
};
exports.getIndoorNotification = getIndoorNotification;
const isFloodlightT8425NotitficationEnabled = function (value, type) {
return (type & value) == type;
};
exports.isFloodlightT8425NotitficationEnabled = isFloodlightT8425NotitficationEnabled;
const getFloodLightT8425Notification = function (value, type, enable) {
let result = 0;
if (!enable) {
result = (type ^ value);
}
else {
result = type | value;
}
return result;
};
exports.getFloodLightT8425Notification = getFloodLightT8425Notification;
const getLockEventType = function (event) {
switch (event) {
case types_2.LockPushEvent.AUTO_LOCK:
case types_2.LockPushEvent.AUTO_UNLOCK:
return 1;
case types_2.LockPushEvent.MANUAL_LOCK:
case types_2.LockPushEvent.MANUAL_UNLOCK:
return 2;
case types_2.LockPushEvent.APP_LOCK:
case types_2.LockPushEvent.APP_UNLOCK:
return 3;
case types_2.LockPushEvent.PW_LOCK:
case types_2.LockPushEvent.PW_UNLOCK:
return 4;
case types_2.LockPushEvent.FINGER_LOCK:
case types_2.LockPushEvent.FINGERPRINT_UNLOCK:
return 5;
case types_2.LockPushEvent.TEMPORARY_PW_LOCK:
case types_2.LockPushEvent.TEMPORARY_PW_UNLOCK:
return 6;
case types_2.LockPushEvent.KEYPAD_LOCK:
return 7;
}
return 0;
};
exports.getLockEventType = getLockEventType;
const switchSmartLockNotification = function (currentValue, mode, enable) {
let result = 0;
if (enable) {
result = mode | currentValue;
}
else {
result = ~mode & currentValue;
}
return result;
};
exports.switchSmartLockNotification = switchSmartLockNotification;
const isSmartLockNotification = function (value, mode) {
return (value & mode) !== 0;
};
exports.isSmartLockNotification = isSmartLockNotification;
const getWaitSeconds = (device) => {
let seconds = 60;
const workingMode = device.getPropertyValue(types_1.PropertyName.DevicePowerWorkingMode);
if (workingMode !== undefined && workingMode === 2) {
const customValue = device.getPropertyValue(types_1.PropertyName.DeviceRecordingClipLength);
if (customValue !== undefined) {
seconds = customValue;
}
}
return seconds;
};
exports.getWaitSeconds = getWaitSeconds;
const loadImageOverP2P = function (station, device, id, p2pTimeouts) {
if (station.hasCommand(types_1.CommandName.StationDatabaseQueryLatestInfo) && p2pTimeouts.get(id) === undefined) {
const seconds = (0, exports.getWaitSeconds)(device);
p2pTimeouts.set(id, setTimeout(async () => {
station.databaseQueryLatestInfo();
p2pTimeouts.delete(id);
}, seconds * 1000));
}
};
exports.loadImageOverP2P = loadImageOverP2P;
const loadEventImage = function (station, api, device, message, p2pTimeouts) {
if (message.notification_style === types_1.NotificationType.MOST_EFFICIENT) {
(0, exports.loadImageOverP2P)(station, device, device.getSerial(), p2pTimeouts);
}
else {
if (!(0, utils_1.isEmpty)(message.pic_url)) {
(0, exports.getImage)(api, device.getSerial(), message.pic_url).then((image) => {
if (image.data.length > 0) {
if (p2pTimeouts.get(device.getSerial()) !== undefined) {
clearTimeout(p2pTimeouts.get(device.getSerial()));
p2pTimeouts.delete(device.getSerial());
}
device.updateProperty(types_1.PropertyName.DevicePicture, image, true);
}
else {
//fallback
(0, exports.loadImageOverP2P)(station, device, device.getSerial(), p2pTimeouts);
}
}).catch((err) => {
const error = (0, error_1.ensureError)(err);
logging_1.rootHTTPLogger.debug(`Device load event image - Fallback Error`, { error: (0, utils_1.getError)(error), stationSN: station.getSerial(), deviceSN: device.getSerial(), message: JSON.stringify(message) });
(0, exports.loadImageOverP2P)(station, device, device.getSerial(), p2pTimeouts);
});
}
else {
//fallback
(0, exports.loadImageOverP2P)(station, device, device.getSerial(), p2pTimeouts);
}
}
};
exports.loadEventImage = loadEventImage;
//# sourceMappingURL=utils.js.map

1
build/http/utils.js.map Normal file

File diff suppressed because one or more lines are too long

8
build/index.d.ts vendored Normal file
View File

@ -0,0 +1,8 @@
export * from "./http";
export * from "./p2p";
export * from "./push";
export * from "./interfaces";
export * from "./eufysecurity";
export * from "./error";
export { LoggingCategories, LogLevel, Logger, dummyLogger } from "./logging";
export declare const libVersion: string;

29
build/index.js Normal file
View File

@ -0,0 +1,29 @@
"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 __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.libVersion = exports.dummyLogger = exports.LogLevel = void 0;
__exportStar(require("./http"), exports);
__exportStar(require("./p2p"), exports);
__exportStar(require("./push"), exports);
__exportStar(require("./interfaces"), exports);
__exportStar(require("./eufysecurity"), exports);
__exportStar(require("./error"), exports);
var logging_1 = require("./logging");
Object.defineProperty(exports, "LogLevel", { enumerable: true, get: function () { return logging_1.LogLevel; } });
Object.defineProperty(exports, "dummyLogger", { enumerable: true, get: function () { return logging_1.dummyLogger; } });
// eslint-disable-next-line @typescript-eslint/no-var-requires
exports.libVersion = require("../package.json").version;
//# sourceMappingURL=index.js.map

1
build/index.js.map Normal file
View File

@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,yCAAuB;AACvB,wCAAsB;AACtB,yCAAuB;AACvB,+CAA6B;AAC7B,iDAA+B;AAC/B,0CAAwB;AACxB,qCAA6E;AAAjD,mGAAA,QAAQ,OAAA;AAAU,sGAAA,WAAW,OAAA;AAEzD,8DAA8D;AACjD,QAAA,UAAU,GAAW,OAAO,CAAC,iBAAiB,CAAC,CAAC,OAAO,CAAC"}

142
build/interfaces.d.ts vendored Normal file
View File

@ -0,0 +1,142 @@
import { Readable } from "stream";
import { Device } from "./http/device";
import { HTTPApiPersistentData, Picture, PropertyValue, Schedule } from "./http/interfaces";
import { Station } from "./http/station";
import { DeviceSmartLockMessage } from "./mqtt/model";
import { DatabaseCountByDate, DatabaseQueryLatestInfo, DatabaseQueryLocal, StreamMetadata } from "./p2p/interfaces";
import { CommandResult } from "./p2p/models";
import { TalkbackStream } from "./p2p/talkback";
import { AlarmEvent, DatabaseReturnCode, SmartSafeAlarm911Event, SmartSafeShakeAlarmEvent } from "./p2p/types";
import { Credentials, PushMessage } from "./push/models";
import { Jsonable, LoggingCategories } from ".";
import { LogLevel } from "typescript-logging";
export interface StationIPAddresses {
[index: string]: string;
}
export interface EufySecurityConfig {
username: string;
password: string;
country?: string;
language?: string;
trustedDeviceName?: string;
persistentDir?: string;
persistentData?: string;
p2pConnectionSetup: number;
pollingIntervalMinutes: number;
eventDurationSeconds: number;
acceptInvitations?: boolean;
stationIPAddresses?: StationIPAddresses;
enableEmbeddedPKCS1Support?: boolean;
deviceConfig?: {
simultaneousDetections?: boolean;
};
logging?: {
level?: LogLevel;
categories?: Array<{
category: LoggingCategories;
level: LogLevel;
}>;
};
}
export interface EufySecurityPersistentData {
country: string;
login_hash: string;
openudid: string;
serial_number: string;
cloud_token?: string;
cloud_token_expiration?: number;
push_credentials: Credentials | undefined;
push_persistentIds: string[];
version: string;
httpApi?: HTTPApiPersistentData;
fallbackTrustedDeviceName?: string;
}
export interface EufySecurityEvents {
"device added": (device: Device) => void;
"device removed": (device: Device) => void;
"device property changed": (device: Device, name: string, value: PropertyValue) => void;
"device raw property changed": (device: Device, type: number, value: string) => void;
"device crying detected": (device: Device, state: boolean) => void;
"device sound detected": (device: Device, state: boolean) => void;
"device pet detected": (device: Device, state: boolean) => void;
"device vehicle detected": (device: Device, state: boolean) => void;
"device motion detected": (device: Device, state: boolean) => void;
"device person detected": (device: Device, state: boolean, person: string) => void;
"device stranger person detected": (device: Device, state: boolean) => void;
"device dog detected": (device: Device, state: boolean) => void;
"device dog lick detected": (device: Device, state: boolean) => void;
"device dog poop detected": (device: Device, state: boolean) => void;
"device rings": (device: Device, state: boolean) => void;
"device locked": (device: Device, state: boolean) => void;
"device open": (device: Device, state: boolean) => void;
"device package delivered": (device: Device, state: boolean) => void;
"device package stranded": (device: Device, state: boolean) => void;
"device package taken": (device: Device, state: boolean) => void;
"device someone loitering": (device: Device, state: boolean) => void;
"device radar motion detected": (device: Device, state: boolean) => void;
"device 911 alarm": (device: Device, state: boolean, detail: SmartSafeAlarm911Event) => void;
"device shake alarm": (device: Device, state: boolean, detail: SmartSafeShakeAlarmEvent) => void;
"device wrong try-protect alarm": (device: Device, state: boolean) => void;
"device long time not close": (device: Device, state: boolean) => void;
"device low battery": (device: Device, state: boolean) => void;
"device jammed": (device: Device, state: boolean) => void;
"device pin verified": (device: Device, successfull: boolean) => void;
"device tampering": (device: Device, state: boolean) => void;
"device low temperature": (device: Device, state: boolean) => void;
"device high temperature": (device: Device, state: boolean) => void;
"device pin incorrect": (device: Device, state: boolean) => void;
"device lid stuck": (device: Device, state: boolean) => void;
"device battery fully charged": (device: Device, state: boolean) => void;
"station added": (station: Station) => void;
"station removed": (station: Station) => void;
"station livestream start": (station: Station, device: Device, metadata: StreamMetadata, videostream: Readable, audiostream: Readable) => void;
"station livestream stop": (station: Station, device: Device) => void;
"station download start": (station: Station, device: Device, metadata: StreamMetadata, videoStream: Readable, audioStream: Readable) => void;
"station download finish": (station: Station, device: Device) => void;
"station command result": (station: Station, result: CommandResult) => void;
"station rtsp livestream start": (station: Station, device: Device) => void;
"station rtsp livestream stop": (station: Station, device: Device) => void;
"station rtsp url": (station: Station, device: Device, value: string) => void;
"station guard mode": (station: Station, guardMode: number) => void;
"station current mode": (station: Station, currentMode: number) => void;
"station property changed": (station: Station, name: string, value: PropertyValue) => void;
"station raw property changed": (station: Station, type: number, value: string) => void;
"station alarm event": (station: Station, alarmEvent: AlarmEvent) => void;
"station alarm delay event": (station: Station, alarmDelayEvent: AlarmEvent, alarmDelay: number) => void;
"station alarm armed": (station: Station) => void;
"station alarm arm delay event": (station: Station, armDelay: number) => void;
"station connect": (station: Station) => void;
"station connection error": (station: Station, error: Error) => void;
"station close": (station: Station) => void;
"station talkback start": (station: Station, device: Device, talkbackStream: TalkbackStream) => void;
"station talkback stop": (station: Station, device: Device) => void;
"station image download": (station: Station, file: string, image: Picture) => void;
"station database query latest": (station: Station, returnCode: DatabaseReturnCode, data: Array<DatabaseQueryLatestInfo>) => void;
"station database query local": (station: Station, returnCode: DatabaseReturnCode, data: Array<DatabaseQueryLocal>) => void;
"station database count by date": (station: Station, returnCode: DatabaseReturnCode, data: Array<DatabaseCountByDate>) => void;
"station database delete": (station: Station, returnCode: DatabaseReturnCode, failedIds: Array<unknown>) => void;
"push connect": () => void;
"push close": () => void;
"push message": (message: PushMessage) => void;
"connect": () => void;
"close": () => void;
"connection error": (error: Error) => void;
"tfa request": () => void;
"captcha request": (id: string, captcha: string) => void;
"persistent data": (data: string) => void;
"mqtt connect": () => void;
"mqtt close": () => void;
"mqtt lock message": (message: DeviceSmartLockMessage) => void;
"user added": (device: Device, username: string, schedule?: Schedule) => void;
"user deleted": (device: Device, username: string) => void;
"user error": (device: Device, username: string, error: Error) => void;
"user username updated": (device: Device, username: string) => void;
"user schedule updated": (device: Device, username: string, schedule: Schedule) => void;
"user passcode updated": (device: Device, username: string) => void;
}
export interface ErrorObject {
cause: unknown;
message: string;
context: Jsonable;
stacktrace?: string;
}

3
build/interfaces.js Normal file
View File

@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=interfaces.js.map

1
build/interfaces.js.map Normal file
View File

@ -0,0 +1 @@
{"version":3,"file":"interfaces.js","sourceRoot":"","sources":["../src/interfaces.ts"],"names":[],"mappings":""}

22
build/logging.d.ts vendored Normal file
View File

@ -0,0 +1,22 @@
import { LogLevel } from "typescript-logging";
export type LoggingCategories = "all" | "main" | "http" | "p2p" | "push" | "mqtt";
export { LogLevel };
export interface Logger {
trace(message: unknown, ...args: unknown[]): void;
debug(message: unknown, ...args: unknown[]): void;
info(message: unknown, ...args: unknown[]): void;
warn(message: unknown, ...args: unknown[]): void;
error(message: unknown, ...args: unknown[]): void;
fatal?(message: unknown, ...args: unknown[]): void;
}
export declare const dummyLogger: Logger;
export declare class InternalLogger {
static logger: Logger | undefined;
}
export declare const rootMainLogger: import("typescript-logging-category-style").Category;
export declare const rootHTTPLogger: import("typescript-logging-category-style").Category;
export declare const rootMQTTLogger: import("typescript-logging-category-style").Category;
export declare const rootPushLogger: import("typescript-logging-category-style").Category;
export declare const rootP2PLogger: import("typescript-logging-category-style").Category;
export declare const setLoggingLevel: (category?: LoggingCategories, level?: LogLevel) => void;
export declare const getLoggingLevel: (category?: LoggingCategories) => number;

116
build/logging.js Normal file
View File

@ -0,0 +1,116 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getLoggingLevel = exports.setLoggingLevel = exports.rootP2PLogger = exports.rootPushLogger = exports.rootMQTTLogger = exports.rootHTTPLogger = exports.rootMainLogger = exports.InternalLogger = exports.LogLevel = void 0;
const typescript_logging_1 = require("typescript-logging");
Object.defineProperty(exports, "LogLevel", { enumerable: true, get: function () { return typescript_logging_1.LogLevel; } });
const typescript_logging_category_style_1 = require("typescript-logging-category-style");
class InternalLogger {
static logger;
}
exports.InternalLogger = InternalLogger;
const getMethodName = function () {
const matches = new Error("").stack?.split("\n")[6].match(/ at( new){0,1} ([a-zA-Z0-9_\.]+) /);
if (matches !== null && matches !== undefined && matches[2] !== undefined && matches[2] !== "eval") {
return matches[2];
}
return undefined;
};
const provider = typescript_logging_category_style_1.CategoryProvider.createProvider("EufySecurityClientProvider", {
level: typescript_logging_1.LogLevel.Off,
channel: {
type: "RawLogChannel",
write: (msg, _formatArg) => {
const methodName = getMethodName();
const method = methodName ? `[${methodName}] ` : "";
switch (msg.level) {
case typescript_logging_1.LogLevel.Trace:
if (msg.args)
InternalLogger.logger?.trace(`[${msg.logNames}] ${method}${msg.message}`, ...msg.args);
else
InternalLogger.logger?.trace(`[${msg.logNames}] ${method}${msg.message}`);
break;
case typescript_logging_1.LogLevel.Debug:
if (msg.args)
InternalLogger.logger?.debug(`[${msg.logNames}] ${method}${msg.message}`, ...msg.args);
else
InternalLogger.logger?.debug(`[${msg.logNames}] ${method}${msg.message}`);
break;
case typescript_logging_1.LogLevel.Info:
if (msg.args)
InternalLogger.logger?.info(`[${msg.logNames}] ${method}${msg.message}`, ...msg.args);
else
InternalLogger.logger?.info(`[${msg.logNames}] ${method}${msg.message}`);
break;
case typescript_logging_1.LogLevel.Warn:
if (msg.args)
InternalLogger.logger?.warn(`[${msg.logNames}] ${method}${msg.message}`, ...msg.args);
else
InternalLogger.logger?.warn(`[${msg.logNames}] ${method}${msg.message}`);
break;
case typescript_logging_1.LogLevel.Error:
if (msg.args)
InternalLogger.logger?.error(`[${msg.logNames}] ${method}${msg.message}`, ...msg.args);
else
InternalLogger.logger?.error(`[${msg.logNames}] ${method}${msg.message}`);
break;
case typescript_logging_1.LogLevel.Fatal:
if (InternalLogger.logger && InternalLogger.logger.fatal)
if (msg.args)
InternalLogger.logger.fatal(`[${msg.logNames}] ${method}${msg.message}`, ...msg.args);
else
InternalLogger.logger.fatal(`[${msg.logNames}] ${method}${msg.message}`);
break;
}
},
},
});
exports.rootMainLogger = provider.getCategory("main");
exports.rootHTTPLogger = provider.getCategory("http");
exports.rootMQTTLogger = provider.getCategory("mqtt");
exports.rootPushLogger = provider.getCategory("push");
exports.rootP2PLogger = provider.getCategory("p2p");
const setLoggingLevel = function (category = "all", level = typescript_logging_1.LogLevel.Off) {
switch (category) {
case "all":
provider.updateRuntimeSettings({
level: level
});
break;
case "main":
provider.updateRuntimeSettingsCategory(exports.rootMainLogger, {
level: level
});
break;
case "http":
provider.updateRuntimeSettingsCategory(exports.rootHTTPLogger, {
level: level
});
break;
case "mqtt":
provider.updateRuntimeSettingsCategory(exports.rootMQTTLogger, {
level: level
});
break;
case "p2p":
provider.updateRuntimeSettingsCategory(exports.rootP2PLogger, {
level: level
});
break;
case "push":
provider.updateRuntimeSettingsCategory(exports.rootPushLogger, {
level: level
});
break;
}
};
exports.setLoggingLevel = setLoggingLevel;
const getLoggingLevel = function (category = "all") {
switch (category) {
case "all":
return provider.runtimeConfig.level;
default:
return provider.getCategory(category).logLevel;
}
};
exports.getLoggingLevel = getLoggingLevel;
//# sourceMappingURL=logging.js.map

1
build/logging.js.map Normal file
View File

@ -0,0 +1 @@
{"version":3,"file":"logging.js","sourceRoot":"","sources":["../src/logging.ts"],"names":[],"mappings":"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"}

6
build/mqtt/interface.d.ts vendored Normal file
View File

@ -0,0 +1,6 @@
import { DeviceSmartLockMessage } from "./model";
export interface MQTTServiceEvents {
"connect": () => void;
"close": () => void;
"lock message": (message: DeviceSmartLockMessage) => void;
}

3
build/mqtt/interface.js Normal file
View File

@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=interface.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"interface.js","sourceRoot":"","sources":["../../src/mqtt/interface.ts"],"names":[],"mappings":""}

24
build/mqtt/model.d.ts vendored Normal file
View File

@ -0,0 +1,24 @@
export interface DeviceSmartLockNotifyData {
stationSn: string;
deviceSn: string;
eventType: number;
eventTime: number;
shortUserId: string;
unknown1: string;
nickName: string;
userId: string;
unknown2: string;
deviceName: string;
unknown3: string;
lockState: string;
}
export interface DeviceSmartLockNotify {
timestamp: number;
uuid: string;
data: DeviceSmartLockNotifyData;
}
export interface DeviceSmartLockMessage {
eventType: number;
userId: string;
data: DeviceSmartLockNotify;
}

3
build/mqtt/model.js Normal file
View File

@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=model.js.map

1
build/mqtt/model.js.map Normal file
View File

@ -0,0 +1 @@
{"version":3,"file":"model.js","sourceRoot":"","sources":["../../src/mqtt/model.ts"],"names":[],"mappings":""}

79
build/mqtt/mqtt-eufy.crt Normal file
View File

@ -0,0 +1,79 @@
-----BEGIN CERTIFICATE-----
MIIE0DCCA7igAwIBAgIBBzANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMx
EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoT
EUdvRGFkZHkuY29tLCBJbmMuMTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRp
ZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTExMDUwMzA3MDAwMFoXDTMxMDUwMzA3
MDAwMFowgbQxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQH
EwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjEtMCsGA1UE
CxMkaHR0cDovL2NlcnRzLmdvZGFkZHkuY29tL3JlcG9zaXRvcnkvMTMwMQYDVQQD
EypHbyBEYWRkeSBTZWN1cmUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IC0gRzIwggEi
MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC54MsQ1K92vdSTYuswZLiBCGzD
BNliF44v/z5lz4/OYuY8UhzaFkVLVat4a2ODYpDOD2lsmcgaFItMzEUz6ojcnqOv
K/6AYZ15V8TPLvQ/MDxdR/yaFrzDN5ZBUY4RS1T4KL7QjL7wMDge87Am+GZHY23e
cSZHjzhHU9FGHbTj3ADqRay9vHHZqm8A29vNMDp5T19MR/gd71vCxJ1gO7GyQ5HY
pDNO6rPWJ0+tJYqlxvTV0KaudAVkV4i1RFXULSo6Pvi4vekyCgKUZMQWOlDxSq7n
eTOvDCAHf+jfBDnCaQJsY1L6d8EbyHSHyLmTGFBUNUtpTrw700kuH9zB0lL7AgMB
AAGjggEaMIIBFjAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNV
HQ4EFgQUQMK9J47MNIMwojPX+2yz8LQsgM4wHwYDVR0jBBgwFoAUOpqFBxBnKLbv
9r0FQW4gwZTaD94wNAYIKwYBBQUHAQEEKDAmMCQGCCsGAQUFBzABhhhodHRwOi8v
b2NzcC5nb2RhZGR5LmNvbS8wNQYDVR0fBC4wLDAqoCigJoYkaHR0cDovL2NybC5n
b2RhZGR5LmNvbS9nZHJvb3QtZzIuY3JsMEYGA1UdIAQ/MD0wOwYEVR0gADAzMDEG
CCsGAQUFBwIBFiVodHRwczovL2NlcnRzLmdvZGFkZHkuY29tL3JlcG9zaXRvcnkv
MA0GCSqGSIb3DQEBCwUAA4IBAQAIfmyTEMg4uJapkEv/oV9PBO9sPpyIBslQj6Zz
91cxG7685C/b+LrTW+C05+Z5Yg4MotdqY3MxtfWoSKQ7CC2iXZDXtHwlTxFWMMS2
RJ17LJ3lXubvDGGqv+QqG+6EnriDfcFDzkSnE3ANkR/0yBOtg2DZ2HKocyQetawi
DsoXiWJYRBuriSUBAA/NxBti21G00w9RKpv0vHP8ds42pM3Z2Czqrpv1KrKQ0U11
GIo/ikGQI31bS/6kA1ibRrLDYGCD+H1QQc7CoZDDu+8CL9IVVO5EFdkKrqeKM+2x
LXY2JtwE65/3YR8V3Idv7kaWKK2hJn0KCacuBKONvPi8BDAB
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIEfTCCA2WgAwIBAgIDG+cVMA0GCSqGSIb3DQEBCwUAMGMxCzAJBgNVBAYTAlVT
MSEwHwYDVQQKExhUaGUgR28gRGFkZHkgR3JvdXAsIEluYy4xMTAvBgNVBAsTKEdv
IERhZGR5IENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTQwMTAx
MDcwMDAwWhcNMzEwNTMwMDcwMDAwWjCBgzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT
B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoTEUdvRGFkZHku
Y29tLCBJbmMuMTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRpZmljYXRlIEF1
dGhvcml0eSAtIEcyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv3Fi
CPH6WTT3G8kYo/eASVjpIoMTpsUgQwE7hPHmhUmfJ+r2hBtOoLTbcJjHMgGxBT4H
Tu70+k8vWTAi56sZVmvigAf88xZ1gDlRe+X5NbZ0TqmNghPktj+pA4P6or6KFWp/
3gvDthkUBcrqw6gElDtGfDIN8wBmIsiNaW02jBEYt9OyHGC0OPoCjM7T3UYH3go+
6118yHz7sCtTpJJiaVElBWEaRIGMLKlDliPfrDqBmg4pxRyp6V0etp6eMAo5zvGI
gPtLXcwy7IViQyU0AlYnAZG0O3AqP26x6JyIAX2f1PnbU21gnb8s51iruF9G/M7E
GwM8CetJMVxpRrPgRwIDAQABo4IBFzCCARMwDwYDVR0TAQH/BAUwAwEB/zAOBgNV
HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFDqahQcQZyi27/a9BUFuIMGU2g/eMB8GA1Ud
IwQYMBaAFNLEsNKR1EwRcbNhyz2h/t2oatTjMDQGCCsGAQUFBwEBBCgwJjAkBggr
BgEFBQcwAYYYaHR0cDovL29jc3AuZ29kYWRkeS5jb20vMDIGA1UdHwQrMCkwJ6Al
oCOGIWh0dHA6Ly9jcmwuZ29kYWRkeS5jb20vZ2Ryb290LmNybDBGBgNVHSAEPzA9
MDsGBFUdIAAwMzAxBggrBgEFBQcCARYlaHR0cHM6Ly9jZXJ0cy5nb2RhZGR5LmNv
bS9yZXBvc2l0b3J5LzANBgkqhkiG9w0BAQsFAAOCAQEAWQtTvZKGEacke+1bMc8d
H2xwxbhuvk679r6XUOEwf7ooXGKUwuN+M/f7QnaF25UcjCJYdQkMiGVnOQoWCcWg
OJekxSOTP7QYpgEGRJHjp2kntFolfzq3Ms3dhP8qOCkzpN1nsoX+oYggHFCJyNwq
9kIDN0zmiN/VryTyscPfzLXs4Jlet0lUIDyUGAzHHFIYSaRt4bNYC8nY7NmuHDKO
KHAN4v6mF56ED71XcLNa6R+ghlO773z/aQvgSMO3kwvIClTErF0UZzdsyqUvMQg3
qm5vjLyb4lddJIGvl5echK1srDdMZvNhkREg5L4wn3qkKQmw4TRfZHcYQFHfjDCm
rw==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEh
MB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBE
YWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3
MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRo
ZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3Mg
MiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggEN
ADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCA
PVYYYwhv2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6w
wdhFJ2+qN1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXi
EqITLdiOr18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMY
avx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+
YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0OBBYEFNLE
sNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h
/t2oatTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5
IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmlj
YXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD
ggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wimPQoZ+YeAEW5p5JYXMP80kWNy
OO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKtI3lpjbi2Tc7P
TMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ
HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mER
dEr/VxqHD3VILs9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5Cuf
ReYNnyicsbkqWletNw+vHX/bvZ8=
-----END CERTIFICATE-----

View File

@ -0,0 +1,33 @@
// Copyright: (c) 2022-2024, Patrick Broetto <patrick.broetto@gmail.com>
// MIT License
syntax = "proto3";
package eufy_security_client.lock;
message DeviceSmartLockMessage {
optional uint32 event_type = 1;
optional string user_id = 2;
optional DeviceSmartLockNotify data = 3;
}
message DeviceSmartLockNotify {
optional uint64 timestamp = 1;
optional string uuid = 2;
optional DeviceSmartLockNotifyData data = 3;
}
message DeviceSmartLockNotifyData {
optional string station_sn = 1;
optional string device_sn = 2;
optional uint32 event_type = 3;
optional uint64 event_time = 4;
optional string short_user_id = 5;
optional string unknown1 = 6;
optional string nick_name = 7;
optional string user_id = 8;
optional string unknown2 = 9;
optional string device_name = 10;
optional string unknown3 = 11;
optional string lock_state = 12;
}

28
build/mqtt/service.d.ts vendored Normal file
View File

@ -0,0 +1,28 @@
import { TypedEmitter } from "tiny-typed-emitter";
import { MQTTServiceEvents } from "./interface";
export declare class MQTTService extends TypedEmitter<MQTTServiceEvents> {
private readonly CLIENT_ID_FORMAT;
private readonly USERNAME_FORMAT;
private readonly SUBSCRIBE_NOTICE_FORMAT;
private readonly SUBSCRIBE_LOCK_FORMAT;
private readonly SUBSCRIBE_DOORBELL_FORMAT;
private static proto;
private connected;
private client;
private connecting;
private clientID?;
private androidID?;
private apiBase?;
private email?;
private subscribeLocks;
private deviceSmartLockMessageModel;
private constructor();
static init(): Promise<MQTTService>;
private parseSmartLockMessage;
private getMQTTBrokerUrl;
connect(clientID: string, androidID: string, apiBase: string, email: string): void;
private _subscribeLock;
subscribeLock(deviceSN: string): void;
isConnected(): boolean;
close(): void;
}

177
build/mqtt/service.js Normal file
View File

@ -0,0 +1,177 @@
"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;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.MQTTService = void 0;
const mqtt = __importStar(require("mqtt"));
const tiny_typed_emitter_1 = require("tiny-typed-emitter");
const fse = __importStar(require("fs-extra"));
const path = __importStar(require("path"));
const protobufjs_1 = require("protobufjs");
const utils_1 = require("../utils");
const logging_1 = require("../logging");
const error_1 = require("../error");
class MQTTService extends tiny_typed_emitter_1.TypedEmitter {
CLIENT_ID_FORMAT = "android_EufySecurity_<user_id>_<android_id>";
USERNAME_FORMAT = "eufy_<user_id>";
SUBSCRIBE_NOTICE_FORMAT = "/phone/<user_id>/notice";
SUBSCRIBE_LOCK_FORMAT = "/phone/smart_lock/<device_sn>/push_message";
SUBSCRIBE_DOORBELL_FORMAT = "/phone/doorbell/<device_sn>/push_message";
static proto = null;
connected = false;
client = null;
connecting = false;
clientID;
androidID;
apiBase;
email;
subscribeLocks = [];
deviceSmartLockMessageModel;
constructor() {
super();
this.deviceSmartLockMessageModel = MQTTService.proto.lookupType("DeviceSmartLockMessage");
}
static async init() {
try {
this.proto = await (0, protobufjs_1.load)(path.join(__dirname, "./proto/lock.proto"));
}
catch (error) {
logging_1.rootMainLogger.error("Error loading MQTT proto lock file", { error: (0, error_1.ensureError)(error) });
}
return new MQTTService();
}
parseSmartLockMessage(data) {
const message = this.deviceSmartLockMessageModel.decode(data);
const object = this.deviceSmartLockMessageModel.toObject(message, {
longs: String,
enums: String,
bytes: String,
});
return object;
}
getMQTTBrokerUrl(apiBase) {
switch (apiBase) {
case "https://security-app.eufylife.com":
return "mqtts://security-mqtt.eufylife.com";
case "https://security-app-ci.eufylife.com":
return "mqtts://security-mqtt-ci.eufylife.com";
case "https://security-app-qa.eufylife.com":
case "https://security-app-cn-qa.anker-in.com":
return "mqtts://security-mqtt-qa.eufylife.com";
case "https://security-app-eu.eufylife.com":
return "mqtts://security-mqtt-eu.eufylife.com";
case "https://security-app-short-qa.eufylife.com":
return "mqtts://security-mqtt-short-qa.eufylife.com";
default:
return "mqtts://security-mqtt.eufylife.com";
}
}
connect(clientID, androidID, apiBase, email) {
this.clientID = clientID;
this.androidID = androidID;
this.apiBase = apiBase;
this.email = email;
if (!this.connected && !this.connecting && this.clientID && this.androidID && this.apiBase && this.email && this.subscribeLocks.length > 0) {
this.connecting = true;
this.client = mqtt.connect(this.getMQTTBrokerUrl(apiBase), {
keepalive: 60,
clean: true,
reschedulePings: true,
resubscribe: true,
port: 8789,
username: this.USERNAME_FORMAT.replace("<user_id>", clientID),
password: email,
ca: fse.readFileSync(path.join(__dirname, "./mqtt-eufy.crt")),
clientId: this.CLIENT_ID_FORMAT.replace("<user_id>", clientID).replace("<android_id>", androidID),
rejectUnauthorized: false // Some eufy mqtt servers have an expired certificate :(
});
this.client.on("connect", (_connack) => {
this.connected = true;
this.connecting = false;
this.emit("connect");
this.client.subscribe(this.SUBSCRIBE_NOTICE_FORMAT.replace("<user_id>", clientID), { qos: 1 });
if (this.subscribeLocks.length > 0) {
let lock;
while ((lock = this.subscribeLocks.shift()) !== undefined) {
this._subscribeLock(lock);
}
}
});
this.client.on("close", () => {
this.connected = false;
this.emit("close");
});
this.client.on("error", (error) => {
this.connecting = false;
logging_1.rootMQTTLogger.error("MQTT Error", { error: (0, utils_1.getError)(error) });
if (error.code === 1 || error.code === 2 || error.code === 4 || error.code === 5)
this.client?.end();
});
this.client.on("message", (topic, message, _packet) => {
if (topic.includes("smart_lock")) {
const parsedMessage = this.parseSmartLockMessage(message);
logging_1.rootMQTTLogger.debug("Received a smart lock message over MQTT", { message: parsedMessage });
this.emit("lock message", parsedMessage);
}
else {
logging_1.rootMQTTLogger.debug("MQTT message received", { topic: topic, message: message.toString("hex") });
}
});
}
}
_subscribeLock(deviceSN) {
this.client?.subscribe(this.SUBSCRIBE_LOCK_FORMAT.replace("<device_sn>", deviceSN), { qos: 1 }, (error, granted) => {
if (error) {
logging_1.rootMQTTLogger.error(`Subscribe error for lock ${deviceSN}`, { error: (0, utils_1.getError)(error), deviceSN: deviceSN });
}
if (granted) {
logging_1.rootMQTTLogger.info(`Successfully registered to MQTT notifications for lock ${deviceSN}`);
}
});
}
subscribeLock(deviceSN) {
if (this.connected) {
this._subscribeLock(deviceSN);
}
else {
if (!this.subscribeLocks.includes(deviceSN)) {
this.subscribeLocks.push(deviceSN);
}
if (this.clientID && this.androidID && this.apiBase && this.email)
this.connect(this.clientID, this.androidID, this.apiBase, this.email);
}
}
isConnected() {
return this.connected;
}
close() {
if (this.connected) {
this.client?.end(true);
this.connected = false;
this.connecting = false;
}
}
}
exports.MQTTService = MQTTService;
//# sourceMappingURL=service.js.map

File diff suppressed because one or more lines are too long

59
build/p2p/ble.d.ts vendored Normal file
View File

@ -0,0 +1,59 @@
export declare enum BleParameterIndex {
ZERO = -96,
ONE = -95,
TWO = -94,
THREE = -93,
FOUR = -92,
FIVE = -91,
SIX = -90,
SEVEN = -89,
EIGHT = -88,
NINE = -87,
TEN = -86,
ELEVEN = -85,
TWELVE = -84,
THIRTEEN = -83
}
export declare class BleCommandFactory {
private static readonly HEADER;
private data?;
private commandCode?;
private versionCode?;
private dataType?;
private packageFlag?;
private unknown?;
private additionalDataSeparatorByte?;
private additionalData?;
private responseCode?;
private encrypted?;
private partial?;
static parseLockV12(data: string | Buffer): BleCommandFactory;
static parseSmartSafe(data: string | Buffer): BleCommandFactory;
static parseSmartLock(data: string | Buffer): BleCommandFactory;
toString: () => string;
private setResponseCode;
getResponseCode(): number | undefined;
setVersionCode(version: number): BleCommandFactory;
getVersionCode(): number | undefined;
setCommandCode(command: number): BleCommandFactory;
getCommandCode(): number | undefined;
setDataType(type: number): BleCommandFactory;
getDataType(): number | undefined;
setPackageFlag(flag: number): BleCommandFactory;
getPackageFlag(): number | undefined;
setAdditionalDataSeparator(separator: number): BleCommandFactory;
getAdditionalDataSeparator(): Buffer | undefined;
setAdditionalData(data: Buffer): BleCommandFactory;
getAdditionalData(): Buffer | undefined;
setData(data: Buffer): BleCommandFactory;
getData(): Buffer | undefined;
setUnknown(data: Buffer): BleCommandFactory;
static generateHash(data: Buffer): number;
isEncrypted(): boolean | undefined;
setEncrypted(encrypted: boolean): BleCommandFactory;
isPartial(): boolean | undefined;
setPartial(partial: boolean): BleCommandFactory;
getLockV12Command(): Buffer;
getSmartSafeCommand(): Buffer;
getSmartLockCommand(): Buffer;
}

280
build/p2p/ble.js Normal file
View File

@ -0,0 +1,280 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.BleCommandFactory = exports.BleParameterIndex = void 0;
const error_1 = require("./error");
var BleParameterIndex;
(function (BleParameterIndex) {
BleParameterIndex[BleParameterIndex["ZERO"] = -96] = "ZERO";
BleParameterIndex[BleParameterIndex["ONE"] = -95] = "ONE";
BleParameterIndex[BleParameterIndex["TWO"] = -94] = "TWO";
BleParameterIndex[BleParameterIndex["THREE"] = -93] = "THREE";
BleParameterIndex[BleParameterIndex["FOUR"] = -92] = "FOUR";
BleParameterIndex[BleParameterIndex["FIVE"] = -91] = "FIVE";
BleParameterIndex[BleParameterIndex["SIX"] = -90] = "SIX";
BleParameterIndex[BleParameterIndex["SEVEN"] = -89] = "SEVEN";
BleParameterIndex[BleParameterIndex["EIGHT"] = -88] = "EIGHT";
BleParameterIndex[BleParameterIndex["NINE"] = -87] = "NINE";
BleParameterIndex[BleParameterIndex["TEN"] = -86] = "TEN";
BleParameterIndex[BleParameterIndex["ELEVEN"] = -85] = "ELEVEN";
BleParameterIndex[BleParameterIndex["TWELVE"] = -84] = "TWELVE";
BleParameterIndex[BleParameterIndex["THIRTEEN"] = -83] = "THIRTEEN";
})(BleParameterIndex || (exports.BleParameterIndex = BleParameterIndex = {}));
class BleCommandFactory {
static HEADER = Buffer.from([-1, 9]);
data;
commandCode;
versionCode;
dataType;
packageFlag;
unknown;
additionalDataSeparatorByte;
additionalData;
responseCode;
encrypted;
partial;
static parseLockV12(data) {
if (typeof data === "string") {
data = Buffer.from(data, "hex");
}
if (data.readInt8(0) !== BleCommandFactory.HEADER[0] && data.readInt8(1) !== BleCommandFactory.HEADER[1]) {
throw new error_1.BleInvalidDataHeaderError("Invalid BLE data header");
}
const fac = new BleCommandFactory();
fac.setVersionCode(data.readUint8(4));
fac.setCommandCode(data.readUint8(6));
fac.setDataType(data.readUint8());
fac.setPackageFlag(data.readInt8(7));
fac.setResponseCode(fac.getPackageFlag() === -64 ? data.readUint8(8) : data.readUint8(12));
fac.setData(data.subarray(fac.getPackageFlag() === -64 ? 8 : 12, data.length - 1)); //TODO: Verify if position 8 is correct for data (i think it should be 9 or 13)...
if (BleCommandFactory.generateHash(data.subarray(0, data.length - 1)) !== data.readUint8(data.length - 1)) {
throw new error_1.BleInvalidChecksumError("Invalid BLE data, checksum mismatch");
}
return fac;
}
static parseSmartSafe(data) {
return BleCommandFactory.parseLockV12(data);
}
static parseSmartLock(data) {
if (typeof data === "string") {
data = Buffer.from(data, "hex");
}
if (data.length < 9 || (data.readInt8(0) !== BleCommandFactory.HEADER[0] && data.readInt8(1) !== BleCommandFactory.HEADER[1])) {
throw new error_1.BleInvalidDataHeaderError("Invalid BLE data header");
}
if (BleCommandFactory.generateHash(data.subarray(0, data.length - 1)) !== data.readUint8(data.length - 1)) {
throw new error_1.BleInvalidChecksumError("Invalid BLE data, checksum mismatch");
}
const fac = new BleCommandFactory();
const flags = data.readUint16BE(7);
fac.setVersionCode(data.readUint8(4));
fac.setDataType(data.readUint8(6));
fac.setPartial((flags >> 15) === 1);
fac.setEncrypted(((flags << 1) >> 15) === 1);
fac.setCommandCode(((flags << 4) & 32767) >> 4);
fac.setData(data.subarray(9, data.length - 1));
return fac;
}
toString = () => {
return `BleCommandFactory (versionCode: ${this.versionCode} commandCode: ${this.commandCode} dataType: ${this.dataType} partial: ${this.partial} encrypted: ${this.encrypted} data: ${this.data?.toString("hex")} packageFlag: ${this.packageFlag} responseCode: ${this.responseCode})`;
};
setResponseCode(code) {
this.responseCode = code;
}
getResponseCode() {
return this.responseCode;
}
setVersionCode(version) {
this.versionCode = version;
return this;
}
getVersionCode() {
return this.versionCode;
}
setCommandCode(command) {
this.commandCode = command;
return this;
}
getCommandCode() {
return this.commandCode;
}
setDataType(type) {
this.dataType = type;
return this;
}
getDataType() {
return this.dataType;
}
setPackageFlag(flag) {
this.packageFlag = flag;
return this;
}
getPackageFlag() {
return this.packageFlag;
}
setAdditionalDataSeparator(separator) {
this.additionalDataSeparatorByte = Buffer.from([separator]);
return this;
}
getAdditionalDataSeparator() {
return this.additionalDataSeparatorByte;
}
setAdditionalData(data) {
this.additionalData = data;
return this;
}
getAdditionalData() {
return this.additionalData;
}
setData(data) {
this.data = data;
return this;
}
getData() {
return this.data;
}
setUnknown(data) {
this.unknown = data;
return this;
}
static generateHash(data) {
let result = 0;
for (const value of data) {
result = result ^ value;
}
return result;
}
isEncrypted() {
return this.encrypted;
}
setEncrypted(encrypted) {
this.encrypted = encrypted;
return this;
}
isPartial() {
return this.partial;
}
setPartial(partial) {
this.partial = partial;
return this;
}
getLockV12Command() {
if (this.versionCode === undefined)
throw new error_1.BleVersionCodeError("BleCommandFactory version code value missing");
if (this.dataType === undefined)
throw new error_1.BleDataTypeError("BleCommandFactory data type value missing");
if (this.commandCode === undefined)
throw new error_1.BleCommandCodeError("BleCommandFactory command code value missing");
if (this.data === undefined)
throw new error_1.BleDataError("BleCommandFactory data value missing");
if (this.additionalData === undefined)
throw new error_1.BleAdditionalDataError("BleCommandFactory additional data value missing");
this.setAdditionalDataSeparator(BleParameterIndex.ZERO);
const bVersionCode = Buffer.from([this.versionCode]);
const bDataType = Buffer.from([this.dataType]);
const bCommandCode = Buffer.from([this.commandCode]);
const bPackageFlag = this.packageFlag === undefined ? Buffer.from([-64]) : Buffer.from([this.packageFlag]);
const bAdditionalDataLength = Buffer.from([this.additionalData.length]);
const size = Buffer.allocUnsafe(2);
size.writeInt16LE(BleCommandFactory.HEADER.length +
size.length +
bVersionCode.length +
bDataType.length +
bCommandCode.length +
bPackageFlag.length +
this.additionalDataSeparatorByte.length +
bAdditionalDataLength.length +
this.additionalData.length +
this.data.length +
1 // Hash
);
const data = Buffer.concat([
BleCommandFactory.HEADER,
size,
bVersionCode,
bDataType,
bCommandCode,
bPackageFlag,
this.additionalDataSeparatorByte,
bAdditionalDataLength,
this.additionalData,
this.data
]);
const hash = BleCommandFactory.generateHash(data);
return Buffer.concat([data, Buffer.from([hash])]);
}
getSmartSafeCommand() {
if (this.versionCode === undefined)
throw new error_1.BleVersionCodeError("BleCommandFactory version code value missing");
if (this.dataType === undefined)
throw new error_1.BleDataTypeError("BleCommandFactory data type value missing");
if (this.commandCode === undefined)
throw new error_1.BleCommandCodeError("BleCommandFactory command code value missing");
if (this.data === undefined)
throw new error_1.BleDataError("BleCommandFactory data value missing");
const bVersionCode = Buffer.from([this.versionCode]);
const bDataType = Buffer.from([this.dataType]);
const bCommandCode = Buffer.from([this.commandCode]);
const bPackageFlag = this.packageFlag === undefined ? Buffer.from([-64]) : Buffer.from([this.packageFlag]);
const size = Buffer.allocUnsafe(2);
size.writeInt16LE(BleCommandFactory.HEADER.length +
size.length +
bVersionCode.length +
bDataType.length +
bCommandCode.length +
bPackageFlag.length +
this.data.length +
1 // Hash
);
const data = Buffer.concat([
BleCommandFactory.HEADER,
size,
bVersionCode,
bDataType,
bCommandCode,
bPackageFlag,
this.data
]);
const hash = BleCommandFactory.generateHash(data);
return Buffer.concat([data, Buffer.from([hash])]);
}
getSmartLockCommand() {
if (this.versionCode === undefined)
throw new error_1.BleVersionCodeError("BleCommandFactory version code value missing");
if (this.dataType === undefined)
throw new error_1.BleDataTypeError("BleCommandFactory data type value missing");
if (this.commandCode === undefined)
throw new error_1.BleCommandCodeError("BleCommandFactory command code value missing");
if (this.data === undefined)
throw new error_1.BleDataError("BleCommandFactory data value missing");
const bVersionCode = Buffer.from([this.versionCode]);
const bDataType = Buffer.from([this.dataType]);
const unknown = Buffer.alloc(1);
const partial = false;
const encrypted = true;
const commandCodeEncoded = Buffer.allocUnsafe(2);
commandCodeEncoded.writeInt16BE(((partial ? 1 : 0) << 15) + ((encrypted ? 1 : 0) << 14) + this.commandCode);
const size = Buffer.allocUnsafe(2);
size.writeInt16LE(BleCommandFactory.HEADER.length +
size.length +
bVersionCode.length +
unknown.length +
bDataType.length +
commandCodeEncoded.length +
this.data.length +
1 // Hash
);
const data = Buffer.concat([
BleCommandFactory.HEADER,
size,
bVersionCode,
unknown,
bDataType,
commandCodeEncoded,
this.data
]);
const hash = BleCommandFactory.generateHash(data);
return Buffer.concat([data, Buffer.from([hash])]);
}
}
exports.BleCommandFactory = BleCommandFactory;
//# sourceMappingURL=ble.js.map

1
build/p2p/ble.js.map Normal file

File diff suppressed because one or more lines are too long

49
build/p2p/error.d.ts vendored Normal file
View File

@ -0,0 +1,49 @@
import { BaseError, Jsonable } from "../error";
export declare class BleVersionCodeError extends BaseError {
constructor(message: string, options?: {
cause?: Error;
context?: Jsonable;
});
}
export declare class BleCommandCodeError extends BaseError {
constructor(message: string, options?: {
cause?: Error;
context?: Jsonable;
});
}
export declare class BleDataTypeError extends BaseError {
constructor(message: string, options?: {
cause?: Error;
context?: Jsonable;
});
}
export declare class BleDataError extends BaseError {
constructor(message: string, options?: {
cause?: Error;
context?: Jsonable;
});
}
export declare class BleAdditionalDataError extends BaseError {
constructor(message: string, options?: {
cause?: Error;
context?: Jsonable;
});
}
export declare class BleAdditionalDataSeparatorError extends BaseError {
constructor(message: string, options?: {
cause?: Error;
context?: Jsonable;
});
}
export declare class BleInvalidDataHeaderError extends BaseError {
constructor(message: string, options?: {
cause?: Error;
context?: Jsonable;
});
}
export declare class BleInvalidChecksumError extends BaseError {
constructor(message: string, options?: {
cause?: Error;
context?: Jsonable;
});
}

69
build/p2p/error.js Normal file
View File

@ -0,0 +1,69 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.BleInvalidChecksumError = exports.BleInvalidDataHeaderError = exports.BleAdditionalDataSeparatorError = exports.BleAdditionalDataError = exports.BleDataError = exports.BleDataTypeError = exports.BleCommandCodeError = exports.BleVersionCodeError = void 0;
const error_1 = require("../error");
class BleVersionCodeError extends error_1.BaseError {
constructor(message, options = {}) {
super(message, options);
Object.setPrototypeOf(this, new.target.prototype);
this.name = BleVersionCodeError.name;
}
}
exports.BleVersionCodeError = BleVersionCodeError;
class BleCommandCodeError extends error_1.BaseError {
constructor(message, options = {}) {
super(message, options);
Object.setPrototypeOf(this, new.target.prototype);
this.name = BleCommandCodeError.name;
}
}
exports.BleCommandCodeError = BleCommandCodeError;
class BleDataTypeError extends error_1.BaseError {
constructor(message, options = {}) {
super(message, options);
Object.setPrototypeOf(this, new.target.prototype);
this.name = BleDataTypeError.name;
}
}
exports.BleDataTypeError = BleDataTypeError;
class BleDataError extends error_1.BaseError {
constructor(message, options = {}) {
super(message, options);
Object.setPrototypeOf(this, new.target.prototype);
this.name = BleDataError.name;
}
}
exports.BleDataError = BleDataError;
class BleAdditionalDataError extends error_1.BaseError {
constructor(message, options = {}) {
super(message, options);
Object.setPrototypeOf(this, new.target.prototype);
this.name = BleAdditionalDataError.name;
}
}
exports.BleAdditionalDataError = BleAdditionalDataError;
class BleAdditionalDataSeparatorError extends error_1.BaseError {
constructor(message, options = {}) {
super(message, options);
Object.setPrototypeOf(this, new.target.prototype);
this.name = BleAdditionalDataSeparatorError.name;
}
}
exports.BleAdditionalDataSeparatorError = BleAdditionalDataSeparatorError;
class BleInvalidDataHeaderError extends error_1.BaseError {
constructor(message, options = {}) {
super(message, options);
Object.setPrototypeOf(this, new.target.prototype);
this.name = BleInvalidDataHeaderError.name;
}
}
exports.BleInvalidDataHeaderError = BleInvalidDataHeaderError;
class BleInvalidChecksumError extends error_1.BaseError {
constructor(message, options = {}) {
super(message, options);
Object.setPrototypeOf(this, new.target.prototype);
this.name = BleInvalidChecksumError.name;
}
}
exports.BleInvalidChecksumError = BleInvalidChecksumError;
//# sourceMappingURL=error.js.map

1
build/p2p/error.js.map Normal file
View File

@ -0,0 +1 @@
{"version":3,"file":"error.js","sourceRoot":"","sources":["../../src/p2p/error.ts"],"names":[],"mappings":";;;AAAA,oCAA+C;AAC/C,MAAa,mBAAoB,SAAQ,iBAAS;IAC9C,YAAY,OAAe,EAAE,UAAiD,EAAE;QAC5E,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACxB,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAClD,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC,IAAI,CAAC;IACzC,CAAC;CACJ;AAND,kDAMC;AAED,MAAa,mBAAoB,SAAQ,iBAAS;IAC9C,YAAY,OAAe,EAAE,UAAiD,EAAE;QAC5E,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACxB,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAClD,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC,IAAI,CAAC;IACzC,CAAC;CACJ;AAND,kDAMC;AAED,MAAa,gBAAiB,SAAQ,iBAAS;IAC3C,YAAY,OAAe,EAAE,UAAiD,EAAE;QAC5E,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACxB,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAClD,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC,IAAI,CAAC;IACtC,CAAC;CACJ;AAND,4CAMC;AAED,MAAa,YAAa,SAAQ,iBAAS;IACvC,YAAY,OAAe,EAAE,UAAiD,EAAE;QAC5E,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACxB,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAClD,IAAI,CAAC,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC;IAClC,CAAC;CACJ;AAND,oCAMC;AAED,MAAa,sBAAuB,SAAQ,iBAAS;IACjD,YAAY,OAAe,EAAE,UAAiD,EAAE;QAC5E,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACxB,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAClD,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC,IAAI,CAAC;IAC5C,CAAC;CACJ;AAND,wDAMC;AAED,MAAa,+BAAgC,SAAQ,iBAAS;IAC1D,YAAY,OAAe,EAAE,UAAiD,EAAE;QAC5E,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACxB,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAClD,IAAI,CAAC,IAAI,GAAG,+BAA+B,CAAC,IAAI,CAAC;IACrD,CAAC;CACJ;AAND,0EAMC;AAED,MAAa,yBAA0B,SAAQ,iBAAS;IACpD,YAAY,OAAe,EAAE,UAAiD,EAAE;QAC5E,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACxB,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAClD,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAC,IAAI,CAAC;IAC/C,CAAC;CACJ;AAND,8DAMC;AAED,MAAa,uBAAwB,SAAQ,iBAAS;IAClD,YAAY,OAAe,EAAE,UAAiD,EAAE;QAC5E,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACxB,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAClD,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC,IAAI,CAAC;IAC7C,CAAC;CACJ;AAND,0DAMC"}

8
build/p2p/index.d.ts vendored Normal file
View File

@ -0,0 +1,8 @@
export * from "./interfaces";
export * from "./models";
export * from "./session";
export * from "./types";
export * from "./talkback";
export * from "./ble";
export * from "./error";
export { isPrivateIp, getLocalIpAddress } from "./utils";

28
build/p2p/index.js Normal file
View File

@ -0,0 +1,28 @@
"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 __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getLocalIpAddress = exports.isPrivateIp = void 0;
__exportStar(require("./interfaces"), exports);
__exportStar(require("./models"), exports);
__exportStar(require("./session"), exports);
__exportStar(require("./types"), exports);
__exportStar(require("./talkback"), exports);
__exportStar(require("./ble"), exports);
__exportStar(require("./error"), exports);
var utils_1 = require("./utils");
Object.defineProperty(exports, "isPrivateIp", { enumerable: true, get: function () { return utils_1.isPrivateIp; } });
Object.defineProperty(exports, "getLocalIpAddress", { enumerable: true, get: function () { return utils_1.getLocalIpAddress; } });
//# sourceMappingURL=index.js.map

1
build/p2p/index.js.map Normal file
View File

@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/p2p/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,+CAA6B;AAC7B,2CAAyB;AACzB,4CAA0B;AAC1B,0CAAwB;AACxB,6CAA2B;AAC3B,wCAAsB;AACtB,0CAAwB;AACxB,iCAAyD;AAAhD,oGAAA,WAAW,OAAA;AAAE,0GAAA,iBAAiB,OAAA"}

388
build/p2p/interfaces.d.ts vendored Normal file
View File

@ -0,0 +1,388 @@
import * as NodeRSA from "node-rsa";
import { Readable } from "stream";
import { SortedMap } from "sweet-collections";
import { AlarmMode, DeviceType, MicStatus, ParamType, TriggerType, VideoType } from "../http/types";
import { Address, CmdCameraInfoResponse, CommandResult, CustomData, StorageInfoBodyHB3 } from "./models";
import { TalkbackStream } from "./talkback";
import { AlarmEvent, AudioCodec, CommandType, DatabaseReturnCode, IndoorSoloSmartdropCommandType, P2PDataType, SmartSafeAlarm911Event, SmartSafeShakeAlarmEvent, P2PStorageType, TFCardStatus, VideoCodec, InternalP2PCommandType } from "./types";
export interface P2PClientProtocolEvents {
"alarm mode": (mode: AlarmMode) => void;
"camera info": (cameraInfo: CmdCameraInfoResponse) => void;
"connect": (address: Address) => void;
"close": () => void;
"command": (result: CommandResult) => void;
"download started": (channel: number, metadata: StreamMetadata, videoStream: Readable, audioStream: Readable) => void;
"download finished": (channel: number) => void;
"livestream started": (channel: number, metadata: StreamMetadata, videoStream: Readable, audioStream: Readable) => void;
"livestream stopped": (channel: number) => void;
"livestream error": (channel: number, error: Error) => void;
"wifi rssi": (channel: number, rssi: number) => void;
"rtsp url": (channel: number, rtspUrl: string) => void;
"parameter": (channel: number, param: number, value: string) => void;
"timeout": () => void;
"runtime state": (channel: number, batteryLevel: number, temperature: number) => void;
"charging state": (channel: number, chargeType: number, batteryLevel: number) => void;
"rtsp livestream started": (channel: number) => void;
"rtsp livestream stopped": (channel: number) => void;
"floodlight manual switch": (channel: number, enabled: boolean) => void;
"alarm delay": (alarmDelayEvent: AlarmEvent, alarmDelay: number) => void;
"alarm armed": () => void;
"alarm event": (alarmEvent: AlarmEvent) => void;
"talkback started": (channel: number, talkbackStream: TalkbackStream) => void;
"talkback stopped": (channel: number) => void;
"talkback error": (channel: number, error: Error) => void;
"secondary command": (result: CommandResult) => void;
"jammed": (channel: number) => void;
"low battery": (channel: number) => void;
"shake alarm": (channel: number, detail: SmartSafeShakeAlarmEvent) => void;
"911 alarm": (channel: number, detail: SmartSafeAlarm911Event) => void;
"wrong try-protect alarm": (channel: number) => void;
"sd info ex": (sdStatus: TFCardStatus, sdCapacity: number, sdCapacityAvailable: number) => void;
"image download": (file: string, image: Buffer) => void;
"tfcard status": (channel: number, status: TFCardStatus) => void;
"database query latest": (returnCode: DatabaseReturnCode, data: Array<DatabaseQueryLatestInfo>) => void;
"database query local": (returnCode: DatabaseReturnCode, data: Array<DatabaseQueryLocal>) => void;
"database count by date": (returnCode: DatabaseReturnCode, data: Array<DatabaseCountByDate>) => void;
"database delete": (returnCode: DatabaseReturnCode, failedIds: Array<unknown>) => void;
"sensor status": (channel: number, status: number) => void;
"garage door status": (channel: number, doorId: number, status: number) => void;
"storage info hb3": (channel: number, storageInfo: StorageInfoBodyHB3) => void;
"sequence error": (channel: number, command: number, sequence: number, serialnumber: string) => void;
}
export interface P2PQueueMessage {
p2pCommandType: InternalP2PCommandType;
p2pCommand: P2PCommand;
nestedCommandType?: CommandType;
nestedCommandType2?: number;
timestamp: number;
customData?: CustomData;
}
export interface P2PMessageState {
sequence: number;
commandType: CommandType;
nestedCommandType?: CommandType | IndoorSoloSmartdropCommandType | ParamType;
nestedCommandType2?: number;
channel: number;
data: Buffer;
retries: number;
acknowledged: boolean;
returnCode?: number;
retryTimeout?: NodeJS.Timeout;
timeout?: NodeJS.Timeout;
customData?: CustomData;
}
export interface P2PMessageParts {
[index: number]: Buffer;
}
export interface P2PMessage {
bytesToRead: number;
type: P2PDataType;
seqNo: number;
data: Buffer;
}
export interface P2PDataHeader {
commandId: number;
bytesToRead: number;
channel: number;
signCode: number;
type: number;
}
export interface P2PDataMessage extends P2PDataHeader {
seqNo: number;
dataType: P2PDataType;
data: Buffer;
}
export interface P2PDataMessageBuilder {
header: P2PDataHeader;
bytesRead: number;
messages: P2PMessageParts;
}
export interface P2PDataMessageState {
leftoverData: Buffer;
queuedData: SortedMap<number, P2PMessage>;
rsaKey: NodeRSA | null;
videoStream: Readable | null;
audioStream: Readable | null;
invalidStream: boolean;
p2pStreaming: boolean;
p2pStreamNotStarted: boolean;
p2pStreamChannel: number;
p2pStreamFirstAudioDataReceived: boolean;
p2pStreamFirstVideoDataReceived: boolean;
p2pStreamMetadata: StreamMetadata;
p2pStreamingTimeout?: NodeJS.Timeout;
rtspStream: {
[index: number]: boolean;
};
rtspStreaming: {
[index: number]: boolean;
};
waitForSeqNoTimeout?: NodeJS.Timeout;
waitForAudioData?: NodeJS.Timeout;
receivedFirstIFrame: boolean;
preFrameVideoData: Buffer;
p2pTalkback: boolean;
p2pTalkbackChannel: number;
}
export interface P2PDataMessageVideo {
streamType: number;
videoSeqNo: number;
videoFPS: number;
videoWidth: number;
videoHeight: number;
videoTimestamp: number;
videoDataLength: number;
aesKey: string;
}
export interface P2PDataMessageAudio {
audioType: number;
audioSeqNo: number;
audioTimestamp: number;
audioDataLength: number;
}
export interface StreamMetadata {
videoCodec: VideoCodec;
videoFPS: number;
videoWidth: number;
videoHeight: number;
audioCodec: AudioCodec;
}
export interface DeviceSerial {
[index: number]: {
sn: string;
adminUserId: string;
};
}
export interface P2PCommand {
commandType: CommandType;
value?: number | string;
valueSub?: number;
strValue?: string;
strValueSub?: string;
channel?: number;
}
export interface P2PVideoMessageState {
sequence: number;
channel: number;
data: Buffer;
retries: number;
timeout?: NodeJS.Timeout;
}
export interface P2PDatabaseQueryLatestInfoResponse {
device_sn: string;
payload: {
event_count: number;
crop_hb3_path: string;
crop_cloud_path: string;
};
}
export interface P2PDatabaseCountByDateResponse {
days: string;
count: number;
}
export interface P2PDatabaseQueryLocalHistoryRecordInfo {
record_id: number;
account: string;
station_sn: string;
device_sn: string;
device_type: DeviceType;
start_time: string;
end_time: string;
frame_num: number;
storage_type: P2PStorageType;
storage_cloud: boolean;
cipher_id: number;
vision: number;
video_type: VideoType;
has_lock: boolean;
automation_id: number;
trigger_type: TriggerType;
push_mode: number;
mic_status: MicStatus;
res_change: number;
res_best_width: number;
res_best_height: number;
self_learning: number;
int_reserve: number;
int_extra: number;
storage_path: string;
thumb_path: string;
write_status: number;
str_extra: string;
cloud_path: string;
folder_size: number;
storage_status: number;
storage_label: string;
time_zone: string;
mp4_cloud: string;
snapshot_cloud: string;
table_version: string;
update_time: string;
}
export interface P2PDatabaseQueryLocalRecordCropPictureInfo {
picture_id: number;
record_id: number;
station_sn: string;
device_sn: string;
detection_type: number;
person_id: number;
crop_path: string;
event_time: string;
str_reserve: string;
person_recog_flag: boolean;
crop_pic_quality: number;
pic_marking_flag: boolean;
group_id: number;
int_reserve: number;
crop_id: number;
start_time: string;
reserve2_int: number;
reserve2_date: string;
reserve2_string: string;
storage_type: P2PStorageType;
storage_status: number;
storage_label: string;
table_version: string;
update_time: string;
}
export interface P2PDatabaseQueryLocalResponse {
payload: Array<P2PDatabaseQueryLocalHistoryRecordInfo> | Array<P2PDatabaseQueryLocalRecordCropPictureInfo>;
table_name: string;
}
export interface P2PDatabaseDeleteResponse {
failed_delete: Array<unknown>;
}
export interface P2PDatabaseResponse {
data: Array<P2PDatabaseQueryLatestInfoResponse> | Array<P2PDatabaseCountByDateResponse> | Array<P2PDatabaseQueryLocalResponse> | P2PDatabaseDeleteResponse;
start_id?: number;
end_id?: number;
count?: number;
transaction: string;
table: string;
cmd: number;
mIntRet: DatabaseReturnCode;
version: string;
msg: string;
}
export interface DatabaseQueryLatestInfoBase {
device_sn: string;
event_count: number;
}
export interface DatabaseQueryLatestInfoCloud extends DatabaseQueryLatestInfoBase {
crop_cloud_path: string;
}
export interface DatabaseQueryLatestInfoLocal extends DatabaseQueryLatestInfoBase {
crop_local_path: string;
}
export type DatabaseQueryLatestInfo = DatabaseQueryLatestInfoCloud | DatabaseQueryLatestInfoLocal;
export interface DatabaseCountByDate {
day: Date;
count: number;
}
export interface HistoryRecordInfo {
device_type: DeviceType;
account: string;
start_time: Date;
end_time: Date;
frame_num: number;
storage_type: P2PStorageType;
storage_cloud: boolean;
cipher_id: number;
vision: number;
video_type: VideoType;
has_lock: boolean;
automation_id: number;
trigger_type: TriggerType;
push_mode: number;
mic_status: MicStatus;
res_change: number;
res_best_width: number;
res_best_height: number;
self_learning: number;
storage_path: string;
thumb_path: string;
write_status: number;
cloud_path: string;
folder_size: number;
storage_status: number;
storage_label: string;
time_zone: string;
mp4_cloud: string;
snapshot_cloud: string;
table_version: string;
}
export interface CropPictureInfo {
picture_id: number;
detection_type: number;
person_id: number;
crop_path: string;
event_time: Date | null;
person_recog_flag: boolean;
crop_pic_quality: number;
pic_marking_flag: boolean;
group_id: number;
crop_id: number;
start_time: Date;
storage_type: P2PStorageType;
storage_status: number;
storage_label: string;
table_version: string;
update_time: string;
}
export interface DatabaseQueryLocal {
record_id: number;
station_sn: string;
device_sn?: string;
history: HistoryRecordInfo;
picture: Array<CropPictureInfo>;
}
export interface RGBColor {
red: number;
green: number;
blue: number;
}
export interface InternalColoredLighting {
color: number;
}
export interface DynamicLighting {
name: string;
mode: number;
speed: number;
colors: Array<RGBColor>;
}
export interface InternalDynamicLighting {
name: string;
mode: number;
id: number;
speed: number;
colors: Array<number>;
}
export interface MotionZonePoint {
x: number;
y: number;
}
export interface MotionZonePoints {
points: Array<MotionZonePoint>;
}
export interface MotionZone {
polygens: Array<MotionZonePoints>;
}
export interface VideoStreamingRecordingQuality {
mode_0: {
quality: number;
};
mode_1: {
quality: number;
};
cur_mode: number;
}
export interface CrossTrackingGroupEntry {
value: Array<string>;
}
export interface CustomDataType {
[index: number]: {
channel: number;
customData: CustomData;
timestamp: number;
};
}

3
build/p2p/interfaces.js Normal file
View File

@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=interfaces.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"interfaces.js","sourceRoot":"","sources":["../../src/p2p/interfaces.ts"],"names":[],"mappings":""}

284
build/p2p/models.d.ts vendored Normal file
View File

@ -0,0 +1,284 @@
import { PropertyValue } from "../http";
import { CommandName, PropertyName } from "../http/types";
import { SmartSafeEventValueDetail } from "../push/models";
import { CommandType } from "./types";
export interface Address {
host: string;
port: number;
}
export interface CmdCameraInfoResponse {
params: Array<{
dev_type: number;
param_type: number;
param_value: string;
}>;
main_sw_version: string;
sec_sw_version: string;
db_bypass_str?: Array<{
channel: number;
param_type: number;
param_value: string;
}>;
}
export interface PropertyData {
name: PropertyName;
value: PropertyValue;
}
export interface CommandData {
name: CommandName;
value?: any;
}
export interface CustomData {
property?: PropertyData;
command?: CommandData;
onSuccess?: () => void;
onFailure?: () => void;
}
export interface CommandResult {
customData?: CustomData;
command_type: CommandType;
channel: number;
return_code: number;
}
export interface CmdNotifyPayload {
cmd: number;
payload: ESLStationP2PThroughData | ESLAdvancedLockStatusNotification | SmartSafeSettingsNotification | SmartSafeStatusNotification | ESLBleV12P2PThroughData | EntrySensorStatus | GarageDoorStatus | StorageInfoHB3 | SmartLockP2PSequenceData | string;
payloadLen?: number;
}
export interface ESLStationP2PThroughData {
channel?: number;
lock_cmd: number;
lock_payload: string;
seq_num?: number;
stationSn?: string;
}
export interface ESLAdvancedLockStatusNotification {
code: number;
slBattery: string;
slState: string;
trigger: number;
}
export interface ESLAdvancedLockStatusNotificationT8530 extends ESLAdvancedLockStatusNotification {
slOpenDirection: string;
}
export interface SmartSafeSettingsNotification {
data: string;
prj_id: number;
}
export interface SmartSafeStatusNotification {
event_type: number;
event_time: number;
event_value: number | SmartSafeEventValueDetail;
}
export interface SmartSafeNotificationResponse {
versionCode: number;
commandCode: number;
packageFlag: number;
dataType: number;
responseCode: number;
data: Buffer;
}
export interface LockAdvancedOnOffRequestBasePayload {
shortUserId: string;
slOperation: number;
userId: string;
userName: string;
}
export interface LockAdvancedOnOffRequestPayload extends LockAdvancedOnOffRequestBasePayload {
seq_num: number;
}
export interface AdvancedLockSetParamsType {
[index: string]: unknown;
autoLockTime: number;
isAutoLock: number;
isLockNotification: number;
isNotification: number;
isOneTouchLock: number;
isSchedule: number;
isScramblePasscode: number;
isUnLockNotification: number;
isWrongTryProtect: number;
lockDownTime: number;
lockSound: number;
paramType: number;
scheduleEnd: string;
scheduleStart: string;
wrongTryTime: number;
seq_num: number;
}
export interface AdvancedLockSetParamsTypeT8520 {
[index: string]: unknown;
autoLockTime: number;
isAutoLock: number;
isLockNotification: number;
isNotification: number;
isOneTouchLock: number;
isSchedule: number;
isScramblePasscode: number;
isUnLockNotification: number;
isWrongTryProtect: number;
lockDownTime: number;
lockOpenDirection: number;
lockVolume: number;
nightVisionEnhance: number;
openLeftAlarmEnable: number;
openLeftAlarmScheduleEnd: string;
openLeftAlarmScheduleStart: string;
openLeftAlarmScheduled: number;
openLeftAlarmTimer: number;
openLeftAlarmWays: number;
paramType: number;
scheduleEnd: string;
scheduleStart: string;
tamperAlarmEnable: number;
tamperAlarmScheduleEnd: string;
tamperAlarmScheduleStart: string;
tamperAlarmScheduled: number;
tamperAlarmWays: number;
wrongTryTime: number;
}
export interface LockP2PCommandType {
commandType: CommandType;
value: string;
channel: number;
aesKey: string;
}
export interface LockP2PCommandPayloadType {
key: string;
account_id: string;
cmd: CommandType;
mChannel: number;
mValue3: number;
payload: string;
}
export interface ESLBleV12P2PThroughData {
dev_sn: string;
lock_payload: string;
}
export interface LockV12P2PCommandPayloadType {
account_id: string;
cmd: CommandType;
mChannel: number;
mValue3: number;
payload: {
apiCommand: number;
lock_payload: string;
seq_num: number;
};
}
export interface LockV12P2PCommandType {
commandType: CommandType;
value: string;
}
export interface SmartSafeP2PCommandPayloadType {
account_id: string;
cmd: CommandType;
mChannel: number;
mValue3: number;
payload: {
data: string;
prj_id: CommandType;
seq_num: number;
};
}
export interface SmartSafeP2PCommandType {
commandType: CommandType;
value: string;
channel: number;
}
export interface CmdDatabaseImageResponse {
file: string;
content: string;
}
export interface EntrySensorStatus {
status: number;
}
export interface GarageDoorStatus {
type: number;
notify_tag: string;
door_id: number;
}
export interface StorageInfoHB3 {
cmd: number;
version: number;
mIntRet: number;
msg: string;
old_storage_label: string;
cur_storage_label: string;
body: StorageInfoBodyHB3;
}
export interface StorageInfoBodyHB3 {
body_version: number;
storage_days: number;
storage_events: number;
con_video_hours: number;
format_transaction: string;
format_errcode: number;
hdd_info: StorageInfoHddHB3;
move_disk_info: StorageInfoMoveDiskInfoHB3;
emmc_info: StorageInfoEmmcHB3;
}
export interface StorageInfoHddHB3 {
serial_number: string;
disk_path: string;
disk_size: number;
system_size: number;
disk_used: number;
video_used: number;
video_size: number;
cur_temperate: number;
parted_status: number;
work_status: number;
hdd_label: string;
health: number;
device_module: string;
hdd_type: number;
}
export interface StorageInfoMoveDiskInfoHB3 {
disk_path: string;
disk_size: number;
disk_used: number;
part_layout_arr: string[];
data: string[];
}
export interface StorageInfoEmmcHB3 {
disk_nominal: number;
disk_size: number;
system_size: number;
disk_used: number;
data_used_percent: number;
swap_size: number;
video_size: number;
video_used: number;
data_partition_size: number;
eol_percent: number;
work_status: number;
health: number;
}
export interface SmartLockP2PCommandPayloadType {
account_id: string;
cmd: CommandType;
mChannel: number;
mValue3: number;
payload: {
apiCommand: number;
lock_payload: string;
seq_num: number;
time: number;
};
}
export interface SmartLockP2PCommandType {
commandType: CommandType;
value: string;
}
export interface SmartLockP2PThroughData {
dev_sn: string;
lock_payload: string;
time: string;
}
export interface SmartLockP2PSequenceData {
lock_cmd: number;
seq_num: number;
dev_sn: string;
bus_type?: number;
}

3
build/p2p/models.js Normal file
View File

@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=models.js.map

1
build/p2p/models.js.map Normal file
View File

@ -0,0 +1 @@
{"version":3,"file":"models.js","sourceRoot":"","sources":["../../src/p2p/models.ts"],"names":[],"mappings":""}

186
build/p2p/session.d.ts vendored Normal file
View File

@ -0,0 +1,186 @@
import { TypedEmitter } from "tiny-typed-emitter";
import * as NodeRSA from "node-rsa";
import { Address, CustomData } from "./models";
import { CommandType, P2PDataType, P2PConnectionType } from "./types";
import { P2PClientProtocolEvents, P2PCommand } from "./interfaces";
import { StationListResponse } from "../http/models";
import { HTTPApi } from "../http/api";
export declare class P2PClientProtocol extends TypedEmitter<P2PClientProtocolEvents> {
private readonly MAX_RETRIES;
private readonly MAX_COMMAND_RESULT_WAIT;
private readonly MAX_GATEWAY_COMMAND_RESULT_WAIT;
private readonly MAX_CONNECTION_TIMEOUT;
private readonly MAX_AKNOWLEDGE_TIMEOUT;
private readonly MAX_LOOKUP_TIMEOUT;
private readonly LOCAL_LOOKUP_RETRY_TIMEOUT;
private readonly LOOKUP_RETRY_TIMEOUT;
private readonly LOOKUP2_TIMEOUT;
private readonly LOOKUP2_RETRY_TIMEOUT;
private readonly MAX_EXPECTED_SEQNO_WAIT;
private readonly HEARTBEAT_INTERVAL;
private readonly MAX_COMMAND_QUEUE_TIMEOUT;
private readonly AUDIO_CODEC_ANALYZE_TIMEOUT;
private readonly KEEPALIVE_INTERVAL;
private readonly ESD_DISCONNECT_TIMEOUT;
private readonly MAX_STREAM_DATA_WAIT;
private readonly RESEND_NOT_ACKNOWLEDGED_COMMAND;
private readonly UDP_RECVBUFFERSIZE_BYTES;
private readonly MAX_PAYLOAD_BYTES;
private readonly MAX_PACKET_BYTES;
private readonly MAX_VIDEO_PACKET_BYTES;
private readonly P2P_DATA_HEADER_BYTES;
private readonly MAX_SEQUENCE_NUMBER;
private readonly LOOP_RUNAWAY_LIMIT;
private readonly SEQUENCE_PROCESSING_BOUNDARY;
private socket;
private binded;
private connected;
private connecting;
private terminating;
private p2pTurnHandshaking;
private p2pTurnConfirmed;
private seqNumber;
private offsetDataSeqNumber;
private videoSeqNumber;
private lockSeqNumber;
private expectedSeqNo;
private currentMessageBuilder;
private currentMessageState;
private talkbackStream?;
private downloadTotalBytes;
private downloadReceivedBytes;
private cloudAddresses;
private messageStates;
private messageVideoStates;
private sendQueue;
private connectTimeout?;
private lookupTimeout?;
private localLookupRetryTimeout?;
private lookupRetryTimeout?;
private lookup2Timeout?;
private lookup2RetryTimeout?;
private heartbeatTimeout?;
private keepaliveTimeout?;
private esdDisconnectTimeout?;
private secondaryCommandTimeout?;
private connectTime;
private lastPong;
private lastPongData;
private connectionType;
private energySavingDevice;
private p2pSeqMapping;
private p2pDataSeqNumber;
private connectAddress;
private localIPAddress;
private preferredIPAddress;
private listeningPort;
private dskKey;
private dskExpiration;
private deviceSNs;
private api;
private rawStation;
private customDataStaging;
private lockPublicKey;
private lockAESKeys;
private channel;
private encryption;
private p2pKey?;
private enableEmbeddedPKCS1Support;
constructor(rawStation: StationListResponse, api: HTTPApi, ipAddress?: string, listeningPort?: number, publicKey?: string, enableEmbeddedPKCS1Support?: boolean);
private _incrementSequence;
private _isBetween;
private _wasSequenceNumberAlreadyProcessed;
private _initialize;
private initializeMessageBuilder;
private initializeMessageState;
private _clearTimeout;
private _clearMessageStateTimeouts;
private _clearMessageVideoStateTimeouts;
private _clearHeartbeatTimeout;
private _clearKeepaliveTimeout;
private _clearConnectTimeout;
private _clearLookupTimeout;
private _clearLocalLookupRetryTimeout;
private _clearLookupRetryTimeout;
private _clearLookup2RetryTimeout;
private _clearLookup2Timeout;
private _clearESDDisconnectTimeout;
private _clearSecondaryCommandTimeout;
private sendMessage;
private _disconnected;
private closeEnergySavingDevice;
private renewDSKKey;
private localLookup;
private cloudLookup;
private cloudLookup2;
private cloudLookupWithTurnServer;
private localLookupByAddress;
private cloudLookupByAddress;
private cloudLookupByAddress2;
private cloudLookupByAddressWithTurnServer;
isConnected(): boolean;
private _startConnectTimeout;
private _connect;
private lookup;
connect(host?: string): Promise<void>;
private sendCamCheck;
private sendCamCheck2;
sendPing(address: Address): Promise<void>;
sendCommandWithIntString(p2pcommand: P2PCommand, customData?: CustomData): void;
sendCommandWithInt(p2pcommand: P2PCommand, customData?: CustomData): void;
sendCommandWithStringPayload(p2pcommand: P2PCommand, customData?: CustomData): void;
sendCommandWithString(p2pcommand: P2PCommand, customData?: CustomData): void;
sendCommandPing(channel?: number): void;
sendCommandDevicePing(channel?: number): void;
sendCommandWithoutData(commandType: CommandType, channel?: number): void;
private sendQueuedMessage;
private sendCommand;
private resendNotAcknowledgedCommand;
private _sendCommand;
private handleMsg;
private parseDataMessage;
private handleData;
private isIFrame;
private waitForStreamData;
private handleDataBinaryAndVideo;
private handleDataControl;
private sendAck;
private getDataType;
close(): Promise<void>;
private getHeartbeatInterval;
private onClose;
private onError;
private scheduleHeartbeat;
private scheduleP2PKeepalive;
getDownloadRSAPrivateKey(): NodeRSA;
setDownloadRSAPrivateKeyPem(pem: string): void;
getRSAPrivateKey(): NodeRSA | null;
private initializeStream;
private endStream;
private endRTSPStream;
private emitStreamStartEvent;
private emitStreamStopEvent;
isStreaming(channel: number, datatype: P2PDataType): boolean;
isLiveStreaming(channel: number): boolean;
private isCurrentlyStreaming;
isRTSPLiveStreaming(channel: number): boolean;
isDownloading(channel: number): boolean;
getLockSequenceNumber(): number;
incLockSequenceNumber(): number;
setConnectionType(type: P2PConnectionType): void;
getConnectionType(): P2PConnectionType;
isEnergySavingDevice(): boolean;
private getDSKKeys;
updateRawStation(value: StationListResponse): void;
private initializeTalkbackStream;
private sendTalkbackAudioFrame;
private onTalkbackStreamClose;
private onTalkbackStreamError;
private _sendVideoData;
isTalkbackOngoing(channel: number): boolean;
startTalkback(channel?: number): void;
stopTalkback(channel?: number): void;
setLockAESKey(commandCode: number, aesKey: string): void;
getLockAESKey(commandCode: number): string | undefined;
isConnecting(): boolean;
}

2678
build/p2p/session.js Normal file

File diff suppressed because it is too large Load Diff

1
build/p2p/session.js.map Normal file

File diff suppressed because one or more lines are too long

8
build/p2p/talkback.d.ts vendored Normal file
View File

@ -0,0 +1,8 @@
import { Transform } from "stream";
export declare class TalkbackStream extends Transform {
private isStreaming;
constructor();
_transform(data: Buffer, _encoding: string, callback: (err?: Error | null) => void): void;
startTalkback(): void;
stopTalkback(): void;
}

23
build/p2p/talkback.js Normal file
View File

@ -0,0 +1,23 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TalkbackStream = void 0;
const stream_1 = require("stream");
class TalkbackStream extends stream_1.Transform {
isStreaming = false;
constructor() {
super();
}
_transform(data, _encoding, callback) {
if (this.isStreaming)
this.push(data);
callback();
}
startTalkback() {
this.isStreaming = true;
}
stopTalkback() {
this.isStreaming = false;
}
}
exports.TalkbackStream = TalkbackStream;
//# sourceMappingURL=talkback.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"talkback.js","sourceRoot":"","sources":["../../src/p2p/talkback.ts"],"names":[],"mappings":";;;AAAA,mCAAmC;AAEnC,MAAa,cAAe,SAAQ,kBAAS;IAEjC,WAAW,GAAG,KAAK,CAAC;IAE5B;QACI,KAAK,EAAE,CAAC;IACZ,CAAC;IAED,UAAU,CAAC,IAAY,EAAE,SAAiB,EAAE,QAAsC;QAC9E,IAAG,IAAI,CAAC,WAAW;YACf,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpB,QAAQ,EAAE,CAAC;IACf,CAAC;IAEM,aAAa;QAChB,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;IAC5B,CAAC;IAEM,YAAY;QACf,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC;IAC7B,CAAC;CACJ;AArBD,wCAqBC"}

1164
build/p2p/types.d.ts vendored Normal file

File diff suppressed because it is too large Load Diff

1219
build/p2p/types.js Normal file

File diff suppressed because it is too large Load Diff

1
build/p2p/types.js.map Normal file

File diff suppressed because one or more lines are too long

72
build/p2p/utils.d.ts vendored Normal file
View File

@ -0,0 +1,72 @@
import { Socket } from "dgram";
import NodeRSA from "node-rsa";
import { P2PMessageParts, P2PMessageState, P2PQueueMessage, RGBColor } from "./interfaces";
import { CommandType, ESLCommand, LockV12P2PCommand, SmartSafeCommandCode, VideoCodec, EncryptionType, SmartLockP2PCommand, SmartLockFunctionType, SmartLockCommand } from "./types";
import { Address, LockP2PCommandType, SmartSafeNotificationResponse, SmartSafeP2PCommandType } from "./models";
import { DeviceType } from "../http/types";
export declare const MAGIC_WORD = "XZYH";
export declare const isPrivateIp: (ip: string) => boolean;
export declare const getLocalIpAddress: (init?: string) => string;
export declare const isP2PCommandEncrypted: (cmd: CommandType) => boolean;
export declare const getP2PCommandEncryptionKey: (serialNumber: string, p2pDid: string) => string;
export declare const encryptP2PData: (data: Buffer, key: Buffer) => Buffer;
export declare const decryptP2PData: (data: Buffer, key: Buffer) => Buffer;
export declare const paddingP2PData: (data: Buffer, blocksize?: number) => Buffer;
export declare const buildLookupWithKeyPayload: (socket: Socket, p2pDid: string, dskKey: string) => Buffer;
export declare const buildLookupWithKeyPayload2: (p2pDid: string, dskKey: string) => Buffer;
export declare const buildLookupWithKeyPayload3: (p2pDid: string, address: Address, data: Buffer) => Buffer;
export declare const buildCheckCamPayload: (p2pDid: string) => Buffer;
export declare const buildCheckCamPayload2: (p2pDid: string, data: Buffer) => Buffer;
export declare const buildIntCommandPayload: (encryptionType: EncryptionType, encryptionKey: Buffer | undefined, serialNumber: string, p2pDid: string, commandType: CommandType, value: number, strValue?: string, channel?: number) => Buffer;
export declare const buildStringTypeCommandPayload: (encryptionType: EncryptionType, encryptionKey: Buffer | undefined, serialNumber: string, p2pDid: string, commandType: CommandType, strValue: string, strValueSub: string, channel?: number) => Buffer;
export declare const buildIntStringCommandPayload: (encryptionType: EncryptionType, encryptionKey: Buffer | undefined, serialNumber: string, p2pDid: string, commandType: CommandType, value: number, valueSub?: number, strValue?: string, strValueSub?: string, channel?: number) => Buffer;
export declare const sendMessage: (socket: Socket, address: {
host: string;
port: number;
}, msgID: Buffer, payload?: Buffer) => Promise<number>;
export declare const hasHeader: (msg: Buffer, searchedType: Buffer) => boolean;
export declare const buildCommandHeader: (seqNumber: number, commandType: CommandType, p2pDataTypeHeader?: Buffer | null) => Buffer;
export declare const buildCommandWithStringTypePayload: (encryptionType: EncryptionType, encryptionKey: Buffer | undefined, serialNumber: string, p2pDid: string, commandType: CommandType, value: string, channel?: number) => Buffer;
export declare const sortP2PMessageParts: (messages: P2PMessageParts) => Buffer;
export declare const getRSAPrivateKey: (pem: string, enableEmbeddedPKCS1Support?: boolean) => NodeRSA;
export declare const getNewRSAPrivateKey: (enableEmbeddedPKCS1Support?: boolean) => NodeRSA;
export declare const decryptAESData: (hexkey: string, data: Buffer) => Buffer;
export declare const findStartCode: (data: Buffer) => boolean;
export declare const isIFrame: (data: Buffer) => boolean;
export declare const decryptLockAESData: (key: string, iv: string, data: Buffer) => Buffer;
export declare const encryptLockAESData: (key: string, iv: string, data: Buffer) => Buffer;
export declare const generateBasicLockAESKey: (adminID: string, stationSN: string) => string;
export declare const getCurrentTimeInSeconds: () => number;
export declare const generateLockSequence: (deviceType?: DeviceType, serialnumber?: string) => number;
export declare const encodeLockPayload: (data: string) => Buffer;
export declare const getLockVectorBytes: (data: string) => string;
export declare const decodeLockPayload: (data: Buffer) => string;
export declare const decodeBase64: (data: string) => Buffer;
export declare const eslTimestamp: (timestamp_in_sec?: number) => number[];
export declare const generateAdvancedLockAESKey: () => string;
export declare const getVideoCodec: (data: Buffer) => VideoCodec;
export declare const checkT8420: (serialNumber: string) => boolean;
export declare const buildVoidCommandPayload: (channel?: number) => Buffer;
export declare function isP2PQueueMessage(type: P2PQueueMessage | P2PMessageState): type is P2PQueueMessage;
export declare const encryptPayloadData: (data: string | Buffer, key: Buffer, iv: Buffer) => Buffer;
export declare const decryptPayloadData: (data: Buffer, key: Buffer, iv: Buffer) => Buffer;
export declare const eufyKDF: (key: Buffer) => Buffer;
export declare const getAdvancedLockKey: (key: string, publicKey: string) => string;
export declare const getLockV12Key: (key: string, publicKey: string) => string;
export declare const buildTalkbackAudioFrameHeader: (audioData: Buffer, channel?: number) => Buffer;
export declare const decodeP2PCloudIPs: (data: string) => Array<Address>;
export declare const decodeSmartSafeData: (deviceSN: string, data: Buffer) => SmartSafeNotificationResponse;
export declare const getSmartSafeP2PCommand: (deviceSN: string, user_id: string, command: CommandType, intCommand: SmartSafeCommandCode, channel: number, sequence: number, data: Buffer) => SmartSafeP2PCommandType;
export declare const getLockP2PCommand: (deviceSN: string, user_id: string, command: CommandType, channel: number, lockPublicKey: string, payload: any) => LockP2PCommandType;
export declare const getLockV12P2PCommand: (deviceSN: string, user_id: string, command: CommandType | ESLCommand, channel: number, lockPublicKey: string, sequence: number, data: Buffer) => LockV12P2PCommand;
export declare const DecimalToRGBColor: (color: number) => RGBColor;
export declare const RGBColorToDecimal: (color: RGBColor) => number;
export declare const getNullTerminatedString: (data: Buffer, encoding?: BufferEncoding) => string;
export declare const isUsbCharging: (value: number) => boolean;
export declare const isSolarCharging: (value: number) => boolean;
export declare const isPlugSolarCharging: (value: number) => boolean;
export declare const isCharging: (value: number) => boolean;
export declare const getSmartLockCurrentTimeInSeconds: () => number;
export declare const generateSmartLockAESKey: (adminUserId: string, time: number) => Buffer;
export declare const getSmartLockP2PCommand: (deviceSN: string, user_id: string, command: CommandType | SmartLockCommand, channel: number, sequence: number, data: Buffer, functionType?: SmartLockFunctionType) => SmartLockP2PCommand;
export declare const readNullTerminatedBuffer: (input: Buffer) => Buffer;

824
build/p2p/utils.js Normal file
View File

@ -0,0 +1,824 @@
"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.getLockP2PCommand = exports.getSmartSafeP2PCommand = exports.decodeSmartSafeData = exports.decodeP2PCloudIPs = exports.buildTalkbackAudioFrameHeader = exports.getLockV12Key = exports.getAdvancedLockKey = exports.eufyKDF = exports.decryptPayloadData = exports.encryptPayloadData = exports.buildVoidCommandPayload = exports.checkT8420 = exports.getVideoCodec = exports.generateAdvancedLockAESKey = exports.eslTimestamp = exports.decodeBase64 = exports.decodeLockPayload = exports.getLockVectorBytes = exports.encodeLockPayload = exports.generateLockSequence = exports.getCurrentTimeInSeconds = exports.generateBasicLockAESKey = exports.encryptLockAESData = exports.decryptLockAESData = exports.isIFrame = exports.findStartCode = exports.decryptAESData = exports.getNewRSAPrivateKey = exports.getRSAPrivateKey = exports.sortP2PMessageParts = exports.buildCommandWithStringTypePayload = exports.buildCommandHeader = exports.hasHeader = exports.sendMessage = exports.buildIntStringCommandPayload = exports.buildStringTypeCommandPayload = exports.buildIntCommandPayload = exports.buildCheckCamPayload2 = exports.buildCheckCamPayload = exports.buildLookupWithKeyPayload3 = exports.buildLookupWithKeyPayload2 = exports.buildLookupWithKeyPayload = exports.paddingP2PData = exports.decryptP2PData = exports.encryptP2PData = exports.getP2PCommandEncryptionKey = exports.isP2PCommandEncrypted = exports.getLocalIpAddress = exports.isPrivateIp = exports.MAGIC_WORD = void 0;
exports.readNullTerminatedBuffer = exports.getSmartLockP2PCommand = exports.generateSmartLockAESKey = exports.getSmartLockCurrentTimeInSeconds = exports.isCharging = exports.isPlugSolarCharging = exports.isSolarCharging = exports.isUsbCharging = exports.getNullTerminatedString = exports.RGBColorToDecimal = exports.DecimalToRGBColor = exports.getLockV12P2PCommand = void 0;
exports.isP2PQueueMessage = isP2PQueueMessage;
const node_rsa_1 = __importDefault(require("node-rsa"));
const CryptoJS = __importStar(require("crypto-js"));
const crypto_1 = require("crypto");
const os = __importStar(require("os"));
const types_1 = require("./types");
const device_1 = require("../http/device");
const ble_1 = require("./ble");
const logging_1 = require("../logging");
exports.MAGIC_WORD = "XZYH";
const isPrivateIp = (ip) => /^(::f{4}:)?10\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$/i.test(ip) ||
/^(::f{4}:)?192\.168\.([0-9]{1,3})\.([0-9]{1,3})$/i.test(ip) ||
/^(::f{4}:)?172\.(1[6-9]|2\d|30|31)\.([0-9]{1,3})\.([0-9]{1,3})$/i.test(ip) ||
/^(::f{4}:)?127\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$/i.test(ip) ||
/^(::f{4}:)?169\.254\.([0-9]{1,3})\.([0-9]{1,3})$/i.test(ip) ||
/^f[cd][0-9a-f]{2}:/i.test(ip) ||
/^fe80:/i.test(ip) ||
/^::1$/.test(ip) ||
/^::$/.test(ip);
exports.isPrivateIp = isPrivateIp;
const stringWithLength = (input, chunkLength = 128) => {
const stringAsBuffer = Buffer.from(input);
const bufferSize = stringAsBuffer.byteLength < chunkLength ? chunkLength : Math.ceil(stringAsBuffer.byteLength / chunkLength) * chunkLength;
const result = Buffer.alloc(bufferSize);
stringAsBuffer.copy(result);
return result;
};
const getLocalIpAddress = (init = "") => {
const ifaces = os.networkInterfaces();
let localAddress = init;
for (const name in ifaces) {
const iface = ifaces[name].filter(function (details) {
return details.family === "IPv4" && details.internal === false;
});
if (iface.length > 0) {
localAddress = iface[0].address;
break;
}
}
return localAddress;
};
exports.getLocalIpAddress = getLocalIpAddress;
const p2pDidToBuffer = (p2pDid) => {
const p2pArray = p2pDid.split("-");
const buf1 = stringWithLength(p2pArray[0], 8);
const buf2 = Buffer.allocUnsafe(4);
buf2.writeUInt32BE(Number.parseInt(p2pArray[1]), 0);
const buf3 = stringWithLength(p2pArray[2], 8);
return Buffer.concat([buf1, buf2, buf3], 20);
};
const isP2PCommandEncrypted = function (cmd) {
return [1001, 1002, 1004, 1005, 1006, 1007, 1008, 1009, 1010, 1011, 1015, 1017, 1019, 1035, 1045, 1056, 1145, 1146, 1152, 1200, 1207, 1210, 1213, 1214, 1226, 1227, 1229, 1230, 1233, 1236, 1240, 1241, 1243, 1246, 1272, 1273, 1275, 1400, 1401, 1402, 1403, 1408, 1409, 1410, 1412, 1413, 1506, 1507, 1607, 1609, 1610, 1611, 1702, 1703, 1704, 1705, 1706, 1707, 1708, 1709, 1013, 1202, 1205, 1206, 1024, 1025, 1132, 1215, 1216, 1217, 1414, 1026, 1164, 1201, 1027, 1047, 1048, 1029, 1034, 1036, 1043, 1057, 1203, 1218, 1219, 1220, 1221, 1222, 1223, 1224, 1232, 1234, 1235, 1237, 1238, 1248, 1253, 1257, 1269, 1800, 1037, 1040, 1038, 1049, 1050, 1051, 1054, 1060, 1204, 1254, 1255, 1256, 1258, 1259, 1260, 1261, 1262, 1264, 1271, 1350, 1404, 1101, 1106, 1108, 1110, 1111, 1112, 1113, 1114, 1116, 1117, 1118, 1119, 1121, 1103, 1129, 1211, 1228, 1231, 1242, 1249, 1250, 1251, 1252, 1405, 1406, 1407, 1700].includes(cmd);
};
exports.isP2PCommandEncrypted = isP2PCommandEncrypted;
const getP2PCommandEncryptionKey = function (serialNumber, p2pDid) {
return `${serialNumber.slice(-7)}${p2pDid.substring(p2pDid.indexOf("-"), p2pDid.indexOf("-") + 9)}`;
};
exports.getP2PCommandEncryptionKey = getP2PCommandEncryptionKey;
const encryptP2PData = (data, key) => {
const cipher = (0, crypto_1.createCipheriv)("aes-128-ecb", key, null);
cipher.setAutoPadding(false);
return Buffer.concat([
cipher.update(data),
cipher.final()
]);
};
exports.encryptP2PData = encryptP2PData;
const decryptP2PData = (data, key) => {
const decipher = (0, crypto_1.createDecipheriv)("aes-128-ecb", key, null);
decipher.setAutoPadding(false);
return Buffer.concat([
decipher.update(data),
decipher.final()
]);
};
exports.decryptP2PData = decryptP2PData;
const paddingP2PData = (data, blocksize = 16) => {
const bufferSize = data.byteLength < blocksize ? blocksize : Math.ceil(data.byteLength / blocksize) * blocksize;
const result = Buffer.alloc(bufferSize);
data.copy(result);
return result;
};
exports.paddingP2PData = paddingP2PData;
const buildLookupWithKeyPayload = (socket, p2pDid, dskKey) => {
const p2pDidBuffer = p2pDidToBuffer(p2pDid);
const addressInfo = socket.address();
const port = addressInfo.port;
const portAsBuffer = Buffer.allocUnsafe(2);
portAsBuffer.writeUInt16LE(port, 0);
//const ip = socket.address().address;
const ip = (0, exports.getLocalIpAddress)(addressInfo.address);
const temp_buff = [];
ip.split(".").reverse().forEach(element => {
temp_buff.push(Number.parseInt(element));
});
const ipAsBuffer = Buffer.from(temp_buff);
const splitter = Buffer.from([0x00, 0x02]);
const magic = Buffer.from([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00]);
const dskKeyAsBuffer = Buffer.from(dskKey);
const fourEmpty = Buffer.from([0x00, 0x00, 0x00, 0x00]);
return Buffer.concat([p2pDidBuffer, splitter, portAsBuffer, ipAsBuffer, magic, dskKeyAsBuffer, fourEmpty]);
};
exports.buildLookupWithKeyPayload = buildLookupWithKeyPayload;
const buildLookupWithKeyPayload2 = (p2pDid, dskKey) => {
const p2pDidBuffer = p2pDidToBuffer(p2pDid);
const dskKeyAsBuffer = Buffer.from(dskKey);
const fourEmpty = Buffer.from([0x00, 0x00, 0x00, 0x00]);
return Buffer.concat([p2pDidBuffer, dskKeyAsBuffer, fourEmpty]);
};
exports.buildLookupWithKeyPayload2 = buildLookupWithKeyPayload2;
const buildLookupWithKeyPayload3 = (p2pDid, address, data) => {
const p2pDidBuffer = p2pDidToBuffer(p2pDid);
const portAsBuffer = Buffer.allocUnsafe(2);
portAsBuffer.writeUInt16LE(address.port, 0);
const temp_buff = [];
address.host.split(".").reverse().forEach(element => {
temp_buff.push(Number.parseInt(element));
});
const ipAsBuffer = Buffer.from(temp_buff);
const splitter = Buffer.from([0x00, 0x02]);
const eightEmpty = Buffer.from([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
return Buffer.concat([p2pDidBuffer, splitter, portAsBuffer, ipAsBuffer, eightEmpty, data]);
};
exports.buildLookupWithKeyPayload3 = buildLookupWithKeyPayload3;
const buildCheckCamPayload = (p2pDid) => {
const p2pDidBuffer = p2pDidToBuffer(p2pDid);
const magic = Buffer.from([0x00, 0x00, 0x00]);
return Buffer.concat([p2pDidBuffer, magic]);
};
exports.buildCheckCamPayload = buildCheckCamPayload;
const buildCheckCamPayload2 = (p2pDid, data) => {
const p2pDidBuffer = p2pDidToBuffer(p2pDid);
const magic = Buffer.from([0x00, 0x00, 0x00, 0x00]);
return Buffer.concat([data, p2pDidBuffer, magic]);
};
exports.buildCheckCamPayload2 = buildCheckCamPayload2;
const buildIntCommandPayload = (encryptionType, encryptionKey, serialNumber, p2pDid, commandType, value, strValue = "", channel = 255) => {
const emptyBuffer = Buffer.from([0x00, 0x00]);
const magicBuffer = Buffer.from([0x01, 0x00]);
const encrypted = (0, exports.isP2PCommandEncrypted)(commandType) && encryptionType !== types_1.EncryptionType.NONE && encryptionKey?.length === 16;
const channelBuffer = Buffer.from([channel, encrypted ? encryptionType : 0]);
const valueBuffer = Buffer.allocUnsafe(4);
valueBuffer.writeUInt32LE(value, 0);
const headerBuffer = Buffer.allocUnsafe(2);
const strValueBuffer = strValue.length === 0 ? Buffer.from([]) : stringWithLength(strValue);
const tmpDataBuffer = Buffer.concat([
valueBuffer,
strValueBuffer
]);
const dataBuffer = encrypted ? (0, exports.paddingP2PData)(tmpDataBuffer) : tmpDataBuffer;
headerBuffer.writeUInt16LE(dataBuffer.length, 0);
return Buffer.concat([
headerBuffer,
emptyBuffer,
magicBuffer,
channelBuffer,
emptyBuffer,
encrypted ? (0, exports.encryptP2PData)(dataBuffer, encryptionKey) : dataBuffer
]);
};
exports.buildIntCommandPayload = buildIntCommandPayload;
const buildStringTypeCommandPayload = (encryptionType, encryptionKey, serialNumber, p2pDid, commandType, strValue, strValueSub, channel = 255) => {
const emptyBuffer = Buffer.from([0x00, 0x00]);
const magicBuffer = Buffer.from([0x01, 0x00]);
const encrypted = (0, exports.isP2PCommandEncrypted)(commandType) && encryptionType !== types_1.EncryptionType.NONE && encryptionKey?.length === 16;
const channelBuffer = Buffer.from([channel, encrypted ? encryptionType : 0]);
const someBuffer = Buffer.from([0x00, 0x00, 0x00, 0x00, 0x00]);
const strValueBuffer = stringWithLength(strValue);
const strValueSubBuffer = stringWithLength(strValueSub);
const headerBuffer = Buffer.allocUnsafe(2);
const tmpDataBuffer = Buffer.concat([
someBuffer,
strValueBuffer,
strValueSubBuffer
]);
const dataBuffer = encrypted ? (0, exports.paddingP2PData)(tmpDataBuffer) : tmpDataBuffer;
headerBuffer.writeUInt16LE(dataBuffer.length, 0);
return Buffer.concat([
headerBuffer,
emptyBuffer,
magicBuffer,
channelBuffer,
emptyBuffer,
encrypted ? (0, exports.encryptP2PData)(dataBuffer, encryptionKey) : dataBuffer
]);
};
exports.buildStringTypeCommandPayload = buildStringTypeCommandPayload;
const buildIntStringCommandPayload = (encryptionType, encryptionKey, serialNumber, p2pDid, commandType, value, valueSub = 0, strValue = "", strValueSub = "", channel = 0) => {
const emptyBuffer = Buffer.from([0x00, 0x00]);
const magicBuffer = Buffer.from([0x01, 0x00]);
const encrypted = (0, exports.isP2PCommandEncrypted)(commandType) && encryptionType !== types_1.EncryptionType.NONE && encryptionKey?.length === 16;
const channelBuffer = Buffer.from([channel, encrypted ? encryptionType : 0]);
const someintBuffer = Buffer.allocUnsafe(4);
someintBuffer.writeUInt32LE(valueSub, 0);
const valueBuffer = Buffer.allocUnsafe(4);
valueBuffer.writeUInt32LE(value, 0);
const strValueBuffer = strValue.length === 0 ? Buffer.from([]) : stringWithLength(strValue);
const strValueSubBuffer = strValueSub.length === 0 ? Buffer.from([]) : stringWithLength(strValueSub);
const headerBuffer = Buffer.allocUnsafe(2);
const tmpDataBuffer = Buffer.concat([
someintBuffer,
valueBuffer,
strValueBuffer,
strValueSubBuffer
]);
const dataBuffer = encrypted ? (0, exports.paddingP2PData)(tmpDataBuffer) : tmpDataBuffer;
headerBuffer.writeUInt16LE(dataBuffer.length, 0);
return Buffer.concat([
headerBuffer,
emptyBuffer,
magicBuffer,
channelBuffer,
emptyBuffer,
encrypted ? (0, exports.encryptP2PData)(dataBuffer, encryptionKey) : dataBuffer
]);
};
exports.buildIntStringCommandPayload = buildIntStringCommandPayload;
const sendMessage = async (socket, address, msgID, payload) => {
if (!payload)
payload = Buffer.from([]);
const payloadLen = Buffer.allocUnsafe(2);
payloadLen.writeUInt16BE(payload.length, 0);
const message = Buffer.concat([msgID, payloadLen, payload], 4 + payload.length);
return new Promise((resolve, reject) => {
socket.send(message, address.port, address.host, (err, bytes) => {
return err ? reject(err) : resolve(bytes);
});
});
};
exports.sendMessage = sendMessage;
const hasHeader = (msg, searchedType) => {
const header = Buffer.allocUnsafe(2);
msg.copy(header, 0, 0, 2);
return Buffer.compare(header, searchedType) === 0;
};
exports.hasHeader = hasHeader;
const buildCommandHeader = (seqNumber, commandType, p2pDataTypeHeader = null) => {
let dataTypeBuffer = types_1.P2PDataTypeHeader.DATA;
if (p2pDataTypeHeader !== null &&
(Buffer.compare(p2pDataTypeHeader, types_1.P2PDataTypeHeader.DATA) === 0 ||
Buffer.compare(p2pDataTypeHeader, types_1.P2PDataTypeHeader.BINARY) === 0 ||
Buffer.compare(p2pDataTypeHeader, types_1.P2PDataTypeHeader.CONTROL) === 0 ||
Buffer.compare(p2pDataTypeHeader, types_1.P2PDataTypeHeader.VIDEO) === 0)) {
dataTypeBuffer = p2pDataTypeHeader;
}
const seqAsBuffer = Buffer.allocUnsafe(2);
seqAsBuffer.writeUInt16BE(seqNumber, 0);
const magicString = Buffer.from(exports.MAGIC_WORD);
const commandTypeBuffer = Buffer.allocUnsafe(2);
commandTypeBuffer.writeUInt16LE(commandType, 0);
return Buffer.concat([dataTypeBuffer, seqAsBuffer, magicString, commandTypeBuffer]);
};
exports.buildCommandHeader = buildCommandHeader;
const buildCommandWithStringTypePayload = (encryptionType, encryptionKey, serialNumber, p2pDid, commandType, value, channel = 0) => {
const headerBuffer = Buffer.allocUnsafe(2);
const emptyBuffer = Buffer.from([0x00, 0x00]);
const magicBuffer = Buffer.from([0x01, 0x00]);
const encrypted = (0, exports.isP2PCommandEncrypted)(commandType) && encryptionType !== types_1.EncryptionType.NONE && encryptionKey?.length === 16;
const channelBuffer = Buffer.from([channel, encrypted ? encryptionType : 0]);
const dataBuffer = encrypted ? (0, exports.paddingP2PData)(Buffer.from(value)) : Buffer.from(value);
headerBuffer.writeUInt16LE(dataBuffer.length, 0);
return Buffer.concat([
headerBuffer,
emptyBuffer,
magicBuffer,
channelBuffer,
emptyBuffer,
encrypted ? (0, exports.encryptP2PData)(dataBuffer, encryptionKey) : dataBuffer
]);
};
exports.buildCommandWithStringTypePayload = buildCommandWithStringTypePayload;
const sortP2PMessageParts = (messages) => {
let completeMessage = Buffer.from([]);
Object.keys(messages).map(Number)
.sort((a, b) => {
if (Math.abs(a - b) > 65000) {
if (a < b) {
return 1;
}
else if (b < a) {
return -1;
}
}
return a - b;
}) // assure the seqNumbers are in correct order
.forEach((key) => {
completeMessage = Buffer.concat([completeMessage, messages[key]]);
});
return completeMessage;
};
exports.sortP2PMessageParts = sortP2PMessageParts;
const getRSAPrivateKey = (pem, enableEmbeddedPKCS1Support = false) => {
const key = new node_rsa_1.default();
if (pem.indexOf("\n") !== -1) {
pem = pem.replaceAll("\n", "");
}
if (pem.startsWith("-----BEGIN RSA PRIVATE KEY-----")) {
pem = pem.replace("-----BEGIN RSA PRIVATE KEY-----", "").replace("-----END RSA PRIVATE KEY-----", "");
}
key.importKey(pem, "pkcs8");
const options = {
encryptionScheme: "pkcs1"
};
if (enableEmbeddedPKCS1Support) {
options.environment = "browser";
}
key.setOptions(options);
return key;
};
exports.getRSAPrivateKey = getRSAPrivateKey;
const getNewRSAPrivateKey = (enableEmbeddedPKCS1Support = false) => {
const key = new node_rsa_1.default({ b: 1024 });
const options = {
encryptionScheme: "pkcs1"
};
if (enableEmbeddedPKCS1Support) {
options.environment = "browser";
}
key.setOptions(options);
return key;
};
exports.getNewRSAPrivateKey = getNewRSAPrivateKey;
const decryptAESData = (hexkey, data) => {
const key = CryptoJS.enc.Hex.parse(hexkey);
const cipherParams = CryptoJS.lib.CipherParams.create({
ciphertext: CryptoJS.enc.Hex.parse(data.toString("hex"))
});
const decrypted = CryptoJS.AES.decrypt(cipherParams, key, {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.NoPadding
});
return Buffer.from(CryptoJS.enc.Hex.stringify(decrypted), "hex");
};
exports.decryptAESData = decryptAESData;
const findStartCode = (data) => {
if (data !== undefined && data.length > 0) {
if (data.length >= 4) {
const startcode = [...data.subarray(0, 4)];
if ((startcode[0] === 0 && startcode[1] === 0 && startcode[2] === 1) || (startcode[0] === 0 && startcode[1] === 0 && startcode[2] === 0 && startcode[3] === 1))
return true;
}
else if (data.length === 3) {
const startcode = [...data.subarray(0, 3)];
if ((startcode[0] === 0 && startcode[1] === 0 && startcode[2] === 1))
return true;
}
}
return false;
};
exports.findStartCode = findStartCode;
const isIFrame = (data) => {
const validValues = [64, 66, 68, 78, 101, 103];
if (data !== undefined && data.length > 0) {
if (data.length >= 5) {
const startcode = [...data.subarray(0, 5)];
if (validValues.includes(startcode[3]) || validValues.includes(startcode[4]))
return true;
}
}
return false;
};
exports.isIFrame = isIFrame;
const decryptLockAESData = (key, iv, data) => {
const ekey = CryptoJS.enc.Hex.parse(key);
const eiv = CryptoJS.enc.Hex.parse(iv);
const cipherParams = CryptoJS.lib.CipherParams.create({
ciphertext: CryptoJS.enc.Hex.parse(data.toString("hex"))
});
const decrypted = CryptoJS.AES.decrypt(cipherParams, ekey, {
iv: eiv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});
return Buffer.from(CryptoJS.enc.Hex.stringify(decrypted), "hex");
};
exports.decryptLockAESData = decryptLockAESData;
const encryptLockAESData = (key, iv, data) => {
const ekey = CryptoJS.enc.Hex.parse(key);
const eiv = CryptoJS.enc.Hex.parse(iv);
const encrypted = CryptoJS.AES.encrypt(CryptoJS.enc.Hex.parse(data.toString("hex")), ekey, {
iv: eiv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});
return Buffer.from(CryptoJS.enc.Hex.stringify(encrypted.ciphertext), "hex");
};
exports.encryptLockAESData = encryptLockAESData;
const generateBasicLockAESKey = (adminID, stationSN) => {
const encoder = new TextEncoder();
const encOwnerID = encoder.encode(adminID);
const encStationSerial = encoder.encode(stationSN);
const array = [104, -83, -72, 38, -107, 99, -110, 17, -95, -121, 54, 57, -46, -98, -111, 89];
for (let i = 0; i < 16; i++) {
array[i] = (array[i] + encStationSerial[((encStationSerial[i] * 3) + 5) % 16] + encOwnerID[((encOwnerID[i] * 3) + 5) % 40]);
}
return Buffer.from(array).toString("hex");
};
exports.generateBasicLockAESKey = generateBasicLockAESKey;
const getCurrentTimeInSeconds = function () {
return Math.trunc(new Date().getTime() / 1000);
};
exports.getCurrentTimeInSeconds = getCurrentTimeInSeconds;
const generateLockSequence = (deviceType, serialnumber) => {
if (deviceType !== undefined && serialnumber !== undefined)
if (device_1.Device.isLockWifi(deviceType, serialnumber) || device_1.Device.isLockWifiNoFinger(deviceType))
return Math.trunc(Math.random() * 1000);
return (0, exports.getCurrentTimeInSeconds)();
};
exports.generateLockSequence = generateLockSequence;
const encodeLockPayload = (data) => {
const encoder = new TextEncoder();
const encData = encoder.encode(data);
const length = encData.length;
const old_buffer = Buffer.from(encData);
if (length % 16 == 0) {
return old_buffer;
}
const new_length = (Math.trunc(length / 16) + 1) * 16;
const new_buffer = Buffer.alloc(new_length);
old_buffer.copy(new_buffer, 0);
return new_buffer;
};
exports.encodeLockPayload = encodeLockPayload;
const getLockVectorBytes = (data) => {
const encoder = new TextEncoder();
const encData = encoder.encode(data);
const old_buffer = Buffer.from(encData);
if (encData.length >= 16)
return old_buffer.toString("hex");
const new_buffer = Buffer.alloc(16);
old_buffer.copy(new_buffer, 0);
return new_buffer.toString("hex");
};
exports.getLockVectorBytes = getLockVectorBytes;
const decodeLockPayload = (data) => {
const decoder = new TextDecoder();
return decoder.decode(data);
};
exports.decodeLockPayload = decodeLockPayload;
const decodeBase64 = (data) => {
const base64RegExp = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{4})$/;
if (base64RegExp.test(data))
return Buffer.from(data, "base64");
return Buffer.from(data);
};
exports.decodeBase64 = decodeBase64;
const eslTimestamp = function (timestamp_in_sec = new Date().getTime() / 1000) {
const array = [];
for (let pos = 0; pos < 4; pos++) {
array[pos] = ((timestamp_in_sec >> (pos * 8)) & 255);
}
return array;
};
exports.eslTimestamp = eslTimestamp;
const generateAdvancedLockAESKey = () => {
const randomBytesArray = [...(0, crypto_1.randomBytes)(16)];
let result = "";
for (let pos = 0; pos < randomBytesArray.length; pos++) {
result += "0123456789ABCDEF".charAt((randomBytesArray[pos] >> 4) & 15);
result += "0123456789ABCDEF".charAt(randomBytesArray[pos] & 15);
}
return result;
};
exports.generateAdvancedLockAESKey = generateAdvancedLockAESKey;
const getVideoCodec = (data) => {
if (data !== undefined && data.length > 0) {
if (data.length >= 5) {
const h265Values = [38, 64, 66, 68, 78];
const startcode = [...data.subarray(0, 5)];
if (h265Values.includes(startcode[3]) || h265Values.includes(startcode[4])) {
return types_1.VideoCodec.H265;
}
else if (startcode[3] === 103 || startcode[4] === 103) {
return types_1.VideoCodec.H264;
}
}
return types_1.VideoCodec.H264;
}
return types_1.VideoCodec.UNKNOWN; // Maybe return h264 as Eufy does?
};
exports.getVideoCodec = getVideoCodec;
const checkT8420 = (serialNumber) => {
if (!(serialNumber !== undefined && serialNumber !== null && serialNumber.length > 0 && serialNumber.startsWith("T8420")) || serialNumber.length <= 7 || serialNumber[6] != "6") {
return false;
}
return true;
};
exports.checkT8420 = checkT8420;
const buildVoidCommandPayload = (channel = 255) => {
const headerBuffer = Buffer.from([0x00, 0x00]);
const emptyBuffer = Buffer.from([0x00, 0x00]);
const magicBuffer = Buffer.from([0x01, 0x00]);
const channelBuffer = Buffer.from([channel, 0x00]);
return Buffer.concat([
headerBuffer,
emptyBuffer,
magicBuffer,
channelBuffer,
emptyBuffer
]);
};
exports.buildVoidCommandPayload = buildVoidCommandPayload;
function isP2PQueueMessage(type) {
return type.p2pCommand !== undefined;
}
const encryptPayloadData = (data, key, iv) => {
const cipher = (0, crypto_1.createCipheriv)("aes-128-cbc", key, iv);
return Buffer.concat([
cipher.update(data),
cipher.final()
]);
};
exports.encryptPayloadData = encryptPayloadData;
const decryptPayloadData = (data, key, iv) => {
const cipher = (0, crypto_1.createDecipheriv)("aes-128-cbc", key, iv);
return Buffer.concat([
cipher.update(data),
cipher.final()
]);
};
exports.decryptPayloadData = decryptPayloadData;
const eufyKDF = (key) => {
const hash_length = 32;
const digest_length = 48;
const staticBuffer = Buffer.from("ECIES");
const steps = Math.ceil(digest_length / hash_length);
const buffer = Buffer.alloc(hash_length * steps);
let tmpBuffer = staticBuffer;
for (let step = 0; step < steps; ++step) {
tmpBuffer = (0, crypto_1.createHmac)("sha256", key).update(tmpBuffer).digest();
const digest = (0, crypto_1.createHmac)("sha256", key).update(Buffer.concat([tmpBuffer, staticBuffer])).digest();
digest.copy(buffer, hash_length * step);
}
return buffer.subarray(0, digest_length);
};
exports.eufyKDF = eufyKDF;
const getAdvancedLockKey = (key, publicKey) => {
const ecdh = (0, crypto_1.createECDH)("prime256v1");
ecdh.generateKeys();
const secret = ecdh.computeSecret(Buffer.concat([Buffer.from("04", "hex"), Buffer.from(publicKey, "hex")]));
const randomValue = (0, crypto_1.randomBytes)(16);
const derivedKey = (0, exports.eufyKDF)(secret);
const encryptedData = (0, exports.encryptPayloadData)(key, derivedKey.subarray(0, 16), randomValue);
const hmac = (0, crypto_1.createHmac)("sha256", derivedKey.subarray(16));
hmac.update(randomValue);
hmac.update(encryptedData);
const hmacDigest = hmac.digest();
return Buffer.concat([Buffer.from(ecdh.getPublicKey("hex", "compressed"), "hex"), randomValue, encryptedData, hmacDigest]).toString("hex");
};
exports.getAdvancedLockKey = getAdvancedLockKey;
const getLockV12Key = (key, publicKey) => {
const ecdh = (0, crypto_1.createECDH)("prime256v1");
ecdh.generateKeys();
const secret = ecdh.computeSecret(Buffer.concat([Buffer.from("04", "hex"), Buffer.from(publicKey, "hex")]));
const randomValue = (0, crypto_1.randomBytes)(16);
const derivedKey = (0, exports.eufyKDF)(secret);
const encryptedData = (0, exports.encryptPayloadData)(Buffer.from(key, "hex"), derivedKey.subarray(0, 16), randomValue);
const hmac = (0, crypto_1.createHmac)("sha256", derivedKey.subarray(16));
hmac.update(randomValue);
hmac.update(encryptedData);
const hmacDigest = hmac.digest();
return Buffer.concat([Buffer.from(ecdh.getPublicKey("hex", "compressed"), "hex"), randomValue, encryptedData, hmacDigest]).toString("hex");
};
exports.getLockV12Key = getLockV12Key;
const buildTalkbackAudioFrameHeader = (audioData, channel = 0) => {
const audioDataLength = Buffer.allocUnsafe(4);
audioDataLength.writeUInt32LE(audioData.length);
const unknown1 = Buffer.alloc(1);
const audioType = Buffer.alloc(1);
const audioSeq = Buffer.alloc(2);
const audioTimestamp = Buffer.alloc(8);
const audioDataHeader = Buffer.concat([audioDataLength, unknown1, audioType, audioSeq, audioTimestamp]);
const bytesToRead = Buffer.allocUnsafe(4);
bytesToRead.writeUInt32LE(audioData.length + audioDataHeader.length);
const magicBuffer = Buffer.from([0x01, 0x00]);
const channelBuffer = Buffer.from([channel, 0x00]);
const emptyBuffer = Buffer.from([0x00, 0x00]);
return Buffer.concat([
bytesToRead,
magicBuffer,
channelBuffer,
emptyBuffer,
audioDataHeader
]);
};
exports.buildTalkbackAudioFrameHeader = buildTalkbackAudioFrameHeader;
const decodeP2PCloudIPs = (data) => {
const lookupTable = Buffer.from("4959433db5bf6da347534f6165e371e9677f02030badb3892b2f35c16b8b959711e5a70deff1050783fb9d3bc5c713171d1f2529d3df", "hex");
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const [encoded, name = "name not included"] = data.split(":");
const output = Buffer.alloc(encoded.length / 2);
for (let i = 0; i <= data.length / 2; i++) {
let z = 0x39; // 57 // '9'
for (let j = 0; j < i; j++) {
z = z ^ output[j];
}
const x = (data.charCodeAt(i * 2 + 1) - "A".charCodeAt(0));
const y = (data.charCodeAt(i * 2) - "A".charCodeAt(0)) * 0x10;
output[i] = z ^ lookupTable[i % lookupTable.length] ^ x + y;
}
const result = [];
output.toString("utf8").split(",").forEach((ip) => {
if (ip !== "") {
result.push({ host: ip, port: 32100 });
}
});
return result;
};
exports.decodeP2PCloudIPs = decodeP2PCloudIPs;
const decodeSmartSafeData = function (deviceSN, data) {
const response = ble_1.BleCommandFactory.parseSmartSafe(data);
return {
versionCode: response.getVersionCode(),
dataType: response.getDataType(),
commandCode: response.getCommandCode(),
packageFlag: response.getPackageFlag(),
responseCode: response.getResponseCode(),
data: (0, exports.decryptPayloadData)(response.getData(), Buffer.from(deviceSN), Buffer.from(device_1.SmartSafe.IV, "hex"))
};
};
exports.decodeSmartSafeData = decodeSmartSafeData;
const getSmartSafeP2PCommand = function (deviceSN, user_id, command, intCommand, channel, sequence, data) {
const encPayload = (0, exports.encryptPayloadData)(data, Buffer.from(deviceSN), Buffer.from(device_1.SmartSafe.IV, "hex"));
const bleCommand = new ble_1.BleCommandFactory()
.setVersionCode(device_1.SmartSafe.VERSION_CODE)
.setCommandCode(intCommand)
.setDataType(-1)
.setData(encPayload)
.getSmartSafeCommand();
logging_1.rootP2PLogger.debug(`Generate smart safe command`, { deviceSN: deviceSN, userId: user_id, command: command, intCommand: intCommand, channel: channel, sequence: sequence, data: data.toString("hex") });
return {
commandType: types_1.CommandType.CMD_SET_PAYLOAD,
value: JSON.stringify({
account_id: user_id,
cmd: command,
mChannel: channel,
mValue3: 0,
payload: {
data: bleCommand.toString("hex"),
prj_id: command,
seq_num: sequence,
}
}),
channel: channel
};
};
exports.getSmartSafeP2PCommand = getSmartSafeP2PCommand;
const getLockP2PCommand = function (deviceSN, user_id, command, channel, lockPublicKey, payload) {
const key = (0, exports.generateAdvancedLockAESKey)();
const ecdhKey = (0, exports.getAdvancedLockKey)(key, lockPublicKey);
const iv = (0, exports.getLockVectorBytes)(deviceSN);
const encPayload = (0, exports.encryptLockAESData)(key, iv, Buffer.from(JSON.stringify(payload)));
logging_1.rootP2PLogger.debug(`Generate lock command`, { deviceSN: deviceSN, userId: user_id, command: command, channel: channel, data: JSON.stringify(payload) });
return {
commandType: types_1.CommandType.CMD_SET_PAYLOAD,
value: JSON.stringify({
key: ecdhKey,
account_id: user_id,
cmd: command,
mChannel: channel,
mValue3: 0,
payload: encPayload.toString("base64")
}).replace(/=/g, "\\u003d"),
channel: channel,
aesKey: key
};
};
exports.getLockP2PCommand = getLockP2PCommand;
const getLockV12P2PCommand = function (deviceSN, user_id, command, channel, lockPublicKey, sequence, data) {
const key = (0, exports.generateAdvancedLockAESKey)();
const encryptedAesKey = (0, exports.getLockV12Key)(key, lockPublicKey);
const iv = (0, exports.getLockVectorBytes)(deviceSN);
const encPayload = (0, exports.encryptPayloadData)(data, Buffer.from(key, "hex"), Buffer.from(iv, "hex"));
logging_1.rootP2PLogger.debug(`Generate smart lock v12 command`, { deviceSN: deviceSN, userId: user_id, command: command, channel: channel, sequence: sequence, data: data.toString("hex") });
const bleCommand = new ble_1.BleCommandFactory()
.setVersionCode(device_1.Lock.VERSION_CODE_LOCKV12)
.setCommandCode(Number.parseInt(types_1.ESLBleCommand[types_1.ESLCommand[command]])) //TODO: Change internal command identification?
.setDataType(-1)
.setData(encPayload)
.setAdditionalData(Buffer.from(encryptedAesKey, "hex"));
return {
aesKey: key,
bleCommand: bleCommand.getCommandCode(),
payload: {
commandType: types_1.CommandType.CMD_SET_PAYLOAD,
value: JSON.stringify({
account_id: user_id,
cmd: types_1.CommandType.CMD_SET_PAYLOAD_LOCKV12,
mChannel: channel,
mValue3: 0,
payload: {
apiCommand: command,
lock_payload: bleCommand.getLockV12Command().toString("hex"),
seq_num: sequence,
}
})
}
};
};
exports.getLockV12P2PCommand = getLockV12P2PCommand;
const DecimalToRGBColor = function (color) {
return {
red: (color >> 16) & 0xff,
green: (color >> 8) & 0xff,
blue: color & 0xff,
};
};
exports.DecimalToRGBColor = DecimalToRGBColor;
const RGBColorToDecimal = function (color) {
return (color.red << 16) + (color.green << 8) + (color.blue);
};
exports.RGBColorToDecimal = RGBColorToDecimal;
const getNullTerminatedString = function (data, encoding) {
const index = data.indexOf(0);
return data.toString(encoding, 0, index === -1 ? data.length : index);
};
exports.getNullTerminatedString = getNullTerminatedString;
const isUsbCharging = function (value) {
return (value & 1) == 1;
};
exports.isUsbCharging = isUsbCharging;
const isSolarCharging = function (value) {
return ((value >> 2) & 1) == 1;
};
exports.isSolarCharging = isSolarCharging;
const isPlugSolarCharging = function (value) {
return ((value >> 3) & 1) == 1;
};
exports.isPlugSolarCharging = isPlugSolarCharging;
const isCharging = function (value) {
return (0, exports.isUsbCharging)(value) || (0, exports.isSolarCharging)(value) || (0, exports.isPlugSolarCharging)(value);
};
exports.isCharging = isCharging;
const getSmartLockCurrentTimeInSeconds = function () {
return Math.trunc(new Date().getTime() / 1000) | Math.trunc(Math.random() * 100);
};
exports.getSmartLockCurrentTimeInSeconds = getSmartLockCurrentTimeInSeconds;
const generateSmartLockAESKey = (adminUserId, time) => {
const buffer = Buffer.allocUnsafe(4);
buffer.writeUint32BE(time);
return Buffer.concat([Buffer.from(adminUserId.substring(adminUserId.length - 12)), buffer]);
};
exports.generateSmartLockAESKey = generateSmartLockAESKey;
const getSmartLockP2PCommand = function (deviceSN, user_id, command, channel, sequence, data, functionType = types_1.SmartLockFunctionType.TYPE_2) {
const time = (0, exports.getSmartLockCurrentTimeInSeconds)();
const key = (0, exports.generateSmartLockAESKey)(user_id, time);
const iv = (0, exports.getLockVectorBytes)(deviceSN);
const encPayload = (0, exports.encryptPayloadData)(data, key, Buffer.from(iv, "hex"));
logging_1.rootP2PLogger.debug(`Generate smart lock command`, { deviceSN: deviceSN, userId: user_id, command: command, channel: channel, sequence: sequence, data: data.toString("hex"), functionType: functionType });
let commandCode = 0;
if (functionType === types_1.SmartLockFunctionType.TYPE_1) {
commandCode = Number.parseInt(types_1.SmartLockBleCommandFunctionType1[types_1.SmartLockCommand[command]]);
}
else if (functionType === types_1.SmartLockFunctionType.TYPE_2) {
commandCode = Number.parseInt(types_1.SmartLockBleCommandFunctionType2[types_1.SmartLockCommand[command]]);
}
const bleCommand = new ble_1.BleCommandFactory()
.setVersionCode(device_1.Lock.VERSION_CODE_SMART_LOCK)
.setCommandCode(commandCode)
.setDataType(functionType)
.setData(encPayload);
return {
bleCommand: bleCommand.getCommandCode(),
payload: {
commandType: types_1.CommandType.CMD_SET_PAYLOAD,
value: JSON.stringify({
account_id: user_id,
cmd: types_1.CommandType.CMD_TRANSFER_PAYLOAD,
mChannel: channel,
mValue3: 0,
payload: {
apiCommand: command,
lock_payload: bleCommand.getSmartLockCommand().toString("hex"),
seq_num: sequence,
time: time,
}
})
}
};
};
exports.getSmartLockP2PCommand = getSmartLockP2PCommand;
const readNullTerminatedBuffer = (input) => {
const index = input.indexOf(new Uint8Array([0]));
if (index === -1) {
const result = Buffer.alloc(input.length);
input.copy(result);
return result;
}
const result = Buffer.alloc(input.subarray(0, index).length);
input.subarray(0, index).copy(result);
return result;
};
exports.readNullTerminatedBuffer = readNullTerminatedBuffer;
//# sourceMappingURL=utils.js.map

1
build/p2p/utils.js.map Normal file

File diff suppressed because one or more lines are too long

49
build/push/client.d.ts vendored Normal file
View File

@ -0,0 +1,49 @@
import { TypedEmitter } from "tiny-typed-emitter";
import { PushClientEvents } from "./interfaces";
export declare class PushClient extends TypedEmitter<PushClientEvents> {
private readonly HOST;
private readonly PORT;
private readonly MCS_VERSION;
private readonly HEARTBEAT_INTERVAL;
private loggedIn;
private streamId;
private lastStreamIdReported;
private currentDelay;
private client?;
private heartbeatTimeout?;
private reconnectTimeout?;
private persistentIds;
private static proto;
private pushClientParser;
private auth;
private constructor();
static init(auth: {
androidId: string;
securityToken: string;
}): Promise<PushClient>;
private initialize;
getPersistentIds(): Array<string>;
setPersistentIds(ids: Array<string>): void;
connect(): void;
private buildLoginRequest;
private buildHeartbeatPingRequest;
private buildHeartbeatAckRequest;
private onSocketData;
private onSocketConnect;
private onSocketClose;
private onSocketError;
private handleParsedMessage;
private handleHeartbeatPing;
private handleHeartbeatAck;
private convertPayloadMessage;
private getStreamId;
private newStreamIdAvailable;
private scheduleHeartbeat;
private sendHeartbeat;
isConnected(): boolean;
private getHeartbeatInterval;
private getCurrentDelay;
private resetCurrentDelay;
private scheduleReconnect;
close(): void;
}

323
build/push/client.js Normal file
View File

@ -0,0 +1,323 @@
"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.PushClient = void 0;
const long_1 = __importDefault(require("long"));
const path = __importStar(require("path"));
const protobufjs_1 = require("protobufjs");
const tls = __importStar(require("tls"));
const tiny_typed_emitter_1 = require("tiny-typed-emitter");
const models_1 = require("./models");
const parser_1 = require("./parser");
const utils_1 = require("../utils");
const error_1 = require("./error");
const error_2 = require("../error");
const utils_2 = require("../p2p/utils");
const logging_1 = require("../logging");
class PushClient extends tiny_typed_emitter_1.TypedEmitter {
HOST = "mtalk.google.com";
PORT = 5228;
MCS_VERSION = 41;
HEARTBEAT_INTERVAL = 5 * 60 * 1000;
loggedIn = false;
streamId = 0;
lastStreamIdReported = -1;
currentDelay = 0;
client;
heartbeatTimeout;
reconnectTimeout;
persistentIds = [];
static proto = null;
pushClientParser;
auth;
constructor(pushClientParser, auth) {
super();
this.pushClientParser = pushClientParser;
this.auth = auth;
}
static async init(auth) {
this.proto = await (0, protobufjs_1.load)(path.join(__dirname, "./proto/mcs.proto"));
const pushClientParser = await parser_1.PushClientParser.init();
return new PushClient(pushClientParser, auth);
}
initialize() {
this.loggedIn = false;
this.streamId = 0;
this.lastStreamIdReported = -1;
if (this.client) {
this.client.removeAllListeners();
this.client.destroy();
this.client = undefined;
}
this.pushClientParser.resetState();
if (this.reconnectTimeout) {
clearTimeout(this.reconnectTimeout);
this.reconnectTimeout = undefined;
}
}
getPersistentIds() {
return this.persistentIds;
}
setPersistentIds(ids) {
this.persistentIds = ids;
}
connect() {
this.initialize();
this.pushClientParser.on("message", (message) => this.handleParsedMessage(message));
this.client = tls.connect(this.PORT, this.HOST, {
rejectUnauthorized: false,
});
this.client.setKeepAlive(true);
// For debugging purposes
//this.client.enableTrace();
this.client.on("connect", () => this.onSocketConnect());
this.client.on("close", () => this.onSocketClose());
this.client.on("error", (error) => this.onSocketError(error));
this.client.on("data", (newData) => this.onSocketData(newData));
this.client.write(this.buildLoginRequest());
}
buildLoginRequest() {
const androidId = this.auth.androidId;
const securityToken = this.auth.securityToken;
const LoginRequestType = PushClient.proto.lookupType("mcs_proto.LoginRequest");
const hexAndroidId = long_1.default.fromString(androidId).toString(16);
const loginRequest = {
adaptiveHeartbeat: false,
authService: 2,
authToken: securityToken,
id: "chrome-63.0.3234.0",
domain: "mcs.android.com",
deviceId: `android-${hexAndroidId}`,
networkType: 1,
resource: androidId,
user: androidId,
useRmq2: true,
setting: [{ name: "new_vc", value: "1" }],
clientEvent: [],
receivedPersistentId: this.persistentIds,
};
const errorMessage = LoginRequestType.verify(loginRequest);
if (errorMessage) {
throw new error_1.BuildLoginRequestError(errorMessage, { context: { loginRequest: loginRequest } });
}
const buffer = LoginRequestType.encodeDelimited(loginRequest).finish();
return Buffer.concat([Buffer.from([this.MCS_VERSION, models_1.MessageTag.LoginRequest]), buffer]);
}
buildHeartbeatPingRequest(stream_id) {
const heartbeatPingRequest = {};
if (stream_id) {
heartbeatPingRequest.last_stream_id_received = stream_id;
}
logging_1.rootPushLogger.debug(`Push client - heartbeatPingRequest`, { streamId: stream_id, request: JSON.stringify(heartbeatPingRequest) });
const HeartbeatPingRequestType = PushClient.proto.lookupType("mcs_proto.HeartbeatPing");
const errorMessage = HeartbeatPingRequestType.verify(heartbeatPingRequest);
if (errorMessage) {
throw new error_1.BuildHeartbeatPingRequestError(errorMessage, { context: { heartbeatPingRequest: heartbeatPingRequest } });
}
const buffer = HeartbeatPingRequestType.encodeDelimited(heartbeatPingRequest).finish();
return Buffer.concat([Buffer.from([models_1.MessageTag.HeartbeatPing]), buffer]);
}
buildHeartbeatAckRequest(stream_id, status) {
const heartbeatAckRequest = {};
if (stream_id && !status) {
heartbeatAckRequest.last_stream_id_received = stream_id;
}
else if (!stream_id && status) {
heartbeatAckRequest.status = status;
}
else {
heartbeatAckRequest.last_stream_id_received = stream_id;
heartbeatAckRequest.status = status;
}
logging_1.rootPushLogger.debug(`Push client - heartbeatAckRequest`, { streamId: stream_id, status: status, request: JSON.stringify(heartbeatAckRequest) });
const HeartbeatAckRequestType = PushClient.proto.lookupType("mcs_proto.HeartbeatAck");
const errorMessage = HeartbeatAckRequestType.verify(heartbeatAckRequest);
if (errorMessage) {
throw new error_1.BuildHeartbeatAckRequestError(errorMessage, { context: { heartbeatAckRequest: heartbeatAckRequest } });
}
const buffer = HeartbeatAckRequestType.encodeDelimited(heartbeatAckRequest).finish();
return Buffer.concat([Buffer.from([models_1.MessageTag.HeartbeatAck]), buffer]);
}
onSocketData(newData) {
this.pushClientParser.handleData(newData);
}
onSocketConnect() {
//
}
onSocketClose() {
this.loggedIn = false;
if (this.heartbeatTimeout) {
clearTimeout(this.heartbeatTimeout);
this.heartbeatTimeout = undefined;
}
this.emit("close");
this.scheduleReconnect();
}
onSocketError(err) {
const error = (0, error_2.ensureError)(err);
logging_1.rootPushLogger.error(`Push client - Socket Error`, { error: (0, utils_1.getError)(error) });
}
handleParsedMessage(message) {
this.resetCurrentDelay();
switch (message.tag) {
case models_1.MessageTag.DataMessageStanza:
logging_1.rootPushLogger.debug(`Push client - DataMessageStanza`, { message: JSON.stringify(message) });
if (message.object && message.object.persistentId)
this.persistentIds.push(message.object.persistentId);
this.emit("message", this.convertPayloadMessage(message));
break;
case models_1.MessageTag.HeartbeatPing:
this.handleHeartbeatPing(message);
break;
case models_1.MessageTag.HeartbeatAck:
this.handleHeartbeatAck(message);
break;
case models_1.MessageTag.Close:
logging_1.rootPushLogger.debug(`Push client - Close: Server requested close`, { message: JSON.stringify(message) });
break;
case models_1.MessageTag.LoginResponse:
logging_1.rootPushLogger.debug("Push client - Login response: GCM -> logged in -> waiting for push messages...", { message: JSON.stringify(message) });
this.loggedIn = true;
this.persistentIds = [];
this.emit("connect");
this.heartbeatTimeout = setTimeout(() => {
this.scheduleHeartbeat(this);
}, this.getHeartbeatInterval());
break;
case models_1.MessageTag.LoginRequest:
logging_1.rootPushLogger.debug(`Push client - Login request`, { message: JSON.stringify(message) });
break;
case models_1.MessageTag.IqStanza:
logging_1.rootPushLogger.debug(`Push client - IqStanza: Not implemented`, { message: JSON.stringify(message) });
break;
default:
logging_1.rootPushLogger.debug(`Push client - Unknown message`, { message: JSON.stringify(message) });
return;
}
this.streamId++;
}
handleHeartbeatPing(message) {
logging_1.rootPushLogger.debug(`Push client - Heartbeat ping`, { message: JSON.stringify(message) });
let streamId = undefined;
let status = undefined;
if (this.newStreamIdAvailable()) {
streamId = this.getStreamId();
}
if (message.object && message.object.status) {
status = message.object.status;
}
if (this.client)
this.client.write(this.buildHeartbeatAckRequest(streamId, status));
}
handleHeartbeatAck(message) {
logging_1.rootPushLogger.debug(`Push client - Heartbeat acknowledge`, { message: JSON.stringify(message) });
}
convertPayloadMessage(message) {
const { appData, ...otherData } = message.object;
const messageData = {};
appData.forEach((kv) => {
if (kv.key === "payload") {
const payload = (0, utils_1.parseJSON)((0, utils_2.getNullTerminatedString)(Buffer.from(kv.value, "base64"), "utf8"), logging_1.rootPushLogger);
messageData[kv.key] = payload;
}
else {
messageData[kv.key] = kv.value;
}
});
return {
...otherData,
payload: messageData,
};
}
getStreamId() {
this.lastStreamIdReported = this.streamId;
return this.streamId;
}
newStreamIdAvailable() {
return this.lastStreamIdReported != this.streamId;
}
scheduleHeartbeat(client) {
if (client.sendHeartbeat()) {
this.heartbeatTimeout = setTimeout(() => {
this.scheduleHeartbeat(client);
}, client.getHeartbeatInterval());
}
else {
logging_1.rootPushLogger.debug("Push client - Heartbeat disabled!");
}
}
sendHeartbeat() {
let streamId = undefined;
if (this.newStreamIdAvailable()) {
streamId = this.getStreamId();
}
if (this.client && this.isConnected()) {
logging_1.rootPushLogger.debug(`Push client - Sending heartbeat...`, { streamId: streamId });
this.client.write(this.buildHeartbeatPingRequest(streamId));
return true;
}
else {
logging_1.rootPushLogger.debug("Push client - No more connected, reconnect...");
this.scheduleReconnect();
}
return false;
}
isConnected() {
return this.loggedIn;
}
getHeartbeatInterval() {
return this.HEARTBEAT_INTERVAL;
}
getCurrentDelay() {
const delay = this.currentDelay == 0 ? 5000 : this.currentDelay;
if (this.currentDelay < 60000)
this.currentDelay += 10000;
if (this.currentDelay >= 60000 && this.currentDelay < 600000)
this.currentDelay += 60000;
return delay;
}
resetCurrentDelay() {
this.currentDelay = 0;
}
scheduleReconnect() {
const delay = this.getCurrentDelay();
logging_1.rootPushLogger.debug("Push client - Schedule reconnect...", { delay: delay });
if (!this.reconnectTimeout)
this.reconnectTimeout = setTimeout(() => {
this.connect();
}, delay);
}
close() {
const wasConnected = this.isConnected();
this.initialize();
if (wasConnected)
this.emit("close");
}
}
exports.PushClient = PushClient;
//# sourceMappingURL=client.js.map

1
build/push/client.js.map Normal file

File diff suppressed because one or more lines are too long

73
build/push/error.d.ts vendored Normal file
View File

@ -0,0 +1,73 @@
import { BaseError, Jsonable } from "../error";
export declare class UnknownExpiryFormaError extends BaseError {
constructor(message: string, options?: {
cause?: Error;
context?: Jsonable;
});
}
export declare class FidRegistrationFailedError extends BaseError {
constructor(message: string, options?: {
cause?: Error;
context?: Jsonable;
});
}
export declare class RenewFidTokenFailedError extends BaseError {
constructor(message: string, options?: {
cause?: Error;
context?: Jsonable;
});
}
export declare class ExecuteCheckInError extends BaseError {
constructor(message: string, options?: {
cause?: Error;
context?: Jsonable;
});
}
export declare class RegisterGcmError extends BaseError {
constructor(message: string, options?: {
cause?: Error;
context?: Jsonable;
});
}
export declare class BuildLoginRequestError extends BaseError {
constructor(message: string, options?: {
cause?: Error;
context?: Jsonable;
});
}
export declare class BuildHeartbeatPingRequestError extends BaseError {
constructor(message: string, options?: {
cause?: Error;
context?: Jsonable;
});
}
export declare class BuildHeartbeatAckRequestError extends BaseError {
constructor(message: string, options?: {
cause?: Error;
context?: Jsonable;
});
}
export declare class FidGenerationError extends BaseError {
constructor(message: string, options?: {
cause?: Error;
context?: Jsonable;
});
}
export declare class MCSProtocolVersionError extends BaseError {
constructor(message: string, options?: {
cause?: Error;
context?: Jsonable;
});
}
export declare class MCSProtocolProcessingStateError extends BaseError {
constructor(message: string, options?: {
cause?: Error;
context?: Jsonable;
});
}
export declare class MCSProtocolMessageTagError extends BaseError {
constructor(message: string, options?: {
cause?: Error;
context?: Jsonable;
});
}

101
build/push/error.js Normal file
View File

@ -0,0 +1,101 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.MCSProtocolMessageTagError = exports.MCSProtocolProcessingStateError = exports.MCSProtocolVersionError = exports.FidGenerationError = exports.BuildHeartbeatAckRequestError = exports.BuildHeartbeatPingRequestError = exports.BuildLoginRequestError = exports.RegisterGcmError = exports.ExecuteCheckInError = exports.RenewFidTokenFailedError = exports.FidRegistrationFailedError = exports.UnknownExpiryFormaError = void 0;
const error_1 = require("../error");
class UnknownExpiryFormaError extends error_1.BaseError {
constructor(message, options = {}) {
super(message, options);
Object.setPrototypeOf(this, new.target.prototype);
this.name = UnknownExpiryFormaError.name;
}
}
exports.UnknownExpiryFormaError = UnknownExpiryFormaError;
class FidRegistrationFailedError extends error_1.BaseError {
constructor(message, options = {}) {
super(message, options);
Object.setPrototypeOf(this, new.target.prototype);
this.name = FidRegistrationFailedError.name;
}
}
exports.FidRegistrationFailedError = FidRegistrationFailedError;
class RenewFidTokenFailedError extends error_1.BaseError {
constructor(message, options = {}) {
super(message, options);
Object.setPrototypeOf(this, new.target.prototype);
this.name = RenewFidTokenFailedError.name;
}
}
exports.RenewFidTokenFailedError = RenewFidTokenFailedError;
class ExecuteCheckInError extends error_1.BaseError {
constructor(message, options = {}) {
super(message, options);
Object.setPrototypeOf(this, new.target.prototype);
this.name = ExecuteCheckInError.name;
}
}
exports.ExecuteCheckInError = ExecuteCheckInError;
class RegisterGcmError extends error_1.BaseError {
constructor(message, options = {}) {
super(message, options);
Object.setPrototypeOf(this, new.target.prototype);
this.name = RegisterGcmError.name;
}
}
exports.RegisterGcmError = RegisterGcmError;
class BuildLoginRequestError extends error_1.BaseError {
constructor(message, options = {}) {
super(message, options);
Object.setPrototypeOf(this, new.target.prototype);
this.name = BuildLoginRequestError.name;
}
}
exports.BuildLoginRequestError = BuildLoginRequestError;
class BuildHeartbeatPingRequestError extends error_1.BaseError {
constructor(message, options = {}) {
super(message, options);
Object.setPrototypeOf(this, new.target.prototype);
this.name = BuildHeartbeatPingRequestError.name;
}
}
exports.BuildHeartbeatPingRequestError = BuildHeartbeatPingRequestError;
class BuildHeartbeatAckRequestError extends error_1.BaseError {
constructor(message, options = {}) {
super(message, options);
Object.setPrototypeOf(this, new.target.prototype);
this.name = BuildHeartbeatAckRequestError.name;
}
}
exports.BuildHeartbeatAckRequestError = BuildHeartbeatAckRequestError;
class FidGenerationError extends error_1.BaseError {
constructor(message, options = {}) {
super(message, options);
Object.setPrototypeOf(this, new.target.prototype);
this.name = FidGenerationError.name;
}
}
exports.FidGenerationError = FidGenerationError;
class MCSProtocolVersionError extends error_1.BaseError {
constructor(message, options = {}) {
super(message, options);
Object.setPrototypeOf(this, new.target.prototype);
this.name = MCSProtocolVersionError.name;
}
}
exports.MCSProtocolVersionError = MCSProtocolVersionError;
class MCSProtocolProcessingStateError extends error_1.BaseError {
constructor(message, options = {}) {
super(message, options);
Object.setPrototypeOf(this, new.target.prototype);
this.name = MCSProtocolProcessingStateError.name;
}
}
exports.MCSProtocolProcessingStateError = MCSProtocolProcessingStateError;
class MCSProtocolMessageTagError extends error_1.BaseError {
constructor(message, options = {}) {
super(message, options);
Object.setPrototypeOf(this, new.target.prototype);
this.name = MCSProtocolMessageTagError.name;
}
}
exports.MCSProtocolMessageTagError = MCSProtocolMessageTagError;
//# sourceMappingURL=error.js.map

1
build/push/error.js.map Normal file
View File

@ -0,0 +1 @@
{"version":3,"file":"error.js","sourceRoot":"","sources":["../../src/push/error.ts"],"names":[],"mappings":"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"}

6
build/push/index.d.ts vendored Normal file
View File

@ -0,0 +1,6 @@
export * from "./models";
export * from "./interfaces";
export * from "./service";
export * from "./types";
export * from "./error";
export { sleep, convertTimestampMs } from "./utils";

26
build/push/index.js Normal file
View File

@ -0,0 +1,26 @@
"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 __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.convertTimestampMs = exports.sleep = void 0;
__exportStar(require("./models"), exports);
__exportStar(require("./interfaces"), exports);
__exportStar(require("./service"), exports);
__exportStar(require("./types"), exports);
__exportStar(require("./error"), exports);
var utils_1 = require("./utils");
Object.defineProperty(exports, "sleep", { enumerable: true, get: function () { return utils_1.sleep; } });
Object.defineProperty(exports, "convertTimestampMs", { enumerable: true, get: function () { return utils_1.convertTimestampMs; } });
//# sourceMappingURL=index.js.map

1
build/push/index.js.map Normal file
View File

@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/push/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,2CAAyB;AACzB,+CAA6B;AAC7B,4CAA0B;AAC1B,0CAAwB;AACxB,0CAAwB;AACxB,iCAAoD;AAA3C,8FAAA,KAAK,OAAA;AAAE,2GAAA,kBAAkB,OAAA"}

19
build/push/interfaces.d.ts vendored Normal file
View File

@ -0,0 +1,19 @@
import { Credentials, RawPushMessage, PushMessage } from "./models";
export interface PushNotificationServiceEvents {
"credential": (credentials: Credentials) => void;
"connect": (token: string) => void;
"close": () => void;
"raw message": (message: RawPushMessage) => void;
"message": (message: PushMessage) => void;
}
export interface PushClientEvents {
"connect": () => void;
"close": () => void;
"message": (message: RawPushMessage) => void;
}
export interface PushClientParserEvents {
"message": (message: {
tag: number;
object: any;
}) => void;
}

3
build/push/interfaces.js Normal file
View File

@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=interfaces.js.map

Some files were not shown because too many files have changed in this diff Show More