UNPKG

@sailboat-computer/validation

Version:

Validation framework for sailboat computer v3

205 lines 7.68 kB
"use strict"; /** * Extended validation types for Signal K * * This file extends the base validation types with Signal K specific types * to enable more comprehensive validation of Signal K data. */ Object.defineProperty(exports, "__esModule", { value: true }); exports.getSignalKPathMetadata = exports.calculateSignalKConfidence = exports.SignalKValueType = void 0; /** * Signal K value types */ var SignalKValueType; (function (SignalKValueType) { SignalKValueType["NUMBER"] = "number"; SignalKValueType["STRING"] = "string"; SignalKValueType["BOOLEAN"] = "boolean"; SignalKValueType["OBJECT"] = "object"; SignalKValueType["ARRAY"] = "array"; SignalKValueType["POSITION"] = "position"; SignalKValueType["ATTITUDE"] = "attitude"; SignalKValueType["DATETIME"] = "datetime"; })(SignalKValueType || (exports.SignalKValueType = SignalKValueType = {})); /** * Calculate confidence for Signal K data * * @param factors Confidence factors * @returns Confidence score (0-1) */ function calculateSignalKConfidence(factors) { // Weighted average of confidence factors const weights = { sourceReliability: 0.25, pathConsistency: 0.15, valueStability: 0.20, updateFrequency: 0.15, crossValidation: 0.15, contextAppropriateness: 0.10 }; let confidence = 0; let totalWeight = 0; for (const [factor, weight] of Object.entries(weights)) { if (factor in factors && typeof factors[factor] === 'number') { confidence += factors[factor] * weight; totalWeight += weight; } } // Normalize by total weight if (totalWeight > 0) { confidence /= totalWeight; } return Math.max(0, Math.min(1, confidence)); } exports.calculateSignalKConfidence = calculateSignalKConfidence; /** * Get Signal K path metadata for common paths * * @param path Signal K path * @returns Path metadata if available */ function getSignalKPathMetadata(path) { // Common path metadata const pathMetadata = { 'navigation.position': { path: 'navigation.position', valueType: SignalKValueType.POSITION, description: 'The vessel\'s current position', displayName: 'Position' }, 'navigation.courseOverGroundTrue': { path: 'navigation.courseOverGroundTrue', valueType: SignalKValueType.NUMBER, units: 'rad', description: 'Course over ground (true)', displayName: 'COG', zones: [ { lower: 0, upper: 6.28318, state: 'normal' } ] }, 'navigation.speedOverGround': { path: 'navigation.speedOverGround', valueType: SignalKValueType.NUMBER, units: 'm/s', description: 'Speed over ground', displayName: 'SOG', zones: [ { lower: 0, upper: 30, state: 'normal' }, { lower: 30, upper: 50, state: 'warn', message: 'High speed' }, { lower: 50, state: 'alarm', message: 'Excessive speed' } ] }, 'navigation.headingTrue': { path: 'navigation.headingTrue', valueType: SignalKValueType.NUMBER, units: 'rad', description: 'Heading (true)', displayName: 'Heading', zones: [ { lower: 0, upper: 6.28318, state: 'normal' } ] }, 'navigation.headingMagnetic': { path: 'navigation.headingMagnetic', valueType: SignalKValueType.NUMBER, units: 'rad', description: 'Heading (magnetic)', displayName: 'Heading (M)', zones: [ { lower: 0, upper: 6.28318, state: 'normal' } ] }, 'environment.depth.belowKeel': { path: 'environment.depth.belowKeel', valueType: SignalKValueType.NUMBER, units: 'm', description: 'Depth below keel', displayName: 'Depth', zones: [ { lower: 3, state: 'normal' }, { lower: 1, upper: 3, state: 'warn', message: 'Shallow water' }, { lower: 0, upper: 1, state: 'alarm', message: 'Very shallow water' }, { upper: 0, state: 'emergency', message: 'Aground' } ] }, 'environment.wind.speedApparent': { path: 'environment.wind.speedApparent', valueType: SignalKValueType.NUMBER, units: 'm/s', description: 'Apparent wind speed', displayName: 'AWS', zones: [ { lower: 0, upper: 15, state: 'normal' }, { lower: 15, upper: 25, state: 'warn', message: 'Strong wind' }, { lower: 25, state: 'alarm', message: 'Storm conditions' } ] }, 'environment.wind.angleApparent': { path: 'environment.wind.angleApparent', valueType: SignalKValueType.NUMBER, units: 'rad', description: 'Apparent wind angle', displayName: 'AWA', zones: [ { lower: -3.14159, upper: 3.14159, state: 'normal' } ] }, 'electrical.batteries.*.voltage': { path: 'electrical.batteries.*.voltage', valueType: SignalKValueType.NUMBER, units: 'V', description: 'Battery voltage', displayName: 'Voltage', zones: [ { lower: 12.5, upper: 14.8, state: 'normal' }, { lower: 11.8, upper: 12.5, state: 'warn', message: 'Low voltage' }, { lower: 0, upper: 11.8, state: 'alarm', message: 'Critical voltage' }, { lower: 14.8, state: 'warn', message: 'High voltage' } ] }, 'propulsion.*.revolutions': { path: 'propulsion.*.revolutions', valueType: SignalKValueType.NUMBER, units: 'Hz', description: 'Engine revolutions', displayName: 'RPM', zones: [ { lower: 0, upper: 2500, state: 'normal' }, { lower: 2500, upper: 3000, state: 'warn', message: 'High RPM' }, { lower: 3000, state: 'alarm', message: 'Excessive RPM' } ] }, 'propulsion.*.temperature': { path: 'propulsion.*.temperature', valueType: SignalKValueType.NUMBER, units: 'K', description: 'Engine temperature', displayName: 'Temp', zones: [ { lower: 330, upper: 380, state: 'normal' }, { lower: 380, upper: 390, state: 'warn', message: 'High temperature' }, { lower: 390, state: 'alarm', message: 'Overheating' }, { lower: 0, upper: 330, state: 'warn', message: 'Low temperature' } ] } }; // Check for exact path match if (path in pathMetadata) { return pathMetadata[path]; } // Check for wildcard paths for (const [metadataPath, metadata] of Object.entries(pathMetadata)) { if (metadataPath.includes('*')) { const regex = new RegExp('^' + metadataPath.replace('.*.', '\\.[^\\.]+\\.') + '$'); if (regex.test(path)) { return { ...metadata, path // Use the actual path instead of the wildcard path }; } } } return undefined; } exports.getSignalKPathMetadata = getSignalKPathMetadata; //# sourceMappingURL=types-extension.js.map