@sailboat-computer/health-monitoring
Version:
Comprehensive health monitoring system for sailboat computer v3 with marine-specific health checks
302 lines (276 loc) • 8.25 kB
text/typescript
/**
* GPS Recalibration Recovery Action
* Demonstrates a concrete implementation of a recovery action for GPS systems
*/
import {
BaseRecoveryAction,
RecoveryActionConfig,
RecoveryActionResult,
RecoveryActionType,
RecoveryPriority,
RecoveryStatus
} from '../RecoveryAction';
import {
HealthCheckResult,
OperationalContext,
OperationalContextType,
MarineSystemType,
MarineSystemTypeType,
MarineEnvironmentStatus
} from '../../types';
/**
* GPS recalibration parameters
*/
export interface GPSRecalibrationParams {
/**
* Reset satellite tracking
*/
resetSatelliteTracking: boolean;
/**
* Clear almanac data
*/
clearAlmanac: boolean;
/**
* Reset HDOP thresholds
*/
resetHDOPThresholds: boolean;
/**
* Force cold start
*/
forceColdStart: boolean;
/**
* Wait time for satellite acquisition in seconds
*/
satelliteAcquisitionTimeout: number;
}
/**
* GPS Recalibration Action
* Attempts to recalibrate a GPS system that is reporting poor quality data
*/
export class GPSRecalibrationAction extends BaseRecoveryAction {
private gpsInterface: {
resetSatelliteTracking: () => Promise<boolean>;
clearAlmanac: () => Promise<boolean>;
resetHDOPThresholds: () => Promise<boolean>;
forceColdStart: () => Promise<boolean>;
waitForSatellites: (timeout: number) => Promise<number>;
};
constructor(
config: RecoveryActionConfig,
gpsInterface: {
resetSatelliteTracking: () => Promise<boolean>;
clearAlmanac: () => Promise<boolean>;
resetHDOPThresholds: () => Promise<boolean>;
forceColdStart: () => Promise<boolean>;
waitForSatellites: (timeout: number) => Promise<number>;
}
) {
super(config);
this.gpsInterface = gpsInterface;
}
/**
* Perform GPS recalibration
*/
protected async performRecovery(
triggeringCheck: HealthCheckResult,
operationalContext: OperationalContextType,
marineEnvironment?: MarineEnvironmentStatus
): Promise<RecoveryActionResult> {
const params = this.config.parameters as GPSRecalibrationParams;
const startTime = new Date();
const details: Record<string, any> = {};
const steps: string[] = [];
try {
// Step 1: Reset satellite tracking if configured
if (params.resetSatelliteTracking) {
steps.push('Resetting satellite tracking');
const resetResult = await this.gpsInterface.resetSatelliteTracking();
details['resetSatelliteTracking'] = resetResult;
if (!resetResult) {
return this.createRecoveryResult(
startTime,
new Date(),
false,
'Failed to reset satellite tracking',
steps,
details,
operationalContext,
marineEnvironment
);
}
}
// Step 2: Clear almanac if configured
if (params.clearAlmanac) {
steps.push('Clearing almanac data');
const clearResult = await this.gpsInterface.clearAlmanac();
details['clearAlmanac'] = clearResult;
if (!clearResult) {
return this.createRecoveryResult(
startTime,
new Date(),
false,
'Failed to clear almanac data',
steps,
details,
operationalContext,
marineEnvironment
);
}
}
// Step 3: Reset HDOP thresholds if configured
if (params.resetHDOPThresholds) {
steps.push('Resetting HDOP thresholds');
const resetResult = await this.gpsInterface.resetHDOPThresholds();
details['resetHDOPThresholds'] = resetResult;
if (!resetResult) {
return this.createRecoveryResult(
startTime,
new Date(),
false,
'Failed to reset HDOP thresholds',
steps,
details,
operationalContext,
marineEnvironment
);
}
}
// Step 4: Force cold start if configured
if (params.forceColdStart) {
steps.push('Forcing cold start');
const coldStartResult = await this.gpsInterface.forceColdStart();
details['forceColdStart'] = coldStartResult;
if (!coldStartResult) {
return this.createRecoveryResult(
startTime,
new Date(),
false,
'Failed to force cold start',
steps,
details,
operationalContext,
marineEnvironment
);
}
}
// Step 5: Wait for satellites
steps.push('Waiting for satellite acquisition');
const satelliteCount = await this.gpsInterface.waitForSatellites(
params.satelliteAcquisitionTimeout
);
details['satelliteCount'] = satelliteCount;
// Check if we acquired enough satellites
const success = satelliteCount >= 4; // Minimum for 3D fix
const message = success
? `GPS recalibration successful, acquired ${satelliteCount} satellites`
: `GPS recalibration failed, only acquired ${satelliteCount} satellites`;
return this.createRecoveryResult(
startTime,
new Date(),
success,
message,
steps,
details,
operationalContext,
marineEnvironment
);
} catch (error) {
return this.createRecoveryResult(
startTime,
new Date(),
false,
`GPS recalibration error: ${(error as Error).message}`,
steps,
details,
operationalContext,
marineEnvironment
);
}
}
/**
* Create a recovery result
*/
private createRecoveryResult(
startTime: Date,
endTime: Date,
success: boolean,
message: string,
steps: string[],
details: Record<string, any>,
operationalContext: OperationalContextType,
marineEnvironment?: MarineEnvironmentStatus
): RecoveryActionResult {
return {
actionId: this.config.actionId,
name: this.config.name,
type: this.config.type,
status: success ? RecoveryStatus.SUCCEEDED : RecoveryStatus.FAILED,
message,
startTime,
endTime,
duration: endTime.getTime() - startTime.getTime(),
retryCount: this.retryCount,
success,
error: success ? '' : message,
details: {
...details,
steps,
completedSteps: steps.length
},
marineContext: {
operationalContext,
environmentalConditions: marineEnvironment ? { ...marineEnvironment } : undefined
},
triggeringCheck: undefined
};
}
}
/**
* Create a GPS recalibration action with default configuration
*/
export function createGPSRecalibrationAction(
gpsInterface: {
resetSatelliteTracking: () => Promise<boolean>;
clearAlmanac: () => Promise<boolean>;
resetHDOPThresholds: () => Promise<boolean>;
forceColdStart: () => Promise<boolean>;
waitForSatellites: (timeout: number) => Promise<number>;
},
customConfig?: Partial<RecoveryActionConfig>
): GPSRecalibrationAction {
const defaultConfig: RecoveryActionConfig = {
actionId: 'gps-recalibration',
name: 'GPS Recalibration',
type: RecoveryActionType.RECALIBRATE,
marineSystemType: MarineSystemType.NAVIGATION as MarineSystemTypeType,
priority: RecoveryPriority.HIGH,
timeout: 60000, // 60 seconds
maxRetries: 1,
retryDelay: 5000,
requiresApproval: false,
automatedExecution: true,
marineSettings: {
allowedContexts: [
OperationalContext.DOCKED,
OperationalContext.ANCHORED,
OperationalContext.SAILING,
OperationalContext.MOTORING
] as OperationalContextType[],
allowInRoughSeas: false,
powerAware: true,
safetyImpact: true,
powerConsumption: 2 // 2 watts
},
parameters: {
resetSatelliteTracking: true,
clearAlmanac: false,
resetHDOPThresholds: true,
forceColdStart: false,
satelliteAcquisitionTimeout: 30 // 30 seconds
}
};
return new GPSRecalibrationAction(
{ ...defaultConfig, ...customConfig },
gpsInterface
);
}