Skip to content

Commit

Permalink
Sensor length bugfix
Browse files Browse the repository at this point in the history
### FIXED
- Sensor length mis-match detector removed due to false-positive reports. From now on, plugin will use the list of sensors as source of truth.
  • Loading branch information
mrjackyliang committed Mar 30, 2024
1 parent a74a9b8 commit 2b74f1d
Show file tree
Hide file tree
Showing 5 changed files with 19 additions and 196 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.14",
"version": "3.2.15",
"description": "Homebridge security system platform for ADT Pulse",
"main": "./build/index.js",
"exports": "./build/index.js",
Expand Down
2 changes: 0 additions & 2 deletions src/lib/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1914,7 +1914,6 @@ export class ADTPulse {
action: 'GET_SENSORS_INFORMATION',
success: true,
info: {
rawHtml: sessions.axiosSystem.data,
sensors: parsedSensorsTable,
},
};
Expand Down Expand Up @@ -2175,7 +2174,6 @@ export class ADTPulse {
action: 'GET_SENSORS_STATUS',
success: true,
info: {
rawHtml: sessions.axiosSummary.data,
sensors: parsedOrbSensors,
},
};
Expand Down
88 changes: 0 additions & 88 deletions src/lib/detect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,6 @@ import type {
DetectApiSensorsStatusLogger,
DetectApiSensorsStatusReturns,
DetectApiSensorsStatusSensors,
DetectPlatformSensorCountMismatchData,
DetectPlatformSensorCountMismatchDebugMode,
DetectPlatformSensorCountMismatchLogger,
DetectPlatformSensorCountMismatchReturns,
DetectPlatformUnknownSensorsActionDebugMode,
DetectPlatformUnknownSensorsActionLogger,
DetectPlatformUnknownSensorsActionReturns,
Expand Down Expand Up @@ -889,90 +885,6 @@ export async function detectApiSensorsStatus(sensors: DetectApiSensorsStatusSens
return false;
}

/**
* Detect platform sensor count mismatch.
*
* @param {DetectPlatformSensorCountMismatchData} data - Data.
* @param {DetectPlatformSensorCountMismatchLogger} logger - Logger.
* @param {DetectPlatformSensorCountMismatchDebugMode} debugMode - Debug mode.
*
* @returns {DetectPlatformSensorCountMismatchReturns}
*
* @since 1.0.0
*/
export async function detectPlatformSensorCountMismatch(data: DetectPlatformSensorCountMismatchData, logger: DetectPlatformSensorCountMismatchLogger, debugMode: DetectPlatformSensorCountMismatchDebugMode): DetectPlatformSensorCountMismatchReturns {
const detectedCountMismatch = data.data.sensorsInfo.length !== data.data.sensorsStatus.length;

if (detectedCountMismatch) {
const cleanedData = removePersonalIdentifiableInformation(data);

// If outdated, it means plugin may already have support.
try {
const outdated = await isPluginOutdated();

if (outdated) {
if (logger !== null) {
logger.warn('Plugin has detected a sensor count mismatch. You are running an older plugin version, please update soon.');
}

// This is intentionally duplicated if using Homebridge debug mode.
if (debugMode) {
debugLog(logger, 'detect.ts / detectPlatformSensorCountMismatch()', 'warn', 'Plugin has detected a sensor count mismatch. You are running an older plugin version, please update soon');
}

// Do not send analytics for users running outdated plugin versions.
return false;
}
} catch (error) {
if (debugMode === true) {
debugLog(logger, 'detect.ts / detectPlatformSensorCountMismatch()', 'error', 'Failed to check if plugin is outdated');
stackTracer('serialize-error', serializeError(error));
}

// Try to check if plugin is outdated later on.
return false;
}

if (logger !== null) {
logger.warn('Plugin has detected a sensor count mismatch. Notifying plugin author about this discovery ...');
}

// This is intentionally duplicated if using Homebridge debug mode.
if (debugMode) {
debugLog(logger, 'detect.ts / detectPlatformSensorCountMismatch()', 'warn', 'Plugin has detected a sensor count mismatch. Notifying plugin author about this discovery');
}

// Show content being sent to author.
stackTracer('detect-content', cleanedData);

try {
await axios.post(
getDetectReportUrl(),
JSON.stringify(cleanedData, null, 2),
{
family: 4,
headers: {
'User-Agent': 'homebridge-adt-pulse',
'X-Title': 'Detected a sensor count mismatch',
},
},
);

return true;
} catch (error) {
if (debugMode === true) {
debugLog(logger, 'detect.ts / detectPlatformSensorCountMismatch()', 'error', 'Failed to notify plugin author about the sensor count mismatch');
stackTracer('serialize-error', serializeError(error));
}

// Try to send information to author later.
return false;
}
}

return false;
}

/**
* Detect platform unknown sensors action.
*
Expand Down
67 changes: 16 additions & 51 deletions src/lib/platform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { serializeError } from 'serialize-error';

import { ADTPulseAccessory } from '@/lib/accessory.js';
import { ADTPulse } from '@/lib/api.js';
import { detectPlatformSensorCountMismatch, detectPlatformUnknownSensorsAction } from '@/lib/detect.js';
import { detectPlatformUnknownSensorsAction } from '@/lib/detect.js';
import { textOrbTextSummarySections } from '@/lib/regex.js';
import { platformConfig } from '@/lib/schema.js';
import {
Expand Down Expand Up @@ -61,6 +61,7 @@ import type {
ADTPulsePlatformUnifyDevicesId,
ADTPulsePlatformUnifyDevicesReturns,
ADTPulsePlatformUnknownInformationDispatcherReturns,
ADTPulsePlatformUnknownInformationDispatcherSensors,
ADTPulsePlatformUpdateAccessoryDevice,
ADTPulsePlatformUpdateAccessoryReturns,
} from '@/types/index.d.ts';
Expand Down Expand Up @@ -226,10 +227,6 @@ 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 @@ -875,24 +872,18 @@ export class ADTPulsePlatform implements ADTPulsePlatformPlugin {

// Update sensors information.
if (requests[3].success) {
const { rawHtml, sensors } = requests[3].info;
const { 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 { rawHtml, sensors } = requests[4].info;
const { 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 @@ -1027,52 +1018,26 @@ export class ADTPulsePlatform implements ADTPulsePlatformPlugin {
* @since 1.0.0
*/
private async unknownInformationDispatcher(): ADTPulsePlatformUnknownInformationDispatcherReturns {
const { sensorsInfo: dataSensorsInfo, sensorsStatus: dataSensorsStatus } = this.#state.data;
const { sensorsInfo: rawHtmlSensorsInfo, sensorsStatus: rawHtmlSensorsStatus } = this.#state.rawHtml;
const { sensorsInfo, sensorsStatus } = this.#state.data;

if (
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 = {
data: {
sensorsInfo: dataSensorsInfo,
sensorsStatus: dataSensorsStatus,
},
rawHtml: {
sensorsInfo: rawHtmlSensorsInfo,
sensorsStatus: rawHtmlSensorsStatus,
},
};
const dataHash = generateHash(data);
const sensors = sensorsInfo.reduce((allSensors, currentSensor) => {
const matchedStatus = sensorsStatus.find((sensorStatus) => currentSensor.zone === sensorStatus.zone);

// If the detector has not reported this event before.
if (this.#state.reportedHashes.find((reportedHash) => dataHash === reportedHash) === undefined) {
const detectedNew = await detectPlatformSensorCountMismatch(data, this.#log, this.#debugMode);

// Save this hash so the detector does not detect the same thing multiple times.
if (detectedNew) {
this.#state.reportedHashes.push(dataHash);
}
if (matchedStatus !== undefined) {
allSensors.push({
info: currentSensor,
status: matchedStatus,
type: condenseSensorType(currentSensor.deviceType),
});
}

// Stop here until this is resolved.
return;
}

// Generate an array of matching "sensorInfo" and "sensorStatus" with the device type.
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);
return allSensors;
}, [] as ADTPulsePlatformUnknownInformationDispatcherSensors);
const dataHash = generateHash(sensors);

// If the detector has not reported this event before.
if (this.#state.reportedHashes.find((reportedHash) => dataHash === reportedHash) === undefined) {
const detectedNew = await detectPlatformUnknownSensorsAction(matchedSensors, this.#log, this.#debugMode);
const detectedNew = await detectPlatformUnknownSensorsAction(sensors, this.#log, this.#debugMode);

// Save this hash so the detector does not detect the same thing multiple times.
if (detectedNew) {
Expand Down
56 changes: 2 additions & 54 deletions src/types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -257,14 +257,11 @@ 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 @@ -280,14 +277,11 @@ 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 @@ -902,15 +896,6 @@ 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 @@ -921,7 +906,6 @@ export type ADTPulsePlatformState = {
eventCounters: ADTPulsePlatformStateEventCounters;
intervals: ADTPulsePlatformStateIntervals;
lastRunOn: ADTPulsePlatformStateLastRunOn;
rawHtml: ADTPulsePlatformStateRawHtml;
reportedHashes: ADTPulsePlatformStateReportedHashes;
};

Expand Down Expand Up @@ -964,6 +948,8 @@ export type ADTPulsePlatformUnifyDevicesId = PluginDeviceId;
*/
export type ADTPulsePlatformUnknownInformationDispatcherReturns = Promise<void>;

export type ADTPulsePlatformUnknownInformationDispatcherSensors = DetectPlatformUnknownSensorsActionSensors;

/**
* ADT Pulse Platform - Update accessory.
*
Expand Down Expand Up @@ -1373,44 +1359,6 @@ export type DetectApiSensorsStatusDebugMode = boolean | null;

export type DetectApiSensorsStatusReturns = Promise<boolean>;

/**
* Detect platform sensor count mismatch.
*
* @since 1.0.0
*/
export type DetectPlatformSensorCountMismatchDataDataSensorInfo = SensorInformation;

export type DetectPlatformSensorCountMismatchDataDataSensorsInfo = DetectPlatformSensorCountMismatchDataDataSensorInfo[];

export type DetectPlatformSensorCountMismatchDataDataSensorStatus = SensorStatus;

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 = {
data: DetectPlatformSensorCountMismatchDataData;
rawHtml: DetectPlatformSensorCountMismatchDataRawHtml;
};

export type DetectPlatformSensorCountMismatchLogger = Logger | null;

export type DetectPlatformSensorCountMismatchDebugMode = boolean | null;

export type DetectPlatformSensorCountMismatchReturns = Promise<boolean>;

/**
* Detect platform unknown sensors action.
*
Expand Down

0 comments on commit 2b74f1d

Please sign in to comment.