Skip to content

Commit

Permalink
Better bug detection for mis-matched sensors
Browse files Browse the repository at this point in the history
### UPDATED
- Sensor information and status count mismatch will now include the `rawHtml` information for both pages to better debug certain situations.
- Path for force arm handlers changed from `.p_armDisarmWrapper input` to `.p_whiteBoxMiddleCenter .p_armDisarmWrapper input`.
- Better detect for anomalies between `forceArmHandler`.

### REMOVED
- Temporary detector to find sensor mis-match bug from `devStatTamper` sensors.
  • Loading branch information
mrjackyliang committed Mar 29, 2024
1 parent b0366c4 commit a74a9b8
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 48 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "homebridge-adt-pulse",
"displayName": "Homebridge ADT Pulse",
"version": "3.2.13",
"version": "3.2.14",
"description": "Homebridge security system platform for ADT Pulse",
"main": "./build/index.js",
"exports": "./build/index.js",
Expand Down
26 changes: 3 additions & 23 deletions src/lib/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1825,28 +1825,6 @@ export class ADTPulse {
};
}

// TODO Temporary detector to find sensor mis-match bug from "devStatTamper" sensors.
if (
sessions.axiosSystem.data.includes('devStatTamper')
|| sessions.axiosSystem.data.includes('Panic (14)')
|| sessions.axiosSystem.data.includes('Shed Door')
|| sessions.axiosSystem.data.includes('Patio Door')
) {
await this.newInformationDispatcher('debug-parser', {
method: 'getSensorsInformation',
response: [
{
deviceId: 0,
deviceType: 'Door Sensor',
name: 'Temporary detector to find sensor mis-match bug from devStatTamper sensors',
status: 'Status Unknown',
zone: 0,
},
],
rawHtml: sessions.axiosSystem.data,
});
}

// sessions.jsdomSystem: Parse the system page.
sessions.jsdomSystem = new JSDOM(
sessions.axiosSystem.data,
Expand Down Expand Up @@ -1936,6 +1914,7 @@ export class ADTPulse {
action: 'GET_SENSORS_INFORMATION',
success: true,
info: {
rawHtml: sessions.axiosSystem.data,
sensors: parsedSensorsTable,
},
};
Expand Down Expand Up @@ -2196,6 +2175,7 @@ export class ADTPulse {
action: 'GET_SENSORS_STATUS',
success: true,
info: {
rawHtml: sessions.axiosSummary.data,
sensors: parsedOrbSensors,
},
};
Expand Down Expand Up @@ -3162,7 +3142,7 @@ export class ADTPulse {
*
* @since 1.0.0
*/
const jsdomArmDisarmDoSubmitHandlers = sessions.jsdomArmDisarm.window.document.querySelectorAll('.p_armDisarmWrapper input');
const jsdomArmDisarmDoSubmitHandlers = sessions.jsdomArmDisarm.window.document.querySelectorAll('.p_whiteBoxMiddleCenter .p_armDisarmWrapper input');
const jsdomArmDisarmArmDisarmMessage = sessions.jsdomArmDisarm.window.document.querySelector('.p_armDisarmWrapper div:first-child');
const parsedArmDisarmMessage = parseArmDisarmMessage(jsdomArmDisarmArmDisarmMessage);
const parsedDoSubmitHandlers = parseDoSubmitHandlers(jsdomArmDisarmDoSubmitHandlers);
Expand Down
4 changes: 2 additions & 2 deletions src/lib/detect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ import type {
* @since 1.0.0
*/
export async function detectApiDebugParser(data: DetectApiDebugParserData, logger: DetectApiDebugParserLogger, debugMode: DetectApiDebugParserDebugMode): DetectApiDebugParserReturns {
const forceArmHandlerAnomaly = data.method === 'forceArmHandler' && (isUnknownDoSubmitHandlerCollection(data.response) || !data.rawHtml.includes('class="p_armDisarmWrapper"'));
const forceArmHandlerAnomaly = data.method === 'forceArmHandler' && isUnknownDoSubmitHandlerCollection(data.response) && !data.rawHtml.includes('p_whiteBoxMiddleCenter') && !data.rawHtml.includes('p_armDisarmWrapper');
const getGatewayInformationAnomaly = data.method === 'getGatewayInformation' && isUnknownGatewayDevice(data.response);
const getOrbSecurityButtonsAnomaly = data.method === 'getOrbSecurityButtons' && isUnknownOrbSecurityButtonCollection(data.response) && !data.rawHtml.includes('Status Unavailable.');
const getPanelInformationAnomaly = data.method === 'getPanelInformation' && isUnknownPanelDevice(data.response);
Expand Down Expand Up @@ -901,7 +901,7 @@ export async function detectApiSensorsStatus(sensors: DetectApiSensorsStatusSens
* @since 1.0.0
*/
export async function detectPlatformSensorCountMismatch(data: DetectPlatformSensorCountMismatchData, logger: DetectPlatformSensorCountMismatchLogger, debugMode: DetectPlatformSensorCountMismatchDebugMode): DetectPlatformSensorCountMismatchReturns {
const detectedCountMismatch = data.sensorsInfo.length !== data.sensorsStatus.length;
const detectedCountMismatch = data.data.sensorsInfo.length !== data.data.sensorsStatus.length;

if (detectedCountMismatch) {
const cleanedData = removePersonalIdentifiableInformation(data);
Expand Down
4 changes: 0 additions & 4 deletions src/lib/items.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,6 @@ export const collectionDoSubmitHandlers: CollectionDoSubmitHandlers = [
},
],
},
{
description: 'No force arm required',
handlers: [],
},
];

/**
Expand Down
41 changes: 29 additions & 12 deletions src/lib/platform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,10 @@ export class ADTPulsePlatform implements ADTPulsePlatformPlugin {
adtLastLogin: 0, // January 1, 1970, at 00:00:00 UTC.
adtSyncCheck: 0, // January 1, 1970, at 00:00:00 UTC.
},
rawHtml: {
sensorsInfo: '',
sensorsStatus: '',
},
reportedHashes: [],
};

Expand Down Expand Up @@ -871,18 +875,24 @@ export class ADTPulsePlatform implements ADTPulsePlatformPlugin {

// Update sensors information.
if (requests[3].success) {
const { sensors } = requests[3].info;
const { rawHtml, sensors } = requests[3].info;

// Set sensors information into memory.
this.#state.data.sensorsInfo = sensors;

// Set raw html of sensors information into memory.
this.#state.rawHtml.sensorsInfo = rawHtml;
}

// Update sensors status.
if (requests[4].success) {
const { sensors } = requests[4].info;
const { rawHtml, sensors } = requests[4].info;

// Set sensors status into memory.
this.#state.data.sensorsStatus = sensors;

// Set raw html of sensors status into memory.
this.#state.rawHtml.sensorsStatus = rawHtml;
}

// Cache orb security buttons.
Expand Down Expand Up @@ -1017,16 +1027,23 @@ export class ADTPulsePlatform implements ADTPulsePlatformPlugin {
* @since 1.0.0
*/
private async unknownInformationDispatcher(): ADTPulsePlatformUnknownInformationDispatcherReturns {
const { sensorsInfo, sensorsStatus } = this.#state.data;
const { sensorsInfo: dataSensorsInfo, sensorsStatus: dataSensorsStatus } = this.#state.data;
const { sensorsInfo: rawHtmlSensorsInfo, sensorsStatus: rawHtmlSensorsStatus } = this.#state.rawHtml;

if (
sensorsInfo.length !== sensorsStatus.length // Check if there was a mismatch between the "sensorsInfo" and "sensorsStatus" array.
&& !(sensorsInfo.length === 0 && sensorsStatus.length > 0) // Sometimes devices are slow to fetch sensors information.
&& !(sensorsInfo.length > 0 && sensorsStatus.length === 0) // Sometimes devices are slow to fetch sensors status.
dataSensorsInfo.length !== dataSensorsStatus.length // Check if there was a mismatch between the "sensorsInfo" and "sensorsStatus" array.
&& !(dataSensorsInfo.length === 0 && dataSensorsStatus.length > 0) // Sometimes devices are slow to fetch sensors information.
&& !(dataSensorsInfo.length > 0 && dataSensorsStatus.length === 0) // Sometimes devices are slow to fetch sensors status.
) {
const data = {
sensorsInfo,
sensorsStatus,
data: {
sensorsInfo: dataSensorsInfo,
sensorsStatus: dataSensorsStatus,
},
rawHtml: {
sensorsInfo: rawHtmlSensorsInfo,
sensorsStatus: rawHtmlSensorsStatus,
},
};
const dataHash = generateHash(data);

Expand All @@ -1045,10 +1062,10 @@ export class ADTPulsePlatform implements ADTPulsePlatformPlugin {
}

// Generate an array of matching "sensorInfo" and "sensorStatus" with the device type.
const sensors = sensorsInfo.map((sensorInfo, sensorsInfoKey) => ({
info: sensorInfo,
status: sensorsStatus[sensorsInfoKey],
type: condenseSensorType(sensorInfo.deviceType),
const sensors = dataSensorsInfo.map((dataSensorInfo, dataSensorsInfoKey) => ({
info: dataSensorInfo,
status: dataSensorsStatus[dataSensorsInfoKey],
type: condenseSensorType(dataSensorInfo.deviceType),
}));
const matchedSensors = sensors.filter((sensor): sensor is NonNullable<typeof sensors[number]> => sensor !== null);
const dataHash = generateHash(sensors);
Expand Down
42 changes: 36 additions & 6 deletions src/types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -257,11 +257,14 @@ export type ADTPulseGetOrbSecurityButtonsSessions = Sessions<{
*
* @since 1.0.0
*/
export type ADTPulseGetSensorsInformationReturnsInfoRawHtml = string;

export type ADTPulseGetSensorsInformationReturnsInfoSensor = SensorInformation;

export type ADTPulseGetSensorsInformationReturnsInfoSensors = ADTPulseGetSensorsInformationReturnsInfoSensor[];

export type ADTPulseGetSensorsInformationReturnsInfo = {
rawHtml: ADTPulseGetSensorsInformationReturnsInfoRawHtml;
sensors: ADTPulseGetSensorsInformationReturnsInfoSensors;
};

Expand All @@ -277,11 +280,14 @@ export type ADTPulseGetSensorsInformationSessions = Sessions<{
*
* @since 1.0.0
*/
export type ADTPulseGetSensorsStatusReturnsInfoRawHtml = string;

export type ADTPulseGetSensorsStatusReturnsInfoSensor = SensorStatus;

export type ADTPulseGetSensorsStatusReturnsInfoSensors = ADTPulseGetSensorsStatusReturnsInfoSensor[];

export type ADTPulseGetSensorsStatusReturnsInfo = {
rawHtml: ADTPulseGetSensorsStatusReturnsInfoRawHtml;
sensors: ADTPulseGetSensorsStatusReturnsInfoSensors;
};

Expand Down Expand Up @@ -896,6 +902,15 @@ export type ADTPulsePlatformStateLastRunOn = {
adtSyncCheck: ADTPulsePlatformStateLastRunOnAdtSyncCheck;
};

export type ADTPulsePlatformStateRawHtmlSensorsInfo = string;

export type ADTPulsePlatformStateRawHtmlSensorsStatus = string;

export type ADTPulsePlatformStateRawHtml = {
sensorsInfo: ADTPulsePlatformStateRawHtmlSensorsInfo;
sensorsStatus: ADTPulsePlatformStateRawHtmlSensorsStatus;
};

export type ADTPulsePlatformStateReportedHash = string;

export type ADTPulsePlatformStateReportedHashes = ADTPulsePlatformStateReportedHash[];
Expand All @@ -906,6 +921,7 @@ export type ADTPulsePlatformState = {
eventCounters: ADTPulsePlatformStateEventCounters;
intervals: ADTPulsePlatformStateIntervals;
lastRunOn: ADTPulsePlatformStateLastRunOn;
rawHtml: ADTPulsePlatformStateRawHtml;
reportedHashes: ADTPulsePlatformStateReportedHashes;
};

Expand Down Expand Up @@ -1362,17 +1378,31 @@ export type DetectApiSensorsStatusReturns = Promise<boolean>;
*
* @since 1.0.0
*/
export type DetectPlatformSensorCountMismatchDataSensorInfo = SensorInformation;
export type DetectPlatformSensorCountMismatchDataDataSensorInfo = SensorInformation;

export type DetectPlatformSensorCountMismatchDataSensorsInfo = DetectPlatformSensorCountMismatchDataSensorInfo[];
export type DetectPlatformSensorCountMismatchDataDataSensorsInfo = DetectPlatformSensorCountMismatchDataDataSensorInfo[];

export type DetectPlatformSensorCountMismatchDataSensorStatus = SensorStatus;
export type DetectPlatformSensorCountMismatchDataDataSensorStatus = SensorStatus;

export type DetectPlatformSensorCountMismatchDataSensorsStatus = DetectPlatformSensorCountMismatchDataSensorStatus[];
export type DetectPlatformSensorCountMismatchDataDataSensorsStatus = DetectPlatformSensorCountMismatchDataDataSensorStatus[];

export type DetectPlatformSensorCountMismatchDataData = {
sensorsInfo: DetectPlatformSensorCountMismatchDataDataSensorsInfo;
sensorsStatus: DetectPlatformSensorCountMismatchDataDataSensorsStatus;
};

export type DetectPlatformSensorCountMismatchDataRawHtmlSensorsInfo = string;

export type DetectPlatformSensorCountMismatchDataRawHtmlSensorsStatus = string;

export type DetectPlatformSensorCountMismatchDataRawHtml = {
sensorsInfo: DetectPlatformSensorCountMismatchDataRawHtmlSensorsInfo;
sensorsStatus: DetectPlatformSensorCountMismatchDataRawHtmlSensorsStatus;
};

export type DetectPlatformSensorCountMismatchData = {
sensorsInfo: DetectPlatformSensorCountMismatchDataSensorsInfo;
sensorsStatus: DetectPlatformSensorCountMismatchDataSensorsStatus;
data: DetectPlatformSensorCountMismatchDataData;
rawHtml: DetectPlatformSensorCountMismatchDataRawHtml;
};

export type DetectPlatformSensorCountMismatchLogger = Logger | null;
Expand Down

0 comments on commit a74a9b8

Please sign in to comment.