eufy-security-client 3.6.0 → 3.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.prettierignore/342/200/216 +8 -0
- package/.prettierrc +11 -0
- package/README.md +18 -0
- package/a.ts +61 -0
- package/build/error.js.map +1 -1
- package/build/eufysecurity.d.ts +1 -0
- package/build/eufysecurity.js +721 -224
- package/build/eufysecurity.js.map +1 -1
- package/build/http/api.d.ts +29 -0
- package/build/http/api.js +991 -701
- package/build/http/api.js.map +1 -1
- package/build/http/cache.js.map +1 -1
- package/build/http/const.d.ts +6 -1
- package/build/http/const.js +2044 -7536
- package/build/http/const.js.map +1 -1
- package/build/http/device.d.ts +4 -0
- package/build/http/device.js +1325 -440
- package/build/http/device.js.map +1 -1
- package/build/http/error.js.map +1 -1
- package/build/http/index.js.map +1 -1
- package/build/http/interfaces.d.ts +22 -15
- package/build/http/models.d.ts +2 -1
- package/build/http/parameter.js +74 -63
- package/build/http/parameter.js.map +1 -1
- package/build/http/station.d.ts +20 -2
- package/build/http/station.js +8639 -3566
- package/build/http/station.js.map +1 -1
- package/build/http/types.d.ts +12 -0
- package/build/http/types.js +297 -155
- package/build/http/types.js.map +1 -1
- package/build/http/utils.d.ts +16 -6
- package/build/http/utils.js +335 -208
- package/build/http/utils.js.map +1 -1
- package/build/index.js.map +1 -1
- package/build/interfaces.d.ts +4 -3
- package/build/logging.js +8 -13
- package/build/logging.js.map +1 -1
- package/build/mqtt/interface.d.ts +2 -2
- package/build/mqtt/service.js +12 -3
- package/build/mqtt/service.js.map +1 -1
- package/build/p2p/ble.js +7 -6
- package/build/p2p/ble.js.map +1 -1
- package/build/p2p/error.js.map +1 -1
- package/build/p2p/interfaces.d.ts +41 -6
- package/build/p2p/session.js +1484 -383
- package/build/p2p/session.js.map +1 -1
- package/build/p2p/talkback.js.map +1 -1
- package/build/p2p/types.js +36 -36
- package/build/p2p/types.js.map +1 -1
- package/build/p2p/utils.d.ts +10 -0
- package/build/p2p/utils.js +183 -90
- package/build/p2p/utils.js.map +1 -1
- package/build/push/client.js +15 -4
- package/build/push/client.js.map +1 -1
- package/build/push/error.js.map +1 -1
- package/build/push/interfaces.d.ts +8 -8
- package/build/push/models.js.map +1 -1
- package/build/push/parser.js +6 -2
- package/build/push/parser.js.map +1 -1
- package/build/push/service.js +214 -85
- package/build/push/service.js.map +1 -1
- package/build/push/types.js.map +1 -1
- package/build/push/utils.js.map +1 -1
- package/build/utils.js +7 -15
- package/build/utils.js.map +1 -1
- package/coverage/clover.xml +11133 -13648
- package/coverage/coverage-final.json +20 -30
- package/coverage/lcov-report/error.ts.html +3 -3
- package/coverage/lcov-report/index.html +50 -65
- package/coverage/lcov-report/logging.ts.html +598 -0
- package/coverage/lcov.info +21072 -25751
- package/dont-care.js +101 -0
- package/package.json +9 -5
- package/build/package.json +0 -81
package/build/http/utils.js
CHANGED
|
@@ -3,7 +3,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.
|
|
6
|
+
exports.getWaitSeconds = exports.isSmartLockNotification = exports.switchSmartLockNotification = exports.getLockEventType = exports.getFloodLightT8425Notification = exports.isFloodlightT8425NotitficationEnabled = exports.getIndoorNotification = exports.isIndoorNotitficationEnabled = exports.getIndoorS350DetectionMode = exports.isIndoorS350DetectionModeEnabled = exports.getT8110DetectionMode = exports.isT8110DetectionModeEnabled = 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.isDeliveryPackageType = 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 = exports.normalizeVersionString = void 0;
|
|
7
|
+
exports.getRandomPhoneModel = exports.loadEventImage = exports.loadImageOverP2P = void 0;
|
|
7
8
|
const crypto_1 = require("crypto");
|
|
8
9
|
const const_1 = require("./const");
|
|
9
10
|
const md5_1 = __importDefault(require("crypto-js/md5"));
|
|
@@ -16,72 +17,110 @@ const types_2 = require("./../push/types");
|
|
|
16
17
|
const logging_1 = require("../logging");
|
|
17
18
|
const utils_1 = require("../utils");
|
|
18
19
|
const normalizeVersionString = function (version) {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
const partsLength = parts.length;
|
|
32
|
-
for (i = partsLength - 1; i >= 0; i -= 1) {
|
|
33
|
-
value = parts[i];
|
|
34
|
-
if (value === 0) {
|
|
35
|
-
parts.length -= 1;
|
|
36
|
-
}
|
|
37
|
-
else {
|
|
38
|
-
break;
|
|
39
|
-
}
|
|
20
|
+
/**
|
|
21
|
+
*
|
|
22
|
+
* Normalise version strings into an array of integers, otherwise if a version was not found it returns null
|
|
23
|
+
* Example of a version is 1.4.30.33
|
|
24
|
+
*
|
|
25
|
+
* @param version
|
|
26
|
+
*/
|
|
27
|
+
const match = version.match(/\d+(?:\.\d+)+/);
|
|
28
|
+
if (match == null)
|
|
29
|
+
return null;
|
|
30
|
+
else {
|
|
31
|
+
return match[0].split(".").map(Number);
|
|
40
32
|
}
|
|
41
|
-
return parts;
|
|
42
33
|
};
|
|
34
|
+
exports.normalizeVersionString = normalizeVersionString;
|
|
43
35
|
const isGreaterEqualMinVersion = function (minimal_version, current_version) {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
36
|
+
/**
|
|
37
|
+
*
|
|
38
|
+
* Test the minimal version set is working with the current version by return true if it is equal or greater than min version.
|
|
39
|
+
*
|
|
40
|
+
* @param minimal_version
|
|
41
|
+
* @param current_version
|
|
42
|
+
*/
|
|
43
|
+
const min_version = (0, exports.normalizeVersionString)(minimal_version);
|
|
44
|
+
const actual_version = (0, exports.normalizeVersionString)(current_version);
|
|
45
|
+
// Failed to parse actually version
|
|
46
|
+
if (actual_version === null)
|
|
47
|
+
return false;
|
|
48
|
+
// Failed to a parse min version but the current did, so we assume it is greater
|
|
49
|
+
if (min_version === null)
|
|
50
|
+
return true;
|
|
51
|
+
const version_slots = Math.min(min_version.length, actual_version.length);
|
|
47
52
|
let i;
|
|
48
|
-
for
|
|
49
|
-
|
|
50
|
-
|
|
53
|
+
// Loop for each slot to ensure it is greater or equal
|
|
54
|
+
for (i = 0; i < version_slots; i += 1) {
|
|
55
|
+
if (min_version[i] !== actual_version[i]) {
|
|
56
|
+
return min_version[i] < actual_version[i];
|
|
51
57
|
}
|
|
52
58
|
}
|
|
53
|
-
|
|
59
|
+
// If none of the slots are different but the length is the same, it is most likely the slots are the same
|
|
60
|
+
if (min_version.length === actual_version.length) {
|
|
54
61
|
return true;
|
|
55
62
|
}
|
|
56
|
-
return
|
|
63
|
+
return min_version.length < actual_version.length;
|
|
57
64
|
};
|
|
58
65
|
exports.isGreaterEqualMinVersion = isGreaterEqualMinVersion;
|
|
59
66
|
const pad = function (num) {
|
|
67
|
+
/**
|
|
68
|
+
*
|
|
69
|
+
* Convert the number to be absolute, round down and return "0" if lower than 10 or "" otherwise
|
|
70
|
+
* Seems to be used in a scenario where need to add a zero decimal to format a 2 digit string
|
|
71
|
+
*
|
|
72
|
+
* @param num
|
|
73
|
+
*/
|
|
60
74
|
const norm = Math.floor(Math.abs(num));
|
|
61
75
|
return (norm < 10 ? "0" : "") + norm;
|
|
62
76
|
};
|
|
63
77
|
exports.pad = pad;
|
|
64
78
|
const getTimezoneGMTString = function () {
|
|
79
|
+
/**
|
|
80
|
+
* Get timezone to string
|
|
81
|
+
*
|
|
82
|
+
*/
|
|
65
83
|
const tzo = -new Date().getTimezoneOffset();
|
|
66
84
|
const dif = tzo >= 0 ? "+" : "-";
|
|
67
85
|
return `GMT${dif}${(0, exports.pad)(tzo / 60)}:${(0, exports.pad)(tzo % 60)}`;
|
|
68
86
|
};
|
|
69
87
|
exports.getTimezoneGMTString = getTimezoneGMTString;
|
|
70
88
|
const getAbsoluteFilePath = function (device_type, channel, filename) {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
89
|
+
/**
|
|
90
|
+
*
|
|
91
|
+
* Create the path based on two different devices
|
|
92
|
+
*
|
|
93
|
+
* @param device_type
|
|
94
|
+
* @param channel
|
|
95
|
+
* @param filename
|
|
96
|
+
*/
|
|
97
|
+
// TODO : might need to extend to others device with local storage? not sure why only floodlight
|
|
98
|
+
const prefix = device_type === types_1.DeviceType.FLOODLIGHT ? const_1.PATH_DATA_CAMERA : const_1.PATH_MMC_CAMERA;
|
|
99
|
+
return `${prefix}${String(channel).padStart(2, "0")}/${filename}.dat`;
|
|
75
100
|
};
|
|
76
101
|
exports.getAbsoluteFilePath = getAbsoluteFilePath;
|
|
77
102
|
const getImageFilePath = function (device_type, channel, filename) {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
103
|
+
/**
|
|
104
|
+
*
|
|
105
|
+
* Create the image path from a video filename
|
|
106
|
+
*
|
|
107
|
+
* @param device_type
|
|
108
|
+
* @param channel
|
|
109
|
+
* @param filename
|
|
110
|
+
*/
|
|
111
|
+
// TODO : might need to extend to others device with local storage? not sure why only floodlight
|
|
112
|
+
const prefix = device_type === types_1.DeviceType.FLOODLIGHT ? const_1.PATH_DATA_VIDEO : const_1.PATH_MMC_VIDEO;
|
|
113
|
+
return `${prefix}/${filename}_c${String(channel).padStart(2, "0")}.jpg`;
|
|
82
114
|
};
|
|
83
115
|
exports.getImageFilePath = getImageFilePath;
|
|
84
116
|
const isNotificationSwitchMode = function (value, mode) {
|
|
117
|
+
/**
|
|
118
|
+
*
|
|
119
|
+
* Check if the mode is set to notification
|
|
120
|
+
*
|
|
121
|
+
* @param value
|
|
122
|
+
* @param mode
|
|
123
|
+
*/
|
|
85
124
|
if (value === 1)
|
|
86
125
|
value = 240;
|
|
87
126
|
return (value & mode) !== 0;
|
|
@@ -98,146 +137,170 @@ const switchNotificationMode = function (currentValue, mode, enable) {
|
|
|
98
137
|
else {
|
|
99
138
|
result = ~mode & currentValue;
|
|
100
139
|
}
|
|
101
|
-
if ((0, exports.isNotificationSwitchMode)(result, types_1.NotificationSwitchMode.SCHEDULE) &&
|
|
140
|
+
if ((0, exports.isNotificationSwitchMode)(result, types_1.NotificationSwitchMode.SCHEDULE) &&
|
|
141
|
+
(0, exports.isNotificationSwitchMode)(result, types_1.NotificationSwitchMode.APP) &&
|
|
142
|
+
(0, exports.isNotificationSwitchMode)(result, types_1.NotificationSwitchMode.GEOFENCE) &&
|
|
143
|
+
(0, exports.isNotificationSwitchMode)(result, types_1.NotificationSwitchMode.KEYPAD)) {
|
|
102
144
|
result = 1; /* ALL */
|
|
103
145
|
}
|
|
104
146
|
return result;
|
|
105
147
|
};
|
|
106
148
|
exports.switchNotificationMode = switchNotificationMode;
|
|
149
|
+
// TODO : remove device , not needed
|
|
107
150
|
const calculateWifiSignalLevel = function (device, rssi) {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
return
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
if (rssi >= 0) {
|
|
131
|
-
return types_1.SignalLevel.NO_SIGNAL;
|
|
132
|
-
}
|
|
133
|
-
if (rssi >= -60) {
|
|
134
|
-
return types_1.SignalLevel.FULL;
|
|
135
|
-
}
|
|
136
|
-
if (rssi >= -70) {
|
|
137
|
-
return types_1.SignalLevel.STRONG;
|
|
138
|
-
}
|
|
139
|
-
return rssi >= -80 ? types_1.SignalLevel.NORMAL : types_1.SignalLevel.WEAK;
|
|
140
|
-
}
|
|
141
|
-
else if (device.isBatteryDoorbell()) {
|
|
142
|
-
if (rssi >= -65) {
|
|
143
|
-
return types_1.SignalLevel.FULL;
|
|
144
|
-
}
|
|
145
|
-
if (rssi >= -75) {
|
|
146
|
-
return types_1.SignalLevel.STRONG;
|
|
147
|
-
}
|
|
148
|
-
return rssi >= -85 ? types_1.SignalLevel.NORMAL : types_1.SignalLevel.WEAK;
|
|
149
|
-
}
|
|
150
|
-
else {
|
|
151
|
-
if (rssi >= 0) {
|
|
152
|
-
return types_1.SignalLevel.NO_SIGNAL;
|
|
153
|
-
}
|
|
154
|
-
if (rssi >= -65) {
|
|
155
|
-
return types_1.SignalLevel.FULL;
|
|
156
|
-
}
|
|
157
|
-
if (rssi >= -75) {
|
|
158
|
-
return types_1.SignalLevel.STRONG;
|
|
159
|
-
}
|
|
160
|
-
return rssi >= -85 ? types_1.SignalLevel.NORMAL : types_1.SignalLevel.WEAK;
|
|
161
|
-
}
|
|
151
|
+
/**
|
|
152
|
+
* Calculate the signal strength based on the RSSI
|
|
153
|
+
*
|
|
154
|
+
* Using this scale for reference
|
|
155
|
+
* Excellent/Very Strong (-30 dBm to -50 dBm)
|
|
156
|
+
* Good/Strong (-50 dBm to -60 dBm)
|
|
157
|
+
* Fair/Good (-60 dBm to -67 dBm)
|
|
158
|
+
* Weak/Fair (-67 dBm to -70 dBm)
|
|
159
|
+
* Very Weak/Poor (-70 dBm to -80 dBm)
|
|
160
|
+
* Unusable (-80 dBm to -90 dBm or lower)
|
|
161
|
+
*
|
|
162
|
+
*/
|
|
163
|
+
if (rssi >= -50)
|
|
164
|
+
return types_1.SignalLevel.FULL;
|
|
165
|
+
else if (rssi < -50 && rssi >= -60)
|
|
166
|
+
return types_1.SignalLevel.STRONG;
|
|
167
|
+
else if (rssi < -60 && rssi >= -67)
|
|
168
|
+
return types_1.SignalLevel.NORMAL;
|
|
169
|
+
else if (rssi < -67 && rssi >= -80)
|
|
170
|
+
return types_1.SignalLevel.WEAK;
|
|
171
|
+
else
|
|
172
|
+
return types_1.SignalLevel.NO_SIGNAL;
|
|
162
173
|
};
|
|
163
174
|
exports.calculateWifiSignalLevel = calculateWifiSignalLevel;
|
|
164
175
|
const calculateCellularSignalLevel = function (rssi) {
|
|
165
|
-
|
|
176
|
+
/**
|
|
177
|
+
* Calculate the signal strength from the RSSI ( this has a different scale than wifi )
|
|
178
|
+
*
|
|
179
|
+
* Excellent (>-65 to -70 dBm)
|
|
180
|
+
* Good (-70 to -85 dBm)
|
|
181
|
+
* Fair (-85 to -95 dBm)
|
|
182
|
+
* Poor (-95 to -100 dBm)
|
|
183
|
+
* Unusable/No Signal (<-100 to -110 dBm)
|
|
184
|
+
*
|
|
185
|
+
*/
|
|
186
|
+
if (rssi >= 0)
|
|
166
187
|
return types_1.SignalLevel.NO_SIGNAL;
|
|
167
|
-
|
|
168
|
-
if (rssi >= -90) {
|
|
188
|
+
if (rssi >= -70)
|
|
169
189
|
return types_1.SignalLevel.FULL;
|
|
170
|
-
|
|
171
|
-
if (rssi >= -95) {
|
|
190
|
+
else if (rssi < -70 && rssi >= -85)
|
|
172
191
|
return types_1.SignalLevel.STRONG;
|
|
173
|
-
|
|
174
|
-
|
|
192
|
+
else if (rssi < -85 && rssi >= -95)
|
|
193
|
+
return types_1.SignalLevel.NORMAL;
|
|
194
|
+
else if (rssi < -95 && rssi >= -100)
|
|
195
|
+
return types_1.SignalLevel.WEAK;
|
|
196
|
+
else
|
|
197
|
+
return types_1.SignalLevel.NO_SIGNAL;
|
|
175
198
|
};
|
|
176
199
|
exports.calculateCellularSignalLevel = calculateCellularSignalLevel;
|
|
177
200
|
const encryptAPIData = (data, key) => {
|
|
178
201
|
const cipher = (0, crypto_1.createCipheriv)("aes-256-cbc", key, key.subarray(0, 16));
|
|
179
|
-
return
|
|
180
|
-
cipher.final("base64"));
|
|
202
|
+
return cipher.update(data, "utf8", "base64") + cipher.final("base64");
|
|
181
203
|
};
|
|
182
204
|
exports.encryptAPIData = encryptAPIData;
|
|
183
205
|
const decryptAPIData = (data, key) => {
|
|
184
206
|
const cipher = (0, crypto_1.createDecipheriv)("aes-256-cbc", key, key.subarray(0, 16));
|
|
185
|
-
return Buffer.concat([
|
|
186
|
-
cipher.update(data, "base64"),
|
|
187
|
-
cipher.final()
|
|
188
|
-
]);
|
|
207
|
+
return Buffer.concat([cipher.update(data, "base64"), cipher.final()]);
|
|
189
208
|
};
|
|
190
209
|
exports.decryptAPIData = decryptAPIData;
|
|
191
|
-
const getBlocklist = function (
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
210
|
+
const getBlocklist = function (distanceArray) {
|
|
211
|
+
/**
|
|
212
|
+
* It looks like it taken from the decompiled app from Eufy in the file SimpleDetectionGroup.java
|
|
213
|
+
*
|
|
214
|
+
* From asking, AI, this function it creates a bitmask representing which radar points meet that distance requirement.
|
|
215
|
+
* Finally, it applies a specific bitwise transformation to that mask.
|
|
216
|
+
*
|
|
217
|
+
* Potential description: Generates radar configuration parameters based on distance thresholds.
|
|
218
|
+
*
|
|
219
|
+
* * @param {number[]} distanceArray - An array of integers representing distances.
|
|
220
|
+
* * @returns {number[]} A list of 5 bitmask integers.
|
|
221
|
+
*/
|
|
222
|
+
const requestParams = [];
|
|
223
|
+
for (let threshold = 1; threshold <= 5; threshold++) {
|
|
224
|
+
let bitmask = 0;
|
|
225
|
+
let bitPosition = 1;
|
|
226
|
+
// Iterate through each distance in the array
|
|
227
|
+
for (const distance of distanceArray) {
|
|
228
|
+
if (distance >= threshold) {
|
|
229
|
+
bitmask |= bitPosition;
|
|
200
230
|
}
|
|
201
|
-
|
|
231
|
+
// Shift bitPosition left by 1 (multiply by 2)
|
|
232
|
+
bitPosition <<= 1;
|
|
202
233
|
}
|
|
203
|
-
|
|
204
|
-
|
|
234
|
+
let finalValue = 0;
|
|
235
|
+
// Logic for specific bit patterns
|
|
236
|
+
if (bitmask === 0) {
|
|
237
|
+
finalValue = 0xffff; // 65535
|
|
205
238
|
}
|
|
206
|
-
else if (
|
|
207
|
-
|
|
239
|
+
else if (bitmask !== 0xff && bitmask !== 0xffff) {
|
|
240
|
+
// Flip the bits and add the 0xFF00 (65280) high-byte padding
|
|
241
|
+
finalValue = (bitmask ^ 0xff) + 0xff00;
|
|
208
242
|
}
|
|
209
|
-
|
|
243
|
+
requestParams.push(finalValue);
|
|
210
244
|
}
|
|
211
|
-
return
|
|
245
|
+
return requestParams;
|
|
212
246
|
};
|
|
213
247
|
exports.getBlocklist = getBlocklist;
|
|
214
|
-
const getDistances = function (
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
248
|
+
const getDistances = function (rawDistanceData) {
|
|
249
|
+
/**
|
|
250
|
+
* It looks like it taken from the decompiled app from Eufy in the file SimpleDetectionGroup.java
|
|
251
|
+
*
|
|
252
|
+
* From asking AI:
|
|
253
|
+
* Processes raw radar sensor data to map object detections into spatial sectors.
|
|
254
|
+
* This method iterates through a list of distance data, where each element represents
|
|
255
|
+
* a depth level and its bits represent angular sectors. It inverts the bitmask,
|
|
256
|
+
* identifies active detections via bit-shifting, and updates a collection of
|
|
257
|
+
* RadarSelectInfo objects with the corresponding angle and proximity distance.
|
|
258
|
+
*
|
|
259
|
+
* @param rawDistanceData A list of integers where each bit represents a detection
|
|
260
|
+
* at a specific angle, and the list index represents depth.
|
|
261
|
+
*/
|
|
262
|
+
const radarSectors = [3, 3, 3, 3, 3, 3, 3, 3];
|
|
263
|
+
let distanceStep = 0;
|
|
264
|
+
for (const rawValue of rawDistanceData) {
|
|
265
|
+
// Bitwise NOT/XOR to invert the signal (common in hardware where 0=detected)
|
|
266
|
+
let invertedBits = rawValue ^ 65535;
|
|
267
|
+
distanceStep++;
|
|
268
|
+
if (invertedBits !== 0) {
|
|
269
|
+
for (let i = 0; i < radarSectors.length; i++) {
|
|
270
|
+
const isObjectDetected = invertedBits & 1; // Check if the lowest bit is set
|
|
271
|
+
// If the bit was 1, mark this sector with the current distance
|
|
272
|
+
if (isObjectDetected > 0) {
|
|
273
|
+
radarSectors[i] = distanceStep;
|
|
225
274
|
}
|
|
226
|
-
|
|
275
|
+
// Shift bits to check the next angle in the next iteration
|
|
276
|
+
invertedBits = invertedBits >> 1;
|
|
227
277
|
}
|
|
228
278
|
}
|
|
229
279
|
}
|
|
230
|
-
return
|
|
280
|
+
return radarSectors;
|
|
231
281
|
};
|
|
232
282
|
exports.getDistances = getDistances;
|
|
283
|
+
const isDeliveryPackageType = function (value) {
|
|
284
|
+
/**
|
|
285
|
+
* Seems to be coming from EventData.java
|
|
286
|
+
*
|
|
287
|
+
*/
|
|
288
|
+
return (value & 65536) == 65536;
|
|
289
|
+
};
|
|
290
|
+
exports.isDeliveryPackageType = isDeliveryPackageType;
|
|
233
291
|
const isHB3DetectionModeEnabled = function (value, type) {
|
|
292
|
+
/**
|
|
293
|
+
* Detection if Mode is enabled
|
|
294
|
+
*
|
|
295
|
+
*/
|
|
296
|
+
const prefixCode = (type & value) == type;
|
|
234
297
|
if (type === types_1.HB3DetectionTypes.HUMAN_RECOGNITION) {
|
|
235
|
-
return
|
|
298
|
+
return prefixCode && (0, exports.isDeliveryPackageType)(value);
|
|
236
299
|
}
|
|
237
300
|
else if (type === types_1.HB3DetectionTypes.HUMAN_DETECTION) {
|
|
238
|
-
return
|
|
301
|
+
return prefixCode && (value & 1) == 1;
|
|
239
302
|
}
|
|
240
|
-
return
|
|
303
|
+
return prefixCode;
|
|
241
304
|
};
|
|
242
305
|
exports.isHB3DetectionModeEnabled = isHB3DetectionModeEnabled;
|
|
243
306
|
const getHB3DetectionMode = function (value, type, enable) {
|
|
@@ -245,7 +308,7 @@ const getHB3DetectionMode = function (value, type, enable) {
|
|
|
245
308
|
if (!enable) {
|
|
246
309
|
if (type === types_1.HB3DetectionTypes.HUMAN_RECOGNITION) {
|
|
247
310
|
const tmp = (type & value) == type ? type ^ value : value;
|
|
248
|
-
result = (
|
|
311
|
+
result = (0, exports.isDeliveryPackageType)(value) ? tmp ^ 65536 : tmp;
|
|
249
312
|
}
|
|
250
313
|
else if (type === types_1.HB3DetectionTypes.HUMAN_DETECTION) {
|
|
251
314
|
const tmp = (type & value) == type ? type ^ value : value;
|
|
@@ -281,6 +344,7 @@ exports.getEufyTimezone = getEufyTimezone;
|
|
|
281
344
|
const getAdvancedLockTimezone = function (stationSN) {
|
|
282
345
|
const timezone = (0, exports.getEufyTimezone)();
|
|
283
346
|
if (timezone !== undefined) {
|
|
347
|
+
// TODO: make this a method to check whatever we need to check for the station
|
|
284
348
|
if (stationSN.startsWith("T8520") && (0, exports.isGreaterEqualMinVersion)("1.2.8.6", stationSN))
|
|
285
349
|
return `${timezone.timeZoneGMT}|1.${timezone.timeSn}`;
|
|
286
350
|
else
|
|
@@ -294,7 +358,12 @@ class WritePayload {
|
|
|
294
358
|
data = Buffer.from([]);
|
|
295
359
|
write(bytes) {
|
|
296
360
|
const tmp_data = Buffer.from(bytes);
|
|
297
|
-
this.data = Buffer.concat([
|
|
361
|
+
this.data = Buffer.concat([
|
|
362
|
+
this.data,
|
|
363
|
+
Buffer.from([this.split_byte]),
|
|
364
|
+
Buffer.from([tmp_data.length & 255]),
|
|
365
|
+
tmp_data,
|
|
366
|
+
]);
|
|
298
367
|
this.split_byte += 1;
|
|
299
368
|
}
|
|
300
369
|
getData() {
|
|
@@ -303,6 +372,11 @@ class WritePayload {
|
|
|
303
372
|
}
|
|
304
373
|
exports.WritePayload = WritePayload;
|
|
305
374
|
class ParsePayload {
|
|
375
|
+
/**
|
|
376
|
+
* extract specific pieces of data from a binary buffer
|
|
377
|
+
*
|
|
378
|
+
* @private
|
|
379
|
+
*/
|
|
306
380
|
data;
|
|
307
381
|
constructor(data) {
|
|
308
382
|
this.data = data;
|
|
@@ -371,7 +445,7 @@ class ParsePayload {
|
|
|
371
445
|
break;
|
|
372
446
|
}
|
|
373
447
|
const nextStep = this.getNextStep(value, currentPosition, this.data);
|
|
374
|
-
if (
|
|
448
|
+
if (currentPosition + nextStep >= this.data.length) {
|
|
375
449
|
break;
|
|
376
450
|
}
|
|
377
451
|
if (nextStep == 1) {
|
|
@@ -387,31 +461,17 @@ class ParsePayload {
|
|
|
387
461
|
}
|
|
388
462
|
getNextStep(indexValue, position, data) {
|
|
389
463
|
const newPosition = position + 1 + data.readUInt8(position);
|
|
390
|
-
return
|
|
464
|
+
return newPosition == data.length || newPosition > data.length || data.readInt8(newPosition) == indexValue + 1
|
|
465
|
+
? 1
|
|
466
|
+
: 2;
|
|
391
467
|
}
|
|
392
468
|
}
|
|
393
469
|
exports.ParsePayload = ParsePayload;
|
|
394
|
-
/*export const generateHash = function(data: Buffer): number {
|
|
395
|
-
let result = 0;
|
|
396
|
-
for (const value of data) {
|
|
397
|
-
result = result ^ value;
|
|
398
|
-
}
|
|
399
|
-
return result;
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
export const encodeSmartSafeData = function(command: number, payload: Buffer): Buffer {
|
|
403
|
-
const header = Buffer.from(SmartSafe.DATA_HEADER);
|
|
404
|
-
const size = Buffer.allocUnsafe(2);
|
|
405
|
-
size.writeInt16LE(payload.length + 9);
|
|
406
|
-
const versionCode = Buffer.from([SmartSafe.VERSION_CODE]);
|
|
407
|
-
const dataType = Buffer.from([-1]);
|
|
408
|
-
const commandCode = Buffer.from([command]);
|
|
409
|
-
const packageFlag = Buffer.from([-64]);
|
|
410
|
-
const data = Buffer.concat([header, size, versionCode, dataType, commandCode, packageFlag, payload]);
|
|
411
|
-
const hash = generateHash(data);
|
|
412
|
-
return Buffer.concat([data, Buffer.from([hash])]);
|
|
413
|
-
}*/
|
|
414
470
|
const encodePasscode = function (pass) {
|
|
471
|
+
/**
|
|
472
|
+
* Encode the passcode for smart lock
|
|
473
|
+
*
|
|
474
|
+
*/
|
|
415
475
|
let result = "";
|
|
416
476
|
for (let i = 0; i < pass.length; i++)
|
|
417
477
|
result += pass.charCodeAt(i).toString(16);
|
|
@@ -438,7 +498,7 @@ const hexWeek = function (schedule) {
|
|
|
438
498
|
const MONDAY = 2;
|
|
439
499
|
const TUESDAY = 4;
|
|
440
500
|
const WEDNESDAY = 8;
|
|
441
|
-
const
|
|
501
|
+
const THURSDAY = 16;
|
|
442
502
|
const FRIDAY = 32;
|
|
443
503
|
const SATURDAY = 64;
|
|
444
504
|
let result = 0;
|
|
@@ -456,7 +516,7 @@ const hexWeek = function (schedule) {
|
|
|
456
516
|
result |= WEDNESDAY;
|
|
457
517
|
}
|
|
458
518
|
if (schedule.week.thursday) {
|
|
459
|
-
result |=
|
|
519
|
+
result |= THURSDAY;
|
|
460
520
|
}
|
|
461
521
|
if (schedule.week.friday) {
|
|
462
522
|
result |= FRIDAY;
|
|
@@ -474,18 +534,22 @@ const hexStringScheduleToSchedule = function (startDay, startTime, endDay, endTi
|
|
|
474
534
|
const MONDAY = 2;
|
|
475
535
|
const TUESDAY = 4;
|
|
476
536
|
const WEDNESDAY = 8;
|
|
477
|
-
const
|
|
537
|
+
const THURSDAY = 16;
|
|
478
538
|
const FRIDAY = 32;
|
|
479
539
|
const SATURDAY = 64;
|
|
480
540
|
const weekNumber = Number.parseInt(week, 16);
|
|
481
541
|
return {
|
|
482
|
-
startDateTime: startDay === "00000000"
|
|
483
|
-
|
|
542
|
+
startDateTime: startDay === "00000000"
|
|
543
|
+
? undefined
|
|
544
|
+
: 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)),
|
|
545
|
+
endDateTime: endDay === "ffffffff"
|
|
546
|
+
? undefined
|
|
547
|
+
: 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)),
|
|
484
548
|
week: {
|
|
485
549
|
monday: (weekNumber & MONDAY) == MONDAY,
|
|
486
550
|
tuesday: (weekNumber & TUESDAY) == TUESDAY,
|
|
487
551
|
wednesday: (weekNumber & WEDNESDAY) == WEDNESDAY,
|
|
488
|
-
thursday: (weekNumber &
|
|
552
|
+
thursday: (weekNumber & THURSDAY) == THURSDAY,
|
|
489
553
|
friday: (weekNumber & FRIDAY) == FRIDAY,
|
|
490
554
|
saturday: (weekNumber & SATURDAY) == SATURDAY,
|
|
491
555
|
sunday: (weekNumber & SUNDAY) == SUNDAY,
|
|
@@ -514,36 +578,42 @@ const getIdSuffix = function (p2pDid) {
|
|
|
514
578
|
return result;
|
|
515
579
|
};
|
|
516
580
|
exports.getIdSuffix = getIdSuffix;
|
|
517
|
-
const getImageBaseCode = function (
|
|
581
|
+
const getImageBaseCode = function (serialNumber, p2pDid) {
|
|
518
582
|
let nr = 0;
|
|
519
583
|
try {
|
|
520
|
-
nr = Number.parseInt(`0x${
|
|
584
|
+
nr = Number.parseInt(`0x${serialNumber[serialNumber.length - 1]}`);
|
|
521
585
|
}
|
|
522
586
|
catch (err) {
|
|
523
587
|
const error = (0, error_1.ensureError)(err);
|
|
524
|
-
throw new error_2.ImageBaseCodeError("Error generating image base code", {
|
|
588
|
+
throw new error_2.ImageBaseCodeError("Error generating image base code", {
|
|
589
|
+
cause: error,
|
|
590
|
+
context: { serialnumber: serialNumber, p2pDid: p2pDid },
|
|
591
|
+
});
|
|
525
592
|
}
|
|
526
593
|
nr = (nr + 10) % 10;
|
|
527
|
-
const base =
|
|
594
|
+
const base = serialNumber.substring(nr);
|
|
528
595
|
return `${base}${(0, exports.getIdSuffix)(p2pDid)}`;
|
|
529
596
|
};
|
|
530
597
|
exports.getImageBaseCode = getImageBaseCode;
|
|
531
598
|
const getImageSeed = function (p2pDid, code) {
|
|
532
599
|
try {
|
|
533
|
-
const
|
|
600
|
+
const nCode = Number.parseInt(code.substring(2));
|
|
534
601
|
const prefix = 1000 - (0, exports.getIdSuffix)(p2pDid);
|
|
535
|
-
return (0, md5_1.default)(`${prefix}${
|
|
602
|
+
return (0, md5_1.default)(`${prefix}${nCode}`).toString(enc_hex_1.default).toUpperCase();
|
|
536
603
|
}
|
|
537
604
|
catch (err) {
|
|
538
605
|
const error = (0, error_1.ensureError)(err);
|
|
539
|
-
throw new error_2.ImageBaseCodeError("Error generating image seed", {
|
|
606
|
+
throw new error_2.ImageBaseCodeError("Error generating image seed", {
|
|
607
|
+
cause: error,
|
|
608
|
+
context: { p2pDid: p2pDid, code: code },
|
|
609
|
+
});
|
|
540
610
|
}
|
|
541
611
|
};
|
|
542
612
|
exports.getImageSeed = getImageSeed;
|
|
543
|
-
const getImageKey = function (
|
|
544
|
-
const
|
|
613
|
+
const getImageKey = function (serialNumber, p2pDid, code) {
|
|
614
|
+
const baseCode = (0, exports.getImageBaseCode)(serialNumber, p2pDid);
|
|
545
615
|
const seed = (0, exports.getImageSeed)(p2pDid, code);
|
|
546
|
-
const data = `01${
|
|
616
|
+
const data = `01${baseCode}${seed}`;
|
|
547
617
|
const hash = (0, sha256_1.default)(data);
|
|
548
618
|
const hashBytes = [...Buffer.from(hash.toString(enc_hex_1.default), "hex")];
|
|
549
619
|
const startByte = hashBytes[10];
|
|
@@ -553,10 +623,10 @@ const getImageKey = function (serialnumber, p2pDid, code) {
|
|
|
553
623
|
if (i < 31) {
|
|
554
624
|
fixed_byte = hashBytes[i + 1];
|
|
555
625
|
}
|
|
556
|
-
if (
|
|
626
|
+
if (i == 31 || (i & 1) != 0) {
|
|
557
627
|
hashBytes[10] = fixed_byte;
|
|
558
|
-
if (
|
|
559
|
-
if (byte < hashBytes[10] ||
|
|
628
|
+
if (126 < byte || 126 < hashBytes[10]) {
|
|
629
|
+
if (byte < hashBytes[10] || byte - hashBytes[10] == 0) {
|
|
560
630
|
hashBytes[i] = hashBytes[10] - byte;
|
|
561
631
|
}
|
|
562
632
|
else {
|
|
@@ -564,7 +634,7 @@ const getImageKey = function (serialnumber, p2pDid, code) {
|
|
|
564
634
|
}
|
|
565
635
|
}
|
|
566
636
|
}
|
|
567
|
-
else if (
|
|
637
|
+
else if (byte < 125 || fixed_byte < 125) {
|
|
568
638
|
hashBytes[i] = fixed_byte + byte;
|
|
569
639
|
}
|
|
570
640
|
}
|
|
@@ -575,17 +645,14 @@ const decodeImage = function (p2pDid, data) {
|
|
|
575
645
|
if (data.length >= 12) {
|
|
576
646
|
const header = data.subarray(0, 12).toString();
|
|
577
647
|
if (header === "eufysecurity") {
|
|
578
|
-
const
|
|
648
|
+
const serialNumber = data.subarray(13, 29).toString();
|
|
579
649
|
const code = data.subarray(30, 40).toString();
|
|
580
|
-
const imageKey = (0, exports.getImageKey)(
|
|
650
|
+
const imageKey = (0, exports.getImageKey)(serialNumber, p2pDid, code);
|
|
581
651
|
const otherData = data.subarray(41);
|
|
582
652
|
const encryptedData = otherData.subarray(0, 256);
|
|
583
653
|
const cipher = (0, crypto_1.createDecipheriv)("aes-128-ecb", Buffer.from(imageKey, "utf-8").subarray(0, 16), null);
|
|
584
654
|
cipher.setAutoPadding(false);
|
|
585
|
-
const decryptedData = Buffer.concat([
|
|
586
|
-
cipher.update(encryptedData),
|
|
587
|
-
cipher.final()
|
|
588
|
-
]);
|
|
655
|
+
const decryptedData = Buffer.concat([cipher.update(encryptedData), cipher.final()]);
|
|
589
656
|
decryptedData.copy(otherData);
|
|
590
657
|
return otherData;
|
|
591
658
|
}
|
|
@@ -594,47 +661,47 @@ const decodeImage = function (p2pDid, data) {
|
|
|
594
661
|
};
|
|
595
662
|
exports.decodeImage = decodeImage;
|
|
596
663
|
const getImagePath = function (path) {
|
|
597
|
-
const
|
|
598
|
-
if (
|
|
599
|
-
return
|
|
664
|
+
const splitPath = path.split("~");
|
|
665
|
+
if (splitPath.length === 2) {
|
|
666
|
+
return splitPath[1];
|
|
600
667
|
}
|
|
601
668
|
return path;
|
|
602
669
|
};
|
|
603
670
|
exports.getImagePath = getImagePath;
|
|
671
|
+
// TODO: make up some testing
|
|
604
672
|
const getImage = async function (api, serial, url) {
|
|
605
673
|
const { default: imageType } = await import("image-type");
|
|
606
674
|
const image = await api.getImage(serial, url);
|
|
607
675
|
const type = await imageType(image);
|
|
608
676
|
return {
|
|
609
677
|
data: image,
|
|
610
|
-
type: type !== null && type !== undefined ? type : { ext: "unknown", mime: "application/octet-stream" }
|
|
678
|
+
type: type !== null && type !== undefined ? type : { ext: "unknown", mime: "application/octet-stream" },
|
|
611
679
|
};
|
|
612
680
|
};
|
|
613
681
|
exports.getImage = getImage;
|
|
614
682
|
const isPrioritySourceType = function (current, update) {
|
|
615
|
-
|
|
616
|
-
(
|
|
617
|
-
|
|
618
|
-
}
|
|
619
|
-
return false;
|
|
683
|
+
return (((current === "http" || current === "p2p" || current === "push" || current === "mqtt" || current === undefined) &&
|
|
684
|
+
(update === "p2p" || update === "push" || update === "mqtt")) ||
|
|
685
|
+
((current === "http" || current === undefined) && update === "http"));
|
|
620
686
|
};
|
|
621
687
|
exports.isPrioritySourceType = isPrioritySourceType;
|
|
622
688
|
const decryptTrackerData = (data, key) => {
|
|
623
689
|
const decipher = (0, crypto_1.createDecipheriv)("aes-128-ecb", key, null);
|
|
624
690
|
decipher.setAutoPadding(false);
|
|
625
|
-
return Buffer.concat([
|
|
626
|
-
decipher.update(data),
|
|
627
|
-
decipher.final()
|
|
628
|
-
]);
|
|
691
|
+
return Buffer.concat([decipher.update(data), decipher.final()]);
|
|
629
692
|
};
|
|
630
693
|
exports.decryptTrackerData = decryptTrackerData;
|
|
694
|
+
// TODO: this seems to be used before above
|
|
631
695
|
const isT8170DetectionModeEnabled = function (value, type) {
|
|
632
696
|
return (type & value) == type;
|
|
633
697
|
};
|
|
634
698
|
exports.isT8170DetectionModeEnabled = isT8170DetectionModeEnabled;
|
|
699
|
+
// TODO this seems like getHB3DetectionMode
|
|
635
700
|
const getT8170DetectionMode = function (value, type, enable) {
|
|
636
701
|
let result = 0;
|
|
637
|
-
if (
|
|
702
|
+
if (Object.values(types_1.T8170DetectionTypes).includes(type) &&
|
|
703
|
+
Object.values(types_1.T8170DetectionTypes).includes(value) &&
|
|
704
|
+
!enable)
|
|
638
705
|
return value;
|
|
639
706
|
if (!enable) {
|
|
640
707
|
result = type ^ value;
|
|
@@ -645,13 +712,37 @@ const getT8170DetectionMode = function (value, type, enable) {
|
|
|
645
712
|
return result;
|
|
646
713
|
};
|
|
647
714
|
exports.getT8170DetectionMode = getT8170DetectionMode;
|
|
715
|
+
// TODO: Tidy up!!
|
|
716
|
+
const isT8110DetectionModeEnabled = function (value, type) {
|
|
717
|
+
return (type & value) == type;
|
|
718
|
+
};
|
|
719
|
+
exports.isT8110DetectionModeEnabled = isT8110DetectionModeEnabled;
|
|
720
|
+
const getT8110DetectionMode = function (value, type, enable) {
|
|
721
|
+
let result = 0;
|
|
722
|
+
if (Object.values(types_1.EufyCamC35DetectionTypes).includes(type) &&
|
|
723
|
+
Object.values(types_1.EufyCamC35DetectionTypes).includes(value) &&
|
|
724
|
+
!enable)
|
|
725
|
+
return value;
|
|
726
|
+
if (!enable) {
|
|
727
|
+
result = type ^ value;
|
|
728
|
+
}
|
|
729
|
+
else {
|
|
730
|
+
result = type | value;
|
|
731
|
+
}
|
|
732
|
+
return result;
|
|
733
|
+
};
|
|
734
|
+
exports.getT8110DetectionMode = getT8110DetectionMode;
|
|
735
|
+
// TODO: this is like isT8170DetectionModeEnabled
|
|
648
736
|
const isIndoorS350DetectionModeEnabled = function (value, type) {
|
|
649
737
|
return (type & value) == type;
|
|
650
738
|
};
|
|
651
739
|
exports.isIndoorS350DetectionModeEnabled = isIndoorS350DetectionModeEnabled;
|
|
740
|
+
// TODO: this is like getT8170DetectionMode
|
|
652
741
|
const getIndoorS350DetectionMode = function (value, type, enable) {
|
|
653
742
|
let result = 0;
|
|
654
|
-
if (
|
|
743
|
+
if (Object.values(types_1.IndoorS350DetectionTypes).includes(type) &&
|
|
744
|
+
Object.values(types_1.IndoorS350DetectionTypes).includes(value) &&
|
|
745
|
+
!enable)
|
|
655
746
|
return value;
|
|
656
747
|
if (!enable) {
|
|
657
748
|
result = type ^ value;
|
|
@@ -662,10 +753,12 @@ const getIndoorS350DetectionMode = function (value, type, enable) {
|
|
|
662
753
|
return result;
|
|
663
754
|
};
|
|
664
755
|
exports.getIndoorS350DetectionMode = getIndoorS350DetectionMode;
|
|
756
|
+
// TODO: this is like isT8170DetectionModeEnabled
|
|
665
757
|
const isIndoorNotitficationEnabled = function (value, type) {
|
|
666
758
|
return (type & value) == type;
|
|
667
759
|
};
|
|
668
760
|
exports.isIndoorNotitficationEnabled = isIndoorNotitficationEnabled;
|
|
761
|
+
// TODO: this is like getT8170DetectionMode
|
|
669
762
|
const getIndoorNotification = function (value, type, enable) {
|
|
670
763
|
let result = 0;
|
|
671
764
|
if (!enable) {
|
|
@@ -677,14 +770,16 @@ const getIndoorNotification = function (value, type, enable) {
|
|
|
677
770
|
return result;
|
|
678
771
|
};
|
|
679
772
|
exports.getIndoorNotification = getIndoorNotification;
|
|
773
|
+
// TODO: this is like isT8170DetectionModeEnabled
|
|
680
774
|
const isFloodlightT8425NotitficationEnabled = function (value, type) {
|
|
681
775
|
return (type & value) == type;
|
|
682
776
|
};
|
|
683
777
|
exports.isFloodlightT8425NotitficationEnabled = isFloodlightT8425NotitficationEnabled;
|
|
778
|
+
// TODO: this is like getT8170DetectionMode
|
|
684
779
|
const getFloodLightT8425Notification = function (value, type, enable) {
|
|
685
780
|
let result = 0;
|
|
686
781
|
if (!enable) {
|
|
687
|
-
result =
|
|
782
|
+
result = type ^ value;
|
|
688
783
|
}
|
|
689
784
|
else {
|
|
690
785
|
result = type | value;
|
|
@@ -718,6 +813,7 @@ const getLockEventType = function (event) {
|
|
|
718
813
|
return 0;
|
|
719
814
|
};
|
|
720
815
|
exports.getLockEventType = getLockEventType;
|
|
816
|
+
// TODO: this is like getT8170DetectionMode
|
|
721
817
|
const switchSmartLockNotification = function (currentValue, mode, enable) {
|
|
722
818
|
let result = 0;
|
|
723
819
|
if (enable) {
|
|
@@ -729,6 +825,7 @@ const switchSmartLockNotification = function (currentValue, mode, enable) {
|
|
|
729
825
|
return result;
|
|
730
826
|
};
|
|
731
827
|
exports.switchSmartLockNotification = switchSmartLockNotification;
|
|
828
|
+
// TODO: this is like isT8170DetectionModeEnabled
|
|
732
829
|
const isSmartLockNotification = function (value, mode) {
|
|
733
830
|
return (value & mode) !== 0;
|
|
734
831
|
};
|
|
@@ -761,7 +858,8 @@ const loadEventImage = function (station, api, device, message, p2pTimeouts) {
|
|
|
761
858
|
}
|
|
762
859
|
else {
|
|
763
860
|
if (!(0, utils_1.isEmpty)(message.pic_url)) {
|
|
764
|
-
(0, exports.getImage)(api, device.getSerial(), message.pic_url)
|
|
861
|
+
(0, exports.getImage)(api, device.getSerial(), message.pic_url)
|
|
862
|
+
.then((image) => {
|
|
765
863
|
if (image.data.length > 0) {
|
|
766
864
|
if (p2pTimeouts.get(device.getSerial()) !== undefined) {
|
|
767
865
|
clearTimeout(p2pTimeouts.get(device.getSerial()));
|
|
@@ -773,9 +871,15 @@ const loadEventImage = function (station, api, device, message, p2pTimeouts) {
|
|
|
773
871
|
//fallback
|
|
774
872
|
(0, exports.loadImageOverP2P)(station, device, device.getSerial(), p2pTimeouts);
|
|
775
873
|
}
|
|
776
|
-
})
|
|
874
|
+
})
|
|
875
|
+
.catch((err) => {
|
|
777
876
|
const error = (0, error_1.ensureError)(err);
|
|
778
|
-
logging_1.rootHTTPLogger.debug(`Device load event image - Fallback Error`, {
|
|
877
|
+
logging_1.rootHTTPLogger.debug(`Device load event image - Fallback Error`, {
|
|
878
|
+
error: (0, utils_1.getError)(error),
|
|
879
|
+
stationSN: station.getSerial(),
|
|
880
|
+
deviceSN: device.getSerial(),
|
|
881
|
+
message: JSON.stringify(message),
|
|
882
|
+
});
|
|
779
883
|
(0, exports.loadImageOverP2P)(station, device, device.getSerial(), p2pTimeouts);
|
|
780
884
|
});
|
|
781
885
|
}
|
|
@@ -786,4 +890,27 @@ const loadEventImage = function (station, api, device, message, p2pTimeouts) {
|
|
|
786
890
|
}
|
|
787
891
|
};
|
|
788
892
|
exports.loadEventImage = loadEventImage;
|
|
893
|
+
const getRandomPhoneModel = function () {
|
|
894
|
+
/**
|
|
895
|
+
* Generate a random phone model based on a structure
|
|
896
|
+
*/
|
|
897
|
+
const brandKeys = Object.keys(const_1.PhoneModelStructure);
|
|
898
|
+
const randomBrandName = brandKeys[Math.floor(Math.random() * brandKeys.length)];
|
|
899
|
+
const pick = (arr) => arr[Math.floor(Math.random() * arr.length)];
|
|
900
|
+
let part1 = "";
|
|
901
|
+
let part2 = "";
|
|
902
|
+
const dataBrand = const_1.PhoneModelStructure[randomBrandName];
|
|
903
|
+
if (dataBrand.first && dataBrand.second) {
|
|
904
|
+
part1 = pick(dataBrand.first);
|
|
905
|
+
part2 = pick(dataBrand.second);
|
|
906
|
+
}
|
|
907
|
+
if (dataBrand.numbers && dataBrand.letters) {
|
|
908
|
+
const minNum = Math.pow(10, dataBrand.numbers - 1);
|
|
909
|
+
const maxNum = Math.pow(10, dataBrand.numbers) - 1;
|
|
910
|
+
part1 = String(Math.floor(Math.random() * (maxNum - minNum + 1)) + minNum);
|
|
911
|
+
part2 = pick(dataBrand.letters);
|
|
912
|
+
}
|
|
913
|
+
return `${randomBrandName}${part1}${part2}`.trim();
|
|
914
|
+
};
|
|
915
|
+
exports.getRandomPhoneModel = getRandomPhoneModel;
|
|
789
916
|
//# sourceMappingURL=utils.js.map
|