@canboat/canboatjs
Version:
Native javascript version of canboat
135 lines • 5.44 kB
TypeScript
/**
* Copyright 2026 Signal K contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Transport driver for the Maretron IPG100 over its 0xA5-framed TCP
* protocol.
*
* Notes:
*
* * The IPG100 caps the total number of simultaneous client TCP
* connections at 20. A 21st client is refused.
* * The 4th token in CONNECT is a client-type. Sending `MOBILE`
* does NOT consume one of the limited licensed-client slots, so
* this driver is safe to run alongside Maretron N2KView etc.
* * The IPG100 performs NO device-side PGN filtering in either
* direction. Every frame on the bus reaches every connected client,
* and every frame any client writes is forwarded both to the bus
* and to all *other* connected clients.
* * Binary mode is mandatory for anything beyond a small set of
* well-known PGNs: the IPG's default ASCII output depends on its
* internal PGN dictionary, which can't represent newer / vendor
* PGNs. We send SET_MODE BINARY immediately after CONNECTED.
* * The IPG handles fast-packet reassembly itself, so each frame
* carries a full logical N2K payload.
* * On TX, source address on the wire is always 0xFF — the IPG
* substitutes its own claimed SA.
*/
import net from 'net';
export declare const IPG_PORT = 6543;
/**
* Decoded shape of a single 0xA5 frame.
*/
export interface MaretronDecodedFrame {
pgn: number;
pdu_format: 'PDU1' | 'PDU2';
src: number;
dst: number;
priority: number;
dp: number;
edp: number;
msg_type: number;
msg_type_name: string;
payload_length: number;
payload: Buffer;
}
export interface MaretronParseResult {
/** Bytes consumed from `buf` starting at `offset`. 0 = need more bytes. */
consumed: number;
/** Decoded frame, or undefined when more bytes are required. */
frame?: MaretronDecodedFrame;
/** True when bytes at `offset` are clearly not a valid frame start. */
invalid?: boolean;
}
/**
* Parse a single Maretron 0xA5 binary frame starting at `buf[offset]`.
*
* Header layout:
* byte 0 SYNC = 0xA5
* byte 1 F1 = [sync:1][prio:3][edp:1][msgType:2][dp:1]
* byte 2 PF
* byte 3 PS PDU1 → destination SA; PDU2 → PGN low byte
* byte 4 SA 0xFF = IPG substitutes its claimed SA
* byte 5 LL msgType != 3 → 8-bit length, payload starts at 6
* byte 6 LH msgType == 3 only → length high byte, payload at 7
*/
export declare function parseMaretronFrame(buf: Buffer, offset?: number): MaretronParseResult;
/** Fields a caller must supply to construct an outbound 0xA5 frame. */
export interface MaretronBuildInput {
pgn: number;
src?: number;
dst?: number;
priority?: number;
msg_type?: number;
edp?: number;
payload: Buffer | Uint8Array | number[];
}
/**
* Serialize a single 0xA5 frame from a structured description.
*
* PDU1 puts `dst` in the PS byte; PDU2 puts the PGN low byte in PS and
* ignores the caller-supplied `dst`.
*/
export declare function buildMaretronFrame(input: MaretronBuildInput): Buffer;
/**
* Build the 4-token CONNECT handshake message.
*
* The IPG strips a leading and trailing character from the password
* token before matching, so the password is always wrapped in double
* quotes on the wire. A stock IPG with no configured password is matched
* by the literal two-character string `""`.
*
* The 4th token is a client-type label that the IPG parses but does not
* act on. Hard-coded to "MOBILE" to match the convention used elsewhere.
*/
export declare function buildConnectMessage(password: string): Buffer;
export declare const SET_MODE_BINARY: Buffer<ArrayBuffer>;
export interface MaretronIPGOptions {
host?: string;
port?: number;
password?: string;
reconnect?: boolean;
/** Initial reconnect delay (ms). Default 1000. */
reconnectInitialMs?: number;
/** Max reconnect delay (ms). Default 32000. Doubles 1→2→4→8→16→32 s. */
reconnectMaxMs?: number;
idleTeardownMs?: number;
/**
* When the *initial* connection attempt fails (bad host, refused port,
* DNS error), emit a stream `'error'` and stop retrying instead of
* looping forever. Defaults to `true` in standalone use (no `app`) so
* the CLI fails fast on a typo, and `false` when an `app` is provided
* so SignalK keeps retrying until the IPG comes online. Successful
* sessions always reconnect on close regardless of this flag.
*/
failFastOnInitialConnect?: boolean;
/** SignalK provider app — used for nmea2000out / event wiring. */
app?: any;
providerId?: string;
outEvent?: string;
jsonOutEvent?: string;
_socketFactory?: (host: string, port: number) => net.Socket;
}
export declare function MaretronIPGStream(this: any, options?: MaretronIPGOptions): any;
//# sourceMappingURL=maretron-ipg.d.ts.map