Skip to content

Commit b1ae1b9

Browse files
committed
Bug fixes and enhancements
### UPDATED - Universal `.gitignore` file. - Limit sensor zones to support only from Zone 1 through 99 due to unwanted rogue devices appearing as sensors. - Naming convention for documented items (now sorted into collections, devices, and items for clarity). - Rewritten debug parser detector to better detect parser anomalies. - `generateHash` function now only accepts objects and array of objects to remove data that does not necessarily need to be hashed (e.g. "Last Update" or `rawHtml`). - Logs will not include `rawHtml` anymore since it fills up the screen full of information that is best sent to the developer automatically. - Changed wording for debug logs regarding stale login sessions. ### FIXED - Missing "Tampered" status documentation in sensor statuses. ### ADDED - GitHub workflows. - Keep alive requests will now check for error codes so logs don't get unnecessarily spammed. - Privacy notice in `README.md` that if the plugin detects anomalies, information sent to the plugin author will include unfiltered raw HTML. ### REMOVED - `FunctionName` type. - User reminders for when the detector function sends information out since `rawHtml` is not included in logs anymore due to it taking up too much space.
1 parent df74f46 commit b1ae1b9

File tree

14 files changed

+956
-700
lines changed

14 files changed

+956
-700
lines changed

.github/workflows/lock-threads.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: 'Lock Threads'
22

33
on:
44
schedule:
5-
- cron: '0 * * * *'
5+
- cron: '0 0 * * *'
66

77
permissions:
88
issues: write

.gitignore

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,11 +61,26 @@ package-lock.json
6161
#################
6262
.next/
6363

64+
#####################
65+
#### AWS Amplify ####
66+
#####################
67+
amplify/.config/local-*
68+
amplify/backend/.temp
69+
amplify/backend/amplify-meta.json
70+
amplify/\#current-cloud-backend
71+
amplify/hooks/*.sample
72+
amplify/logs
73+
amplify/mock-api-resources
74+
amplify/mock-data
75+
src/amplifyconfiguration.json
76+
src/aws-exports.js
77+
6478
##################
6579
#### Firebase ####
6680
##################
67-
**/.firebase
68-
**/.firebaserc
81+
.firebase
82+
.firebaserc
83+
firebase-debug.log
6984

7085
###################
7186
#### JetBrains ####

README.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,9 @@ All sensors are now organized within an array of objects, with each object conta
145145
- For example, if the type is "Door/Window Sensor", the value should be `doorWindow`. Read the [Supported Devices](#supported-devices) section for more information.
146146
- __ADT Zone__ (`adtZone`)
147147
- Must match the zone shown under the "Zone" column in the "System" tab when logged into the portal.
148+
- For compatibility reasons, only devices with zones 1 through 99 are supported.
149+
150+
If you do not wish to add sensors, simply assign an empty array (e.g. `[]`). However, it is advisable to include all supported sensors, as having none does not optimize plugin performance.
148151

149152
If you do not find the supported type listed, please note that the plugin will notify me. Do not create a separate issue on GitHub. I am actively working on adding support as soon as I gather sufficient information to determine the statuses displayed on the portal.
150153

@@ -257,7 +260,9 @@ Here is an example of the information I see when the plugin detects unknown stat
257260
}
258261
}
259262
```
260-
__Notice:__ If you prefer to prevent this functionality, you can block the URL that the plugin utilizes to notify me. However, it is essential to note that I will not be able to offer assistance or support if you choose to impede the plugin from fulfilling its purpose to the best of its capabilities.
263+
__Note:__ If you prefer to prevent this functionality, you can block the URL that the plugin utilizes to notify me. However, it is essential to note that I will not be able to offer assistance or support if you choose to impede the plugin from fulfilling its purpose to the best of its capabilities.
264+
265+
__Note 2:__ In certain scenarios, the plugin may identify anomalies while parsing portal data. Such reports may contain raw HTML data (redacted in the logs). To ensure prompt updates, the raw HTML sent to me will remain unfiltered.
261266

262267
## Credits and Appreciation
263268
If you find value in the ongoing development of this plugin and wish to express your appreciation, you have the option to become my supporter on [GitHub Sponsors](https://github.com/sponsors/mrjackyliang)!

config.schema.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@
233233
"description": "Specify the <strong class=\"font-weight-bold\">exact zone</strong> associated with the sensor you want to add. Double-check the zone to ensure the correct sensor is added.",
234234
"placeholder": "e.g. 99",
235235
"minimum": 1,
236-
"maximum": 999
236+
"maximum": 99
237237
}
238238
}
239239
},

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "homebridge-adt-pulse",
33
"displayName": "Homebridge ADT Pulse",
4-
"version": "3.1.2",
4+
"version": "3.1.3",
55
"description": "Homebridge security system platform for ADT Pulse",
66
"main": "./build/index.js",
77
"exports": "./build/index.js",

src/lib/accessory.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import chalk from 'chalk';
22

3-
import { condensedSensorTypeItems } from '@/lib/items.js';
3+
import { itemCondensedSensorTypes } from '@/lib/items.js';
44
import {
55
condensePanelStates,
66
convertPanelCharacteristicValue,
@@ -405,7 +405,7 @@ export class ADTPulseAccessory {
405405
|| type === 'gateway'
406406
|| type === 'panel'
407407
|| type === 'panelSwitch'
408-
|| !condensedSensorTypeItems.includes(type)
408+
|| !itemCondensedSensorTypes.includes(type)
409409
) {
410410
hapStatus = new this.#api.hap.HapStatusError(this.#api.hap.HAPStatus.RESOURCE_DOES_NOT_EXIST);
411411

src/lib/api.ts

Lines changed: 49 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ import {
4242
generateDynatracePCHeaderValue,
4343
generateFakeReadyButtons,
4444
generateHash,
45-
isEmptyOrbTextSummary,
4645
isPortalSyncCode,
4746
parseArmDisarmMessage,
4847
parseDoSubmitHandlers,
@@ -866,25 +865,12 @@ export class ADTPulse {
866865
*/
867866
await this.newInformationDispatcher('gateway-information', gatewayInformation);
868867

869-
// TODO Need a more permanent way and safer way to determine gateway model.
870-
// If the parsing function may be parsing data incorrectly.
871-
if (
872-
Object.keys(fetchedTableCells).length !== 10 // Lynx/QuickConnect Cellular-Only Gateway / Cellular Mode.
873-
&& Object.keys(fetchedTableCells).length !== 11 // Compact SMA Protocol Gateway / Cellular Mode.
874-
&& Object.keys(fetchedTableCells).length !== 17 // ADT Pulse Gateway / Broadband Mode / No Router WAN IP Address.
875-
&& Object.keys(fetchedTableCells).length !== 18 // ADT Pulse Gateway / Broadband Mode.
876-
) {
877-
if (this.#internal.debug) {
878-
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getGatewayInformation()', 'warn', 'The fetchTableCells() function may be parsing the gateway information incorrectly');
879-
}
880-
881-
await this.newInformationDispatcher('debug-parser', {
882-
parserName: 'fetchTableCells()',
883-
parserReason: 'length does not match 10, 11, 17, and 18',
884-
parserResponse: fetchedTableCells,
885-
rawData: sessions.axiosSystemGateway.data,
886-
});
887-
}
868+
// Check if the parsing function is parsing data incorrectly.
869+
await this.newInformationDispatcher('debug-parser', {
870+
method: 'getGatewayInformation',
871+
response: fetchedTableCells,
872+
rawHtml: sessions.axiosSystemGateway.data,
873+
});
888874

889875
if (this.#internal.debug) {
890876
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getGatewayInformation()', 'success', `Successfully retrieved gateway information from "${this.#internal.baseUrl}"`);
@@ -941,9 +927,6 @@ export class ADTPulse {
941927
}),
942928
);
943929

944-
// TODO Check for 500 Internal Server Error (add it to every API method).
945-
// TODO sessions.axiosSystemDeviceId1.status
946-
947930
// If the "ClientRequest" object does not exist in the Axios response.
948931
if (typeof sessions.axiosSystemDeviceId1?.request === 'undefined') {
949932
if (this.#internal.debug) {
@@ -1087,24 +1070,12 @@ export class ADTPulse {
10871070
*/
10881071
await this.newInformationDispatcher('panel-information', panelInformation);
10891072

1090-
// TODO Need a more permanent way and safer way to determine panel status.
1091-
// If the parsing function may be parsing data incorrectly.
1092-
if (
1093-
Object.keys(fetchedTableCells).length !== 3 // PowerSeries/PremisePro.
1094-
&& Object.keys(fetchedTableCells).length !== 4 // Impassa SCW9057.
1095-
&& Object.keys(fetchedTableCells).length !== 5 // Safewatch Pro 3000/3000CN.
1096-
) {
1097-
if (this.#internal.debug) {
1098-
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getPanelInformation()', 'warn', 'The fetchTableCells() function may be parsing the panel information incorrectly');
1099-
}
1100-
1101-
await this.newInformationDispatcher('debug-parser', {
1102-
parserName: 'fetchTableCells()',
1103-
parserReason: 'length does not match 3, 4, and 5',
1104-
parserResponse: fetchedTableCells,
1105-
rawData: sessions.axiosSystemDeviceId1.data,
1106-
});
1107-
}
1073+
// Check if the parsing function is parsing data incorrectly.
1074+
await this.newInformationDispatcher('debug-parser', {
1075+
method: 'getPanelInformation',
1076+
response: fetchedTableCells,
1077+
rawHtml: sessions.axiosSystemDeviceId1.data,
1078+
});
11081079

11091080
if (this.#internal.debug) {
11101081
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getPanelInformation()', 'success', `Successfully retrieved panel information from "${this.#internal.baseUrl}"`);
@@ -1321,19 +1292,12 @@ export class ADTPulse {
13211292
*/
13221293
await this.newInformationDispatcher('panel-status', parsedOrbTextSummary);
13231294

1324-
// If the parsing function may be parsing data incorrectly.
1325-
if (isEmptyOrbTextSummary(parsedOrbTextSummary)) {
1326-
if (this.#internal.debug) {
1327-
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getPanelStatus()', 'warn', 'The parseOrbTextSummary() function may be parsing sensors information incorrectly');
1328-
}
1329-
1330-
await this.newInformationDispatcher('debug-parser', {
1331-
parserName: 'parseOrbTextSummary()',
1332-
parserReason: 'empty response',
1333-
parserResponse: parsedOrbTextSummary,
1334-
rawData: sessions.axiosSummary.data,
1335-
});
1336-
}
1295+
// Check if the parsing function is parsing data incorrectly.
1296+
await this.newInformationDispatcher('debug-parser', {
1297+
method: 'getPanelStatus',
1298+
response: parsedOrbTextSummary,
1299+
rawHtml: sessions.axiosSummary.data,
1300+
});
13371301

13381302
if (this.#internal.debug) {
13391303
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getPanelStatus()', 'success', `Successfully retrieved panel status from "${this.#internal.baseUrl}"`);
@@ -1651,19 +1615,12 @@ export class ADTPulse {
16511615
*/
16521616
await this.newInformationDispatcher('orb-security-buttons', parsedOrbSecurityButtons);
16531617

1654-
// If the parsing function may be parsing data incorrectly.
1655-
if (parsedOrbSecurityButtons.length < 1 || parsedOrbSecurityButtons.length > 3) {
1656-
if (this.#internal.debug) {
1657-
debugLog(this.#internal.logger, 'api.ts / ADTPulse.setPanelStatus()', 'warn', 'The parseOrbSecurityButtons() function may be parsing the orb security buttons incorrectly');
1658-
}
1659-
1660-
await this.newInformationDispatcher('debug-parser', {
1661-
parserName: 'parseOrbSecurityButtons()',
1662-
parserReason: 'length is not between 1 to 3',
1663-
parserResponse: parsedOrbSecurityButtons,
1664-
rawData: sessions.axiosSummary.data,
1665-
});
1666-
}
1618+
// Check if the parsing function is parsing data incorrectly.
1619+
await this.newInformationDispatcher('debug-parser', {
1620+
method: 'setPanelStatus',
1621+
response: parsedOrbSecurityButtons,
1622+
rawHtml: sessions.axiosSummary.data,
1623+
});
16671624

16681625
// Only keep all ready (enabled) orb security buttons.
16691626
let readyButtons = parsedOrbSecurityButtons.filter((parsedOrbSecurityButton): parsedOrbSecurityButton is ADTPulseSetPanelStatusReadyButton => !parsedOrbSecurityButton.buttonDisabled);
@@ -2008,19 +1965,12 @@ export class ADTPulse {
20081965
*/
20091966
await this.newInformationDispatcher('sensors-information', parsedSensorsTable);
20101967

2011-
// If the parsing function may be parsing data incorrectly.
2012-
if (parsedSensorsTable.length < 1) {
2013-
if (this.#internal.debug) {
2014-
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getSensorsInformation()', 'warn', 'The parseSensorsTable() function may be parsing the sensors table incorrectly');
2015-
}
2016-
2017-
await this.newInformationDispatcher('debug-parser', {
2018-
parserName: 'parseSensorsTable()',
2019-
parserReason: 'length is not 1 or more',
2020-
parserResponse: parsedSensorsTable,
2021-
rawData: sessions.axiosSystem.data,
2022-
});
2023-
}
1968+
// Check if the parsing function is parsing data incorrectly.
1969+
await this.newInformationDispatcher('debug-parser', {
1970+
method: 'getSensorsInformation',
1971+
response: parsedSensorsTable,
1972+
rawHtml: sessions.axiosSystem.data,
1973+
});
20241974

20251975
if (this.#internal.debug) {
20261976
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getSensorsInformation()', 'success', `Successfully retrieved sensors information from "${this.#internal.baseUrl}"`);
@@ -2260,19 +2210,12 @@ export class ADTPulse {
22602210
*/
22612211
await this.newInformationDispatcher('sensors-status', parsedOrbSensors);
22622212

2263-
// If the parsing function may be parsing data incorrectly.
2264-
if (parsedOrbSensors.length < 1) {
2265-
if (this.#internal.debug) {
2266-
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getSensorsStatus()', 'warn', 'The parseOrbSensors() function may be parsing the orb sensors incorrectly');
2267-
}
2268-
2269-
await this.newInformationDispatcher('debug-parser', {
2270-
parserName: 'parseOrbSensors()',
2271-
parserReason: 'length is not 1 or more',
2272-
parserResponse: parsedOrbSensors,
2273-
rawData: sessions.axiosSummary.data,
2274-
});
2275-
}
2213+
// Check if the parsing function is parsing data incorrectly.
2214+
await this.newInformationDispatcher('debug-parser', {
2215+
method: 'getSensorsStatus',
2216+
response: parsedOrbSensors,
2217+
rawHtml: sessions.axiosSummary.data,
2218+
});
22762219

22772220
if (this.#internal.debug) {
22782221
debugLog(this.#internal.logger, 'api.ts / ADTPulse.getSensorsStatus()', 'success', `Successfully retrieved sensors status from "${this.#internal.baseUrl}"`);
@@ -2987,19 +2930,12 @@ export class ADTPulse {
29872930
*/
29882931
await this.newInformationDispatcher('orb-security-buttons', parsedOrbSecurityButtons);
29892932

2990-
// If the parsing function may be parsing data incorrectly.
2991-
if (parsedOrbSecurityButtons.length < 1 || parsedOrbSecurityButtons.length > 3) {
2992-
if (this.#internal.debug) {
2993-
debugLog(this.#internal.logger, 'api.ts / ADTPulse.armDisarmHandler()', 'warn', 'The parseOrbSecurityButtons() function may be parsing the orb security buttons incorrectly');
2994-
}
2995-
2996-
await this.newInformationDispatcher('debug-parser', {
2997-
parserName: 'parseOrbSecurityButtons()',
2998-
parserReason: 'length is not between 1 to 3',
2999-
parserResponse: parsedOrbSecurityButtons,
3000-
rawData: sessions.axiosSummary.data,
3001-
});
3002-
}
2933+
// Check if the parsing function is parsing data incorrectly.
2934+
await this.newInformationDispatcher('debug-parser', {
2935+
method: 'armDisarmHandler',
2936+
response: parsedOrbSecurityButtons,
2937+
rawHtml: sessions.axiosSummary.data,
2938+
});
30032939

30042940
let readyButtons = parsedOrbSecurityButtons.filter((parsedOrbSecurityButton): parsedOrbSecurityButton is ADTPulseArmDisarmHandlerReadyButton => !parsedOrbSecurityButton.buttonDisabled);
30052941

@@ -3163,22 +3099,12 @@ export class ADTPulse {
31633099
*/
31643100
await this.newInformationDispatcher('do-submit-handlers', parsedDoSubmitHandlers);
31653101

3166-
// If the parsing function may be parsing data incorrectly.
3167-
if (
3168-
parsedDoSubmitHandlers.length !== 0 // No force arming required.
3169-
&& parsedDoSubmitHandlers.length !== 2 // Force arming required.
3170-
) {
3171-
if (this.#internal.debug) {
3172-
debugLog(this.#internal.logger, 'api.ts / ADTPulse.armDisarmHandler()', 'warn', 'The parseDoSubmitHandlers() function may be parsing the do submit handlers incorrectly');
3173-
}
3174-
3175-
await this.newInformationDispatcher('debug-parser', {
3176-
parserName: 'parseDoSubmitHandlers()',
3177-
parserReason: 'length does not match 0 and 2',
3178-
parserResponse: parsedDoSubmitHandlers,
3179-
rawData: response.data,
3180-
});
3181-
}
3102+
// Check if the parsing function is parsing data incorrectly.
3103+
await this.newInformationDispatcher('debug-parser', {
3104+
method: 'forceArmHandler',
3105+
response: parsedDoSubmitHandlers,
3106+
rawHtml: response.data,
3107+
});
31823108

31833109
// Check if there are no force arm buttons available.
31843110
if (
@@ -3436,7 +3362,7 @@ export class ADTPulse {
34363362
* @since 1.0.0
34373363
*/
34383364
private async newInformationDispatcher(type: ADTPulseNewInformationDispatcherType, data: ADTPulseNewInformationDispatcherData<ADTPulseNewInformationDispatcherType>): ADTPulseNewInformationDispatcherReturns {
3439-
const dataHash = generateHash(`${type}: ${JSON.stringify(data)}`);
3365+
const dataHash = generateHash(data);
34403366

34413367
// If the detector has not reported this event before.
34423368
if (this.#internal.reportedHashes.find((reportedHash) => dataHash === reportedHash) === undefined) {

0 commit comments

Comments
 (0)