signalk-parquet
Version:
SignalK plugin to save marine data directly to Parquet files with regimen-based control
412 lines • 10.6 kB
TypeScript
import { Context, Path, ServerAPI, NormalizedDelta, SourceRef } from '@signalk/server-api';
export { NormalizedDelta, SourceRef };
import { Request, Response, Router } from 'express';
export interface SignalKPlugin {
id: string;
name: string;
description: string;
schema: any;
start: (options: Partial<PluginConfig>) => void;
stop: () => void;
registerWithRouter?: (router: Router) => void;
}
export interface PluginConfig {
bufferSize: number;
saveIntervalSeconds: number;
outputDirectory: string;
filenamePrefix: string;
retentionDays: number;
fileFormat: 'json' | 'csv' | 'parquet';
vesselMMSI: string;
s3Upload: S3UploadConfig;
enableStreaming?: boolean;
claudeIntegration?: ClaudeIntegrationConfig;
}
export interface ClaudeIntegrationConfig {
enabled: boolean;
apiKey?: string;
model?: 'claude-opus-4-1-20250805' | 'claude-opus-4-20250514' | 'claude-sonnet-4-20250514';
maxTokens?: number;
temperature?: number;
autoAnalysis?: {
daily: boolean;
anomaly: boolean;
threshold: number;
};
cacheEnabled?: boolean;
templates?: string[];
}
export interface VesselContext {
vesselInfo: VesselInfo;
customContext: string;
lastUpdated: string;
autoExtracted: boolean;
}
export interface VesselInfo {
name?: string;
callsign?: string;
mmsi?: string;
length?: number;
beam?: number;
draft?: number;
height?: number;
displacement?: number;
vesselType?: string;
classification?: string;
flag?: string;
grossTonnage?: number;
netTonnage?: number;
deadWeight?: number;
builder?: string;
buildYear?: number;
hullNumber?: string;
ownerName?: string;
port?: string;
notes?: string;
}
export interface VesselContextExtraction {
path: string;
signalkPath: string;
displayName: string;
unit?: string;
category: 'identification' | 'physical' | 'classification' | 'technical' | 'build' | 'contact';
}
export interface PathConfig {
path: Path;
name?: string;
enabled?: boolean;
regimen?: string;
source?: string;
context?: Context;
excludeMMSI?: string[];
}
export interface CommandConfig {
command: string;
path: string;
registered: string;
description?: string;
keywords?: string[];
active?: boolean;
lastExecuted?: string;
}
export interface CommandRegistrationState {
registeredCommands: Map<string, CommandConfig>;
putHandlers: Map<string, CommandPutHandler>;
}
export interface CommandExecutionRequest {
command: string;
value: boolean;
timestamp?: string;
}
export interface CommandRegistrationRequest {
command: string;
description?: string;
keywords?: string[];
}
export interface WebAppPathConfig {
paths: PathConfig[];
commands: CommandConfig[];
}
export interface S3UploadConfig {
enabled: boolean;
timing?: 'realtime' | 'consolidation';
bucket?: string;
region?: string;
keyPrefix?: string;
accessKeyId?: string;
secretAccessKey?: string;
deleteAfterUpload?: boolean;
}
export interface SignalKSubscription {
context: string;
subscribe: Array<{
path: string;
period: number;
}>;
}
export interface DataRecord {
received_timestamp: string;
signalk_timestamp: string;
context: string;
path: string;
value: any;
value_json?: string;
source?: string;
source_label?: string;
source_type?: string;
source_pgn?: number;
source_src?: string;
meta?: string;
[key: string]: any;
}
export interface ParquetWriterOptions {
format: 'json' | 'csv' | 'parquet';
app?: ServerAPI;
}
export interface FileInfo {
name: string;
path: string;
size: number;
modified: string;
}
export interface PathInfo {
path: string;
directory: string;
fileCount: number;
}
export interface ApiResponse<T = any> {
success: boolean;
data?: T;
error?: string;
message?: string;
}
export interface CommandApiResponse extends ApiResponse {
commands?: CommandConfig[];
command?: CommandConfig;
count?: number;
}
export interface CommandExecutionResponse extends ApiResponse {
command?: string;
value?: boolean;
executed?: boolean;
timestamp?: string;
}
export interface PathsApiResponse extends ApiResponse {
dataDirectory?: string;
paths?: PathInfo[];
}
export interface FilesApiResponse extends ApiResponse {
path?: string;
directory?: string;
files?: FileInfo[];
}
export interface QueryApiResponse extends ApiResponse {
query?: string;
rowCount?: number;
data?: any[];
}
export interface SampleApiResponse extends ApiResponse {
path?: string;
file?: string;
columns?: string[];
rowCount?: number;
data?: any[];
}
export interface ConfigApiResponse extends ApiResponse {
paths?: PathConfig[];
}
export interface HealthApiResponse extends ApiResponse {
status?: string;
timestamp?: string;
duckdb?: string;
}
export interface S3TestApiResponse extends ApiResponse {
bucket?: string;
region?: string;
keyPrefix?: string;
}
export interface AnalysisApiResponse extends ApiResponse {
analysis?: AnalysisResult;
history?: AnalysisResult[];
templates?: AnalysisTemplateInfo[];
usage?: {
input_tokens: number;
output_tokens: number;
};
}
export interface AnalysisResult {
id: string;
analysis: string;
insights: string[];
recommendations?: string[];
anomalies?: AnomalyInfo[];
confidence: number;
dataQuality: string;
timestamp: string;
metadata: AnalysisMetadata;
}
export interface AnomalyInfo {
timestamp: string;
value: any;
expectedRange: {
min: number;
max: number;
};
severity: 'low' | 'medium' | 'high';
description: string;
confidence: number;
}
export interface AnalysisMetadata {
dataPath: string;
analysisType: string;
recordCount: number;
timeRange?: {
start: Date;
end: Date;
};
templateUsed?: string;
}
export interface AnalysisTemplateInfo {
id: string;
name: string;
description: string;
category: string;
icon: string;
complexity: string;
estimatedTime: string;
requiredPaths: string[];
}
export interface ClaudeConnectionTestResponse extends ApiResponse {
model?: string;
responseTime?: number;
tokenUsage?: number;
}
export interface TypedRequest<T = any> extends Request {
body: T;
params: {
[key: string]: string;
};
query: {
[key: string]: string;
};
}
export interface TypedResponse<T = any> extends Response {
json: (body: T) => this;
status: (code: number) => this;
}
export interface PluginState {
unsubscribes: Array<() => void>;
streamSubscriptions?: any[];
historicalStreamingService?: any;
streamingService?: any;
streamingEnabled?: boolean;
restoredSubscriptions?: Map<string, any>;
dataBuffers: Map<string, DataRecord[]>;
activeRegimens: Set<string>;
subscribedPaths: Set<string>;
saveInterval?: NodeJS.Timeout;
consolidationInterval?: NodeJS.Timeout;
parquetWriter?: ParquetWriter;
s3Client?: any;
currentConfig?: PluginConfig;
commandState: CommandRegistrationState;
}
export interface ParquetWriter {
writeRecords(filepath: string, records: DataRecord[]): Promise<string>;
writeJSON(filepath: string, records: DataRecord[]): Promise<string>;
writeCSV(filepath: string, records: DataRecord[]): Promise<string>;
writeParquet(filepath: string, records: DataRecord[]): Promise<string>;
consolidateDaily(outputDirectory: string, date: Date, filenamePrefix: string): Promise<number>;
}
export interface DuckDBConnection {
runAndReadAll(query: string): Promise<DuckDBResult>;
disconnectSync(): void;
}
export interface DuckDBResult {
getRowObjects(): any[];
}
export interface DuckDBInstance {
connect(): Promise<DuckDBConnection>;
}
export interface S3Config {
region: string;
credentials?: {
accessKeyId: string;
secretAccessKey: string;
};
}
export interface QueryRequest {
query: string;
}
export interface PathConfigRequest {
path: Path;
name?: string;
enabled?: boolean;
regimen?: string;
source?: string;
context?: Context;
}
export type CommandPutHandler = (context: string, path: string, value: any, callback?: (result: CommandExecutionResult) => void) => CommandExecutionResult;
export interface CommandExecutionResult {
state: 'COMPLETED' | 'PENDING' | 'FAILED';
statusCode?: number;
message?: string;
timestamp: string;
}
export interface CommandHistoryEntry {
command: string;
action: 'EXECUTE' | 'STOP' | 'REGISTER' | 'UNREGISTER' | 'UPDATE';
value?: boolean;
timestamp: string;
success: boolean;
error?: string;
}
export declare enum CommandStatus {
ACTIVE = "ACTIVE",
INACTIVE = "INACTIVE",
PENDING = "PENDING",
ERROR = "ERROR"
}
export type FileFormat = 'json' | 'csv' | 'parquet';
export type UploadTiming = 'realtime' | 'consolidation';
export type BufferKey = string;
export interface PluginError extends Error {
code?: string;
details?: any;
}
export interface ConsolidationOptions {
outputDirectory: string;
date: Date;
filenamePrefix: string;
}
export interface ConsolidationResult {
processedPaths: number;
consolidatedFiles: string[];
errors: string[];
}
export interface ParquetField {
type: string;
optional?: boolean;
repeated?: boolean;
}
export interface ParquetSchema {
[fieldName: string]: ParquetField;
}
export interface DataSummary {
rowCount: number;
timeRange: {
start: Date;
end: Date;
};
columns: ColumnInfo[];
statisticalSummary: Record<string, Statistics>;
dataQuality: DataQualityMetrics;
}
export interface ColumnInfo {
name: string;
type: string;
nullCount: number;
uniqueCount: number;
sampleValues: any[];
}
export interface Statistics {
count: number;
mean?: number;
median?: number;
min?: any;
max?: any;
stdDev?: number;
}
export interface DataQualityMetrics {
completeness: number;
consistency: number;
timeliness: number;
accuracy: number;
}
export interface ProcessingStats {
totalBuffers: number;
buffersWithData: number;
totalRecords: number;
processedPaths: string[];
}
//# sourceMappingURL=types.d.ts.map