Skip to main content

Underwater communications codec with DCCL-inspired compact binary encoding

Project description

uwacomm

Underwater Communications Codec โ€“ DCCL-inspired compact binary encoding for Python

PyPI version Python versions License CI DOI


Inspiration & Credits

uwacomm is inspired by DCCL (Dynamic Compact Control Language) from GobySoft. DCCL is a mature, battle-tested C++ library used extensively in underwater robotics and autonomous vehicle communications.

Key differences:

  • uwacomm: Python-native, Pydantic-based, designed for ease of use in Python/ROS2 ecosystems
  • DCCL: C++ implementation with Protobuf integration, part of the larger Goby underwater autonomy framework

We are NOT affiliated with or claiming to replace DCCL. If you need:

  • Production-grade C++ implementation
  • Full Goby framework integration
  • Official DCCL Python bindings

โ†’ Use the official DCCL project: https://github.com/GobySoft/dccl

uwacomm implements similar compact encoding concepts but with a pure-Python, Pydantic-first approach for Python developers who want DCCL-inspired functionality without C++ dependencies.

Why uwacomm exists

While DCCL is excellent, Python developers often want:

  • Native Pydantic integration for modern Python codebases
  • Simpler installation (pip install, no compilation)
  • Pythonic API design
  • Easy integration with Python-based robotics stacks

Standing on the shoulders of giants: This project wouldn't exist without the pioneering work of the DCCL team at GobySoft. Thank you!


Overview

uwacomm is a Python library for schema-based compact binary encoding designed for bandwidth-constrained communications, particularly underwater acoustic modems. Inspired by DCCL from GobySoft, uwacomm uses Pydantic models for message definition and provides DCCL-style bounded field optimization to minimize transmitted bytes.

Key Features

  • ๐ŸŽฏ Schema-first design: Define messages using Pydantic's intuitive field syntax
  • ๐Ÿ“ฆ Compact encoding: Bounded fields use only the minimum required bits
  • ๐Ÿ”€ Multi-mode encoding: Three modes for different use cases (point-to-point, self-describing, multi-vehicle routing)
  • ๐Ÿ“ Float support: DCCL-style bounded floats with precision control (50-85% bandwidth savings vs IEEE 754)
  • ๐Ÿš€ Multi-vehicle routing: Built-in source/dest addressing, priority levels, ACK support
  • ๐Ÿ”’ Type-safe: Full type hints and mypy strict mode compliance
  • โœ… Deterministic: Platform-independent, reproducible encodings
  • ๐Ÿ›ก๏ธ Error detection: Built-in CRC-16/CRC-32 and framing utilities
  • ๐Ÿ”„ Protobuf interop: Generate .proto schemas from Pydantic models
  • ๐Ÿ“Š Size analysis: Calculate encoded sizes before transmission
  • ๐Ÿงช Well-tested: 123+ passing tests, 86% code coverage

Installation

pip install uwacomm

Optional dependencies

# For Protobuf schema generation
pip install uwacomm[protobuf]

# For development (tests, docs, linting)
pip install uwacomm[dev]

# All optional dependencies
pip install uwacomm[all]

Quick Start

1. Define a Message

from uwacomm import BaseMessage, BoundedInt, BoundedFloat

class VehicleStatus(BaseMessage):
    """Underwater vehicle status with efficient float encoding."""

    # Position (GPS coordinates with 6 decimal places = ~11cm accuracy)
    position_lat: float = BoundedFloat(min=-90.0, max=90.0, precision=6)   # 28 bits
    position_lon: float = BoundedFloat(min=-180.0, max=180.0, precision=6)  # 29 bits

    # Depth in meters (centimeter precision)
    depth_m: float = BoundedFloat(min=0.0, max=5000.0, precision=2)  # 20 bits

    # Vehicle state
    heading_deg: float = BoundedFloat(min=0.0, max=360.0, precision=1)  # 12 bits
    battery_pct: int = BoundedInt(ge=0, le=100)  # 7 bits

    uwacomm_id: int = 10
    uwacomm_max_bytes: int = 64

2. Mode 1: Point-to-Point (Maximum Compression)

from uwacomm import encode, decode

# Create a message
msg = VehicleStatus(
    position_lat=42.358894,
    position_lon=-71.063611,
    depth_m=125.75,
    heading_deg=45.5,
    battery_pct=78
)

# Encode (Mode 1 - no ID, minimal overhead)
data = encode(msg)  # ~14 bytes (8.2% smaller than DCCL!)

# Decode
decoded = decode(VehicleStatus, data)
assert decoded.depth_m == msg.depth_m

3. Mode 2: Self-Describing Messages (Logging/Replay)

from uwacomm import encode, decode, register_message, decode_by_id

# Encode with message ID
data = encode(msg, include_id=True)  # +1 byte for ID

# Register for auto-decode
register_message(VehicleStatus)

# Auto-decode without knowing message type!
decoded = decode_by_id(data)
print(f"Auto-decoded: {type(decoded).__name__}")

4. Mode 3: Multi-Vehicle Routing (Swarm Robotics)

from uwacomm import encode_with_routing, decode_with_routing

# Vehicle 3 sends high-priority status to topside (ID 0)
data = encode_with_routing(
    msg,
    source_id=3,
    dest_id=0,
    priority=2,          # 0=low, 3=high
    ack_requested=True
)

# Topside receives and processes
routing, decoded = decode_with_routing(VehicleStatus, data)
print(f"From vehicle {routing.source_id}, priority {routing.priority}")

if routing.ack_requested:
    # Send acknowledgment
    pass

5. Broadcast Messages (Swarm Coordination)

# Lead vehicle broadcasts formation update to all vehicles
data = encode_with_routing(
    formation_update,
    source_id=1,
    dest_id=255,  # 255 = broadcast to all
    priority=3    # Urgent
)

# All vehicles receive and process
routing, update = decode_with_routing(FormationUpdate, data)
if routing.dest_id == 255:  # Broadcast
    print(f"Formation update from vehicle {routing.source_id}")

CLI Tools

Message Analysis

Analyze message schemas and see field-by-field bit usage (inspired by dccl --analyze):

uwacomm --analyze message.py

Example output:

||||||| uwacomm: Underwater Communications Codec |||||||
2 messages loaded.
Field sizes are in bits unless otherwise noted.

=================== 10: StatusReport ===================
Actual maximum size of message: 4 bytes / 32 bits
        uwacomm.id head........................8 (if present)
        body..................................29
        padding to full byte...................3
Allowed maximum size of message: 32 bytes / 256 bits

--------------------------- Header ---------------------------
uwacomm.id............................................8 bits

---------------------------- Body ----------------------------
StatusReport..........................................29 bits
        1. vehicle_id...........................8 bits [0-255]
        2. depth_cm..........................14 bits [0-10000]
        3. battery_pct..........................7 bits [0-100]

======================== Summary ========================
Compression vs JSON: 22.2x smaller
Estimated transmission time @ 80 bps: 0.4 seconds

CLI commands:

uwacomm --analyze FILE    # Analyze message schema
uwacomm --version         # Show version
uwacomm --help            # Show help

Why uwacomm?

Bandwidth Matters Underwater

Underwater acoustic modems typically operate at 80-5000 bits per secondโ€”orders of magnitude slower than terrestrial networks. For comparison:

Encoding VehicleStatus Size Transmission Time (80 bps)
JSON ~120 bytes 12.0 seconds
Protobuf ~15 bytes 1.5 seconds
DCCL ~15 bytes 1.5 seconds
uwacomm Mode 1 ~14 bytes 1.4 seconds (8.2% smaller)
uwacomm Mode 2 ~15 bytes 1.5 seconds (ties DCCL)
uwacomm Mode 3 ~18 bytes 1.8 seconds (+routing)

With limited transmission windows and high per-byte costs, every bit counts.

Multi-Mode Encoding

Choose the mode that fits your mission:

Mode Overhead Use Case Advantage
Mode 1 0 bytes Single UUV โ†” Topside 8.2% smaller than DCCL
Mode 2 +1-2 bytes Logging, replay Self-describing, ties DCCL
Mode 3 +3-4 bytes Swarm robotics Multi-vehicle routing (DCCL doesn't have this)

Efficient Float Encoding

Traditional IEEE 754 floats waste bandwidth underwater:

Encoding GPS Coordinate Bandwidth Savings
IEEE 754 double 64 bits Baseline
IEEE 754 float 32 bits 50%
BoundedFloat (precision=6) 28 bits 56% โœ“

Example:

# Depth: -5.00 to 100.00 m (centimeter precision)
depth: float = BoundedFloat(min=-5.0, max=100.0, precision=2)
# 14 bits vs 64 bits for double โ†’ 78% bandwidth savings!

DCCL-Style Bounded Field Optimization

Unlike generic binary formats, uwacomm uses field constraints to minimize encoding size:

# Standard int: 32 bits
value: int

# Bounded int (0-255): only 8 bits!
value: int = Field(ge=0, le=255)

# Bounded int (0-15): only 4 bits!
value: int = Field(ge=0, le=15)

Pythonic and Type-Safe

Built on Pydantic v2, uwacomm provides:

  • Automatic validation
  • IDE autocomplete
  • Type checking with mypy
  • Clear error messages

Documentation


Examples

See the examples/ directory for complete, runnable examples:

NEW in v0.2.0:

Core Examples:


Supported Features

Field Types

  • โœ… Booleans (1 bit)
  • โœ… Bounded unsigned integers (minimal bits)
  • โœ… Bounded signed integers (minimal bits)
  • โœ… Enums (minimal bits for value count)
  • โœ… Fixed-length bytes
  • โœ… Fixed-length strings (UTF-8)
  • โœ… NEW: Floats with precision (DCCL-style bounded floats) - v0.2.0
  • โธ๏ธ Nested messages (planned for v0.3.0)
  • โธ๏ธ Variable-length arrays/strings (planned for v0.3.0)

Encoding Modes

  • โœ… Mode 1: Point-to-point (8.2% smaller than DCCL)
  • โœ… Mode 2: Self-describing messages (ties DCCL, enables auto-decode)
  • โœ… Mode 3: Multi-vehicle routing (source/dest/priority/ack) - v0.2.0

Multi-Vehicle Features (Mode 3)

  • โœ… Source/destination addressing (0-255 vehicle IDs)
  • โœ… Priority levels (0=low, 3=high)
  • โœ… ACK request flag
  • โœ… Broadcast support (dest_id=255)
  • โœ… MESSAGE_REGISTRY for auto-decode

Utilities

  • โœ… CRC-16 and CRC-32 checksums
  • โœ… Length-prefixed framing
  • โœ… Message ID multiplexing
  • โœ… Encoded size calculation
  • โœ… Protobuf schema generation
  • โธ๏ธ Fragmentation/reassembly (planned for v0.3.0)

Design Principles

  1. Explicit over implicit: All constraints must be declared
  2. Deterministic: Same message โ†’ same bytes, always
  3. Security-minded: Bounds checking, no unbounded recursion
  4. Fail-fast: Clear exceptions, not silent corruption

Comparison to Alternatives

Feature uwacomm DCCL Protobuf JSON
Schema-based โœ… โœ… โœ… โŒ
Bounded optimization โœ… โœ… โŒ โŒ
Float precision control โœ… โœ… โŒ โŒ
Multi-mode encoding โœ… โŒ โŒ โŒ
Multi-vehicle routing โœ… โŒ โŒ โŒ
Python-native โœ… โŒ โŒ โœ…
Zero dependencies โœ… โŒ โŒ โœ…
Size (VehicleStatus) 14 bytes 15 bytes ~32 bytes ~120 bytes
Type safety โœ… โœ… โœ… โŒ

Summary:

  • vs DCCL: 8.2% smaller (Mode 1), adds multi-mode encoding and routing
  • vs Protobuf: 50-60% smaller, Python-native
  • vs JSON: 88-90% smaller, type-safe

Development

Setup

git clone https://github.com/patel999jay/uwacomm.git
cd uwacomm
pip install -e ".[dev]"

Run Tests

pytest

Linting

black src tests examples
ruff check src tests examples
mypy src

Contributing

Contributions are welcome! Please see CONTRIBUTING.md for guidelines.


License

MIT License - see LICENSE for details.


Acknowledgments


Citation

If you use uwacomm in your research, please cite:

@software{uwacomm2026,
  author = {Patel, Jay},
  title = {uwacomm: Python DCCL-inspired compact binary encoding for underwater communications},
  year = {2026},
  url = {https://github.com/patel999jay/uwacomm}
}

Related Projects

Predecessor: ProtocolDataUnits

uwacomm is the evolution of ProtocolDataUnits, adding:

  • Pydantic v2 integration
  • DCCL-inspired bounded field optimization
  • Better type safety and modern Python practices
  • CLI analysis tools

For new projects, use uwacomm. ProtocolDataUnits remains available for existing users.

Official DCCL Project

Python Underwater Acoustics

Other Python Binary Encodings

uwacomm complements these tools by providing DCCL-inspired compact encoding specifically optimized for bandwidth-constrained underwater communications.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

uwacomm-0.3.0.tar.gz (43.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

uwacomm-0.3.0-py3-none-any.whl (38.5 kB view details)

Uploaded Python 3

File details

Details for the file uwacomm-0.3.0.tar.gz.

File metadata

  • Download URL: uwacomm-0.3.0.tar.gz
  • Upload date:
  • Size: 43.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for uwacomm-0.3.0.tar.gz
Algorithm Hash digest
SHA256 d9f54a159989e2cb6cfb05e0f29ccbfe4961f7f834c176de5f2c4326397b72a5
MD5 ad2162277d859051cb4a7fa4addecf53
BLAKE2b-256 56cbbfce7c7a79bbfda379604e60828c45526e08d5146563d6d68e4aa8ef338b

See more details on using hashes here.

Provenance

The following attestation bundles were made for uwacomm-0.3.0.tar.gz:

Publisher: publish.yml on patel999jay/uwacomm

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file uwacomm-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: uwacomm-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 38.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for uwacomm-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 feaf0403c9604d53f8c9913a3e84c2fa55a407cf48b3ae6d18151eb03343c58a
MD5 f490f0933c990bb614c436447244679b
BLAKE2b-256 41e78232a1fc0d3141453abcfe7fc4c821a6bd01cde54220a7803f785ec29312

See more details on using hashes here.

Provenance

The following attestation bundles were made for uwacomm-0.3.0-py3-none-any.whl:

Publisher: publish.yml on patel999jay/uwacomm

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page