From a74a9b893c00a1393b80d4a124be401765075f57 Mon Sep 17 00:00:00 2001 From: Jacky Liang Date: Thu, 28 Mar 2024 22:08:54 -0400 Subject: [PATCH] Better bug detection for mis-matched sensors ### 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. --- package.json | 2 +- src/lib/api.ts | 26 +++----------------------- src/lib/detect.ts | 4 ++-- src/lib/items.ts | 4 ---- src/lib/platform.ts | 41 +++++++++++++++++++++++++++++------------ src/types/index.d.ts | 42 ++++++++++++++++++++++++++++++++++++------ 6 files changed, 71 insertions(+), 48 deletions(-) diff --git a/package.json b/package.json index e3b4ee2..4bda6f3 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/src/lib/api.ts b/src/lib/api.ts index 84b0e49..51a7cb8 100644 --- a/src/lib/api.ts +++ b/src/lib/api.ts @@ -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, @@ -1936,6 +1914,7 @@ export class ADTPulse { action: 'GET_SENSORS_INFORMATION', success: true, info: { + rawHtml: sessions.axiosSystem.data, sensors: parsedSensorsTable, }, }; @@ -2196,6 +2175,7 @@ export class ADTPulse { action: 'GET_SENSORS_STATUS', success: true, info: { + rawHtml: sessions.axiosSummary.data, sensors: parsedOrbSensors, }, }; @@ -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); diff --git a/src/lib/detect.ts b/src/lib/detect.ts index 2cd8829..7193ca9 100644 --- a/src/lib/detect.ts +++ b/src/lib/detect.ts @@ -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); @@ -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); diff --git a/src/lib/items.ts b/src/lib/items.ts index ecc1d8f..b0b975d 100644 --- a/src/lib/items.ts +++ b/src/lib/items.ts @@ -47,10 +47,6 @@ export const collectionDoSubmitHandlers: CollectionDoSubmitHandlers = [ }, ], }, - { - description: 'No force arm required', - handlers: [], - }, ]; /** diff --git a/src/lib/platform.ts b/src/lib/platform.ts index a59a5e9..e6447b9 100644 --- a/src/lib/platform.ts +++ b/src/lib/platform.ts @@ -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: [], }; @@ -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. @@ -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); @@ -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 => sensor !== null); const dataHash = generateHash(sensors); diff --git a/src/types/index.d.ts b/src/types/index.d.ts index da4d8d8..2a0b6cd 100644 --- a/src/types/index.d.ts +++ b/src/types/index.d.ts @@ -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; }; @@ -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; }; @@ -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[]; @@ -906,6 +921,7 @@ export type ADTPulsePlatformState = { eventCounters: ADTPulsePlatformStateEventCounters; intervals: ADTPulsePlatformStateIntervals; lastRunOn: ADTPulsePlatformStateLastRunOn; + rawHtml: ADTPulsePlatformStateRawHtml; reportedHashes: ADTPulsePlatformStateReportedHashes; }; @@ -1362,17 +1378,31 @@ export type DetectApiSensorsStatusReturns = Promise; * * @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;