@aircast-4g/mavlink 1.1.6 → 1.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,51 +1,46 @@
1
1
  # Aircast MAVLink
2
2
 
3
- A comprehensive Node.js tool for working with MAVLink protocols, providing both TypeScript type generation from XML dialect files and real-time MAVLink message parsing.
3
+ A comprehensive TypeScript/JavaScript library for working with MAVLink protocols, providing both TypeScript type generation from XML dialect files and robust real-time MAVLink message parsing with built-in frame parsing and buffering.
4
4
 
5
5
  ## Features
6
6
 
7
7
  ### Type Generation
8
8
  - Generate TypeScript interfaces from MAVLink XML dialects
9
- - Support for all MAVLink data types and enums
9
+ - Support for all MAVLink data types and enums
10
10
  - Type-safe enum definitions with numeric values (not string literals)
11
11
  - Batch processing of multiple dialects
12
12
  - CLI interface for easy integration
13
13
 
14
- ### MAVLink Parser
15
- - Real-time MAVLink v1 and v2 message parsing
16
- - CRC validation for data integrity
17
- - Streaming data support with buffer management
18
- - Browser and Node.js compatibility
19
- - Web Worker and WebRTC integration examples
20
- - TCP/UDP connection handling
14
+ ### MAVLink Parser & Decoder
15
+ - **Complete message parsing** - Built-in frame parsing with `parseBytes()` API
16
+ - **Protocol support** - MAVLink v1 and v2 message parsing
17
+ - **Robust decoding** - Fixed array handling, proper field ordering, graceful error handling
18
+ - **Buffering** - Automatic buffer management for partial messages
19
+ - **Browser & Node.js** - Universal compatibility with Web Workers
20
+ - **Dialect-specific parsers** - Generated parsers for each dialect (Common, ArduPilot, etc.)
21
21
 
22
22
  ## Installation
23
23
 
24
- ### From GitHub Packages
25
-
26
- Since this is a public repository, you can install the package directly without authentication:
27
-
28
24
  ```bash
29
- # Global installation
30
- npm install -g @pavliha/aircast-mavlink --registry=https://npm.pkg.github.com
25
+ # Install the package
26
+ npm install @aircast-4g/mavlink
31
27
 
32
- # Local installation
33
- npm install @pavliha/aircast-mavlink --registry=https://npm.pkg.github.com
28
+ # Or with yarn
29
+ yarn add @aircast-4g/mavlink
34
30
  ```
35
31
 
36
- **Alternative: Configure npm scope (one-time setup)**
37
- ```bash
38
- # Configure npm to use GitHub Packages for @pavliha scope
39
- npm config set @pavliha:registry https://npm.pkg.github.com
40
-
41
- # Then install normally
42
- npm install @pavliha/aircast-mavlink
43
- ```
32
+ ### CDN Usage (Browser)
44
33
 
45
- ### Global Installation (Alternative)
34
+ ```html
35
+ <!-- ES modules -->
36
+ <script type="module">
37
+ import { CommonParser } from 'https://esm.sh/@aircast-4g/mavlink@1.1.6/dist/dialects/common/index.js';
38
+ </script>
46
39
 
47
- ```bash
48
- npm install -g aircast-mavlink
40
+ <!-- Or for specific dialects -->
41
+ <script type="module">
42
+ import { ArdupilotmegaParser } from 'https://esm.sh/@aircast-4g/mavlink@1.1.6/dist/dialects/ardupilotmega/index.js';
43
+ </script>
49
44
  ```
50
45
 
51
46
  ### Local Development
@@ -136,12 +131,151 @@ node dist/cli.js list
136
131
  node dist/cli.js generate -i ./my-dialect.xml -o ./output/custom
137
132
  ```
138
133
 
134
+ ## Quick Start
135
+
136
+ ### Basic Message Parsing
137
+
138
+ ```typescript
139
+ import { CommonParser } from '@aircast-4g/mavlink/dialects/common';
140
+
141
+ // Create parser instance
142
+ const parser = new CommonParser();
143
+
144
+ // Parse raw MAVLink bytes
145
+ const rawBytes = new Uint8Array([/* MAVLink frame data */]);
146
+ const messages = parser.parseBytes(rawBytes);
147
+
148
+ // Process messages
149
+ messages.forEach(message => {
150
+ console.log(`Received ${message.message_name} from ${message.system_id}:${message.component_id}`);
151
+ console.log('Payload:', message.payload);
152
+ });
153
+ ```
154
+
155
+ ### Web Worker Integration
156
+
157
+ ```typescript
158
+ // worker.js
159
+ import { ArdupilotmegaParser } from '@aircast-4g/mavlink/dialects/ardupilotmega';
160
+
161
+ const parser = new ArdupilotmegaParser();
162
+
163
+ self.onmessage = (event) => {
164
+ if (event.data.type === 'PARSE_MAVLINK') {
165
+ const messages = parser.parseBytes(event.data.data);
166
+ self.postMessage({ type: 'MESSAGES', messages });
167
+ }
168
+ };
169
+ ```
170
+
171
+ ### Real-time Stream Processing
172
+
173
+ ```typescript
174
+ import { CommonParser } from '@aircast-4g/mavlink/dialects/common';
175
+
176
+ const parser = new CommonParser();
177
+
178
+ // WebSocket example
179
+ websocket.onmessage = (event) => {
180
+ const data = new Uint8Array(event.data);
181
+ const messages = parser.parseBytes(data);
182
+
183
+ messages.forEach(msg => {
184
+ switch (msg.message_name) {
185
+ case 'HEARTBEAT':
186
+ updateSystemStatus(msg.payload);
187
+ break;
188
+ case 'GPS_RAW_INT':
189
+ updatePosition(msg.payload);
190
+ break;
191
+ }
192
+ });
193
+ };
194
+ ```
195
+
196
+ ## API Reference
197
+
198
+ ### Dialect Parsers
199
+
200
+ Each dialect has its own parser class with the same interface:
201
+
202
+ ```typescript
203
+ // Available parsers
204
+ import { CommonParser } from '@aircast-4g/mavlink/dialects/common';
205
+ import { ArdupilotmegaParser } from '@aircast-4g/mavlink/dialects/ardupilotmega';
206
+ import { MinimalParser } from '@aircast-4g/mavlink/dialects/minimal';
207
+ import { StandardParser } from '@aircast-4g/mavlink/dialects/standard';
208
+ import { TestParser } from '@aircast-4g/mavlink/dialects/test';
209
+
210
+ // Parser interface
211
+ class DialectParser {
212
+ // Parse raw bytes into messages (handles buffering internally)
213
+ parseBytes(data: Uint8Array): ParsedMAVLinkMessage[];
214
+
215
+ // Decode a single frame
216
+ decode(frame: MAVLinkFrame): ParsedMAVLinkMessage;
217
+
218
+ // Get supported message IDs
219
+ getSupportedMessageIds(): number[];
220
+
221
+ // Check if message ID is supported
222
+ supportsMessage(messageId: number): boolean;
223
+
224
+ // Get message definition
225
+ getMessageDefinition(id: number): MessageDefinition | undefined;
226
+
227
+ // Get dialect name
228
+ getDialectName(): string;
229
+
230
+ // Reset internal buffer
231
+ resetBuffer(): void;
232
+ }
233
+ ```
234
+
235
+ ### ParsedMAVLinkMessage
236
+
237
+ ```typescript
238
+ interface ParsedMAVLinkMessage {
239
+ timestamp: number; // Parse timestamp
240
+ system_id: number; // MAVLink system ID
241
+ component_id: number; // MAVLink component ID
242
+ message_id: number; // Message type ID
243
+ message_name: string; // Human-readable message name
244
+ sequence: number; // MAVLink sequence number
245
+ payload: Record<string, any>; // Decoded message fields
246
+ protocol_version: 1 | 2; // MAVLink protocol version
247
+ checksum: number; // Frame checksum
248
+ crc_ok: boolean; // CRC validation result
249
+ signature?: Uint8Array; // MAVLink v2 signature (if present)
250
+ dialect?: string; // Dialect name
251
+ }
252
+ ```
253
+
254
+ ### Key Benefits of parseBytes()
255
+
256
+ 1. **Automatic Buffering** - Handles partial frames across multiple calls
257
+ 2. **Frame Synchronization** - Finds valid MAVLink frames in noisy data
258
+ 3. **Protocol Detection** - Automatically detects MAVLink v1 vs v2
259
+ 4. **Robust Parsing** - Gracefully handles malformed data
260
+ 5. **Zero Configuration** - No setup required, just call parseBytes()
261
+
262
+ ```typescript
263
+ const parser = new CommonParser();
264
+
265
+ // Handle partial data - parser buffers automatically
266
+ const part1 = new Uint8Array([0xFE, 0x09, 0x00]); // Partial frame
267
+ const part2 = new Uint8Array([0x01, 0x01, 0x00, /* rest of frame */]);
268
+
269
+ const messages1 = parser.parseBytes(part1); // [] - no complete messages
270
+ const messages2 = parser.parseBytes(part2); // [message] - complete message
271
+ ```
272
+
139
273
  ### Programmatic Usage
140
274
 
141
275
  #### Type Generation
142
276
 
143
277
  ```typescript
144
- import { MAVLinkGenerator, generateTypesFromXML } from 'aircast-mavlink';
278
+ import { MAVLinkGenerator, generateTypesFromXML } from '@aircast-4g/mavlink';
145
279
 
146
280
  // Generate from XML string
147
281
  const files = await generateTypesFromXML(xmlContent, {
@@ -170,92 +304,100 @@ await generator.generateFromURL(
170
304
  includeTypeGuards: true
171
305
  }
172
306
  );
173
-
174
- // From local file
175
- await generator.generateFromFile('./dialect.xml', './output', {
176
- dialectName: 'custom',
177
- outputFormat: 'single',
178
- includeEnums: true,
179
- includeTypeGuards: false
180
- });
181
307
  ```
182
308
 
183
- #### MAVLink Parsing
309
+ ## Examples & Integration Patterns
310
+
311
+ ### Real-time Telemetry Processing
184
312
 
185
313
  ```typescript
186
- import {
187
- MAVLinkParser,
188
- MAVLinkFrameParser,
189
- DialectParserFactory,
190
- CRCCalculator
191
- } from 'aircast-mavlink';
192
-
193
- // Import pre-generated dialect types separately
194
- import * as CommonTypes from 'aircast-mavlink/types/common';
195
- import * as MinimalTypes from 'aircast-mavlink/types/minimal';
196
- import * as ArduPilotMegaTypes from 'aircast-mavlink/types/ardupilotmega';
197
- import * as StandardTypes from 'aircast-mavlink/types/standard';
314
+ import { CommonParser } from '@aircast-4g/mavlink/dialects/common';
198
315
 
199
- // Basic message parsing with async initialization
200
- const parser = new MAVLinkParser({ validateCRC: true });
201
- await parser.initialize(); // Initialize dialect parsers
316
+ const parser = new CommonParser();
202
317
 
203
- // Parse incoming data (Buffer or Uint8Array)
204
- const messages = await parser.parseBytes(incomingData);
205
- messages.forEach(message => {
206
- console.log(`Message: ${message.message_name}`);
207
- console.log(`From: ${message.system_id}:${message.component_id}`);
208
- console.log(`Payload:`, message.payload);
209
- });
210
-
211
- // Advanced dialect-specific parsing
212
- const dialectParser = await DialectParserFactory.createParser('common');
318
+ // WebRTC data channel
319
+ dataChannel.onmessage = (event) => {
320
+ const messages = parser.parseBytes(new Uint8Array(event.data));
321
+ messages.forEach(processMessage);
322
+ };
213
323
 
214
- const frame = {
215
- magic: 0xFD, length: 9, sequence: 1, system_id: 1, component_id: 1,
216
- message_id: 0, payload: new Uint8Array([6, 3, 196, 144, 0, 0, 4, 0, 0]),
217
- checksum: 0x1234, protocol_version: 2
324
+ // WebSocket connection
325
+ websocket.onmessage = (event) => {
326
+ const messages = parser.parseBytes(new Uint8Array(event.data));
327
+ messages.forEach(processMessage);
218
328
  };
219
329
 
220
- const message = dialectParser.decode(frame);
221
- console.log('Decoded message:', message);
330
+ // TCP/UDP streams (Node.js)
331
+ socket.on('data', (data) => {
332
+ const messages = parser.parseBytes(data);
333
+ messages.forEach(processMessage);
334
+ });
335
+ ```
222
336
 
223
- // WebSocket integration example
224
- websocket.onmessage = async (event) => {
225
- const data = new Uint8Array(event.data);
226
- const messages = await parser.parseBytes(data);
227
-
228
- messages.forEach(msg => {
229
- switch (msg.message_name) {
230
- case 'HEARTBEAT':
231
- updateConnectionStatus(msg.payload);
232
- break;
233
- case 'GPS_RAW_INT':
234
- updatePosition(msg.payload);
235
- break;
236
- case 'ATTITUDE':
237
- updateAttitude(msg.payload);
238
- break;
239
- }
240
- });
241
- };
337
+ ### Message Filtering and Routing
242
338
 
243
- // Using pre-generated types with parser
244
- function processMessage(msg: MAVLinkMessage) {
339
+ ```typescript
340
+ function processMessage(msg: ParsedMAVLinkMessage) {
245
341
  switch (msg.message_name) {
246
342
  case 'HEARTBEAT':
247
- // Type-safe access with CommonTypes
248
- const heartbeat = msg.payload as CommonTypes.MessageHeartbeat;
249
- console.log(`System type: ${heartbeat.type}`);
343
+ updateSystemStatus(msg.system_id, msg.payload);
250
344
  break;
251
345
  case 'GPS_RAW_INT':
252
- const gps = msg.payload as CommonTypes.MessageGpsRawInt;
253
- console.log(`Lat: ${gps.lat / 1e7}, Lon: ${gps.lon / 1e7}`);
346
+ updatePosition(msg.payload.lat / 1e7, msg.payload.lon / 1e7);
347
+ break;
348
+ case 'ATTITUDE':
349
+ updateAttitude(msg.payload.roll, msg.payload.pitch, msg.payload.yaw);
350
+ break;
351
+ case 'VFR_HUD':
352
+ updateHUD(msg.payload);
353
+ break;
354
+ case 'STATUSTEXT':
355
+ displayStatusMessage(msg.payload.text, msg.payload.severity);
254
356
  break;
255
357
  }
256
358
  }
257
359
  ```
258
360
 
361
+ ### Error Handling and Recovery
362
+
363
+ ```typescript
364
+ try {
365
+ const messages = parser.parseBytes(incomingData);
366
+ messages.forEach(processMessage);
367
+ } catch (error) {
368
+ console.error('Parse error:', error.message);
369
+
370
+ // Reset parser buffer if needed
371
+ parser.resetBuffer();
372
+
373
+ // Implement reconnection logic
374
+ scheduleReconnect();
375
+ }
376
+ ```
377
+
378
+ ## Robustness & Features
379
+
380
+ ### Parser Robustness
381
+ - **Fixed array decoding** - Proper handling of `uint8_t[8]` arrays without double nesting
382
+ - **Graceful degradation** - Missing fields get sensible default values
383
+ - **Protocol version detection** - Automatic MAVLink v1/v2 detection
384
+ - **Frame synchronization** - Finds valid frames in noisy data streams
385
+ - **Buffer management** - Handles partial frames across data chunks
386
+ - **Memory efficient** - Reuses buffers, minimal allocations
387
+
388
+ ### Decoder Features
389
+ - **All MAVLink types** - Support for `uint8_t`, `int32_t`, `float`, `double`, `char[N]`, arrays
390
+ - **Little-endian parsing** - Correct byte order handling
391
+ - **Unknown message handling** - Gracefully processes unsupported message types
392
+ - **Field validation** - Bounds checking and safe defaults
393
+ - **CRC validation** - Optional checksum verification (simplified implementation)
394
+
395
+ ### Testing & Quality
396
+ - **Comprehensive tests** - 20+ test cases covering edge cases
397
+ - **Generated decoder tests** - Validates HEARTBEAT, PROTOCOL_VERSION, arrays, partial payloads
398
+ - **Frame parsing tests** - Tests v1/v2 protocols, multi-message buffers, invalid data
399
+ - **CI/CD integration** - Automated testing on builds
400
+
259
401
  ## Pre-generated Types
260
402
 
261
403
  The package includes pre-generated TypeScript types for common MAVLink dialects:
@@ -616,28 +758,36 @@ node dist/cli.js generate -i https://raw.githubusercontent.com/mavlink/mavlink/m
616
758
  │ ├── types.ts # Shared type definitions
617
759
  │ ├── generator/ # Type generation components
618
760
  │ │ ├── generator.ts # Main generator class
619
- │ │ ├── template-engine.ts # Handlebars template engine
761
+ │ │ ├── template-engine.ts # Handlebars template engine with decoder
620
762
  │ │ ├── type-converter.ts # XML to TypeScript conversion
621
763
  │ │ ├── xml-parser.ts # MAVLink XML parser
622
764
  │ │ └── batch-processor.ts # Batch processing utilities
623
- │ └── parser/ # MAVLink parsing components
624
- ├── index.ts # Parser exports
625
- ├── mavlink-parser.ts # Main parser class
626
- ├── frame-parser.ts # Frame-level parsing
627
- ├── message-decoder.ts # Message decoding
628
- ├── crc.ts # CRC calculation utilities
629
- └── types.ts # Parser type definitions
630
- ├── examples/ # Usage examples and demos
631
- │ ├── README.md # Examples documentation
632
- │ ├── basic-parser.js # Basic Node.js usage
633
- │ ├── nodejs-stream.js # Advanced streaming patterns
634
- │ ├── web-worker-example.js # Web Worker integration
635
- │ ├── webrtc-integration.html # Complete web demo
636
- │ └── test-web.html # Simple browser test
765
+ │ └── generated/ # Generated dialect parsers
766
+ └── dialects/ # Generated parsers for each dialect
767
+ ├── common/ # Common dialect parser + types
768
+ ├── ardupilotmega/ # ArduPilot dialect parser + types
769
+ ├── minimal/ # Minimal dialect parser + types
770
+ ├── standard/ # Standard dialect parser + types
771
+ └── test/ # Test dialect parser + types
637
772
  ├── tests/ # Jest test files
638
- └── dist/ # Compiled JavaScript output
773
+ │ ├── decoder.test.ts # Decoder functionality tests
774
+ │ ├── template-engine.test.ts # Template generation tests
775
+ │ ├── xml-parser.test.ts # XML parsing tests
776
+ │ └── generator.test.ts # End-to-end generation tests
777
+ ├── dist/ # Compiled JavaScript output
778
+ │ └── dialects/ # Built dialect parsers for distribution
779
+ └── examples/ # Usage examples and demos
639
780
  ```
640
781
 
782
+ ### Generated Files Per Dialect
783
+
784
+ Each dialect directory contains:
785
+ - `decoder.ts` - Parser class with parseBytes() and decode() methods
786
+ - `types.ts` - Base types and ParsedMAVLinkMessage interface
787
+ - `enums.ts` - Enum definitions and type aliases
788
+ - `messages.ts` - Message interfaces and type guards
789
+ - `index.ts` - Main export file
790
+
641
791
  ## License
642
792
 
643
793
  MIT