NMEA telemetry recorder for Nortek ADCP instruments with DuckDB backend
Project description
ADCP Recorder
ADCP Recorder is a production-ready NMEA telemetry recorder for Nortek ADCP (Acoustic Doppler Current Profiler) instruments with a DuckDB backend. It provides reliable, high-performance data collection with comprehensive parsing, validation, and storage capabilities.
Features
- ✅ Asynchronous Serial Communication - Non-blocking serial port polling with automatic reconnection
- ✅ NMEA Protocol Support - Full checksum validation and frame parsing for 21+ message types
- ✅ DuckDB Persistence - Embedded database with timestamped raw lines and parsed data
- ✅ Graceful Signal Handling - Clean shutdown on SIGTERM/SIGINT
- ✅ Health Monitoring - Built-in health checks with optional webhook alerting
- ✅ Binary Data Detection - Separate error logging for non-NMEA data
- ✅ Daily File Export - Automatic CSV export per message type
- ✅ Cross-Platform - Full support for Linux and Windows
- ✅ Service Integration - Systemd (Linux) and Windows Service support
- ✅ Production Ready - Comprehensive testing, logging, and error handling
Supported NMEA Message Types
Configuration: PNORI, PNORI1, PNORI2
Sensor Data: PNORS, PNORS1, PNORS2, PNORS3, PNORS4
Current Velocity: PNORC, PNORC1, PNORC2, PNORC3, PNORC4
Headers: PNORH3, PNORH4
Additional: PNORA, PNORW, PNORB, PNORE, PNORF, PNORWD
Quick Start
Installation
# Install from PyPI (recommended)
pip install adcp-recorder
# Or install from source
git clone https://github.com/your-org/adcp-recorder.git
cd adcp-recorder
pip install .
Basic Usage
# List available serial ports
adcp-recorder list-ports
# Configure the recorder
adcp-recorder configure --port /dev/ttyUSB0 --baud 9600 --output ~/adcp_data
# Check configuration
adcp-recorder status
# Start recording
adcp-recorder start
Press Ctrl+C to stop the recorder.
Documentation
User Guides
- Installation Guide - Complete installation instructions for Linux and Windows
- Configuration Guide - Detailed configuration options and examples
- Usage Guide - CLI commands, workflows, and best practices
- Examples - Practical examples and common scenarios
Deployment
- Deployment Guide - Production deployment, service setup, and maintenance
Technical Documentation
- Architecture Overview - System design and components
- NMEA Protocol - NMEA sentence format and validation
- Message Specifications - Detailed specs for all message types
- Implementation Guides - Parser patterns and database schemas
Complete Documentation
Browse the full documentation at docs/README.md
System Requirements
- Python: 3.9 or higher
- Operating System: Linux (Ubuntu 20.04+, Debian 11+, RHEL 8+) or Windows 10/11
- RAM: 512 MB minimum, 1 GB recommended
- Disk Space: 100 MB for application, additional space for data storage
- Serial Port: USB-to-serial adapter or native serial port
Installation Methods
Method 1: PyPI (Recommended for Production)
pip install adcp-recorder
Method 2: From Source
git clone https://github.com/your-org/adcp-recorder.git
cd adcp-recorder
pip install .
Method 3: Development Installation
git clone https://github.com/your-org/adcp-recorder.git
cd adcp-recorder
pip install -e ".[dev]"
pytest # Run tests
Production Deployment
Linux (Systemd Service)
# Automated installation
sudo ./scripts/install-linux.sh
# Or manual installation
sudo cp adcp_recorder/templates/linux/adcp-recorder.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable adcp-recorder
sudo systemctl start adcp-recorder
Windows (Windows Service)
REM Automated installation (run as Administrator)
install-windows.bat
REM Or manual service installation
python -m adcp_recorder.service.win_service install
sc config adcp-recorder start= auto
sc start adcp-recorder
See Deployment Guide for complete instructions.
CLI Commands
# List available serial ports
adcp-recorder list-ports
# Configure settings
adcp-recorder configure [OPTIONS]
--port TEXT Serial port device
--baud INTEGER Baud rate
--output TEXT Output directory
--debug/--no-debug Enable/disable debug logging
# Show current status
adcp-recorder status
# Start recording
adcp-recorder start
# Generate service templates
adcp-recorder generate-service --platform {linux|windows}
Data Access
Database Queries
# Connect to database
duckdb ~/adcp_data/adcp.duckdb
# Query examples
SELECT COUNT(*) FROM raw_lines;
SELECT * FROM pnors ORDER BY timestamp DESC LIMIT 10;
SELECT AVG(temperature) FROM pnors WHERE temperature IS NOT NULL;
CSV Files
Daily CSV files are automatically exported to {output_dir}/{MESSAGE_TYPE}/{YYYY-MM-DD}.csv
# View today's sensor data
cat ~/adcp_data/PNORS/$(date +%Y-%m-%d).csv
Development
Running Tests
# Install development dependencies
pip install -e ".[dev]"
# Run all tests
pytest
# Run with coverage
pytest --cov=adcp_recorder --cov-report=html
# Run specific test file
pytest adcp_recorder/tests/test_nmea.py
Code Quality
# Linting (using ruff)
ruff check adcp_recorder/
# Type checking
mypy adcp_recorder/
# Code formatting
ruff format adcp_recorder/
Building Distribution
# Build package
./scripts/build.sh
# This will:
# - Run tests
# - Generate coverage reports
# - Build wheel and source distributions
# - Generate checksums
Architecture
┌─────────────────────────────────────────────────────────┐
│ ADCP Recorder │
├─────────────────────────────────────────────────────────┤
│ │
│ Serial Port → Producer → Queue → Consumer │
│ ↓ │
│ Message Router │
│ ↓ │
│ ┌────────┴────────┐ │
│ ↓ ↓ │
│ DuckDB Database CSV Files│
│ │
└─────────────────────────────────────────────────────────┘
See Architecture Overview for details.
Configuration
Configuration is stored in ~/.adcp-recorder/config.json:
{
"serial_port": "/dev/ttyUSB0",
"baudrate": 9600,
"timeout": 1.0,
"output_dir": "/home/user/adcp_data",
"log_level": "INFO",
"db_path": null
}
Environment variables can override configuration:
export ADCP_RECORDER_SERIAL_PORT=/dev/ttyUSB1
export ADCP_RECORDER_BAUDRATE=115200
export ADCP_RECORDER_OUTPUT_DIR=/data/adcp
See Configuration Guide for all options.
Monitoring
Service Status
# Linux
sudo systemctl status adcp-recorder
sudo journalctl -u adcp-recorder -f
# Windows
sc query adcp-recorder
Get-EventLog -LogName Application -Source adcp-recorder -Newest 20
Health Checks
# Check data collection rate
duckdb ~/adcp_data/adcp.duckdb \
"SELECT COUNT(*) FROM raw_lines WHERE timestamp > NOW() - INTERVAL 5 MINUTES"
# Check for errors
duckdb ~/adcp_data/adcp.duckdb \
"SELECT * FROM errors ORDER BY timestamp DESC LIMIT 10"
Troubleshooting
Common Issues
Serial port permission denied (Linux):
sudo usermod -a -G dialout $USER
# Log out and log back in
Service won't start:
# Check logs
sudo journalctl -u adcp-recorder -n 50
# Verify configuration
adcp-recorder status
# Test manually
adcp-recorder start
No data being collected:
# Enable debug logging
adcp-recorder configure --debug
adcp-recorder start
# Check serial port
adcp-recorder list-ports
See Usage Guide for more troubleshooting.
Contributing
Contributions are welcome! Please follow these guidelines:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Make your changes
- Run tests (
pytest) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Development Setup
git clone https://github.com/your-org/adcp-recorder.git
cd adcp-recorder
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
pip install -e ".[dev]"
pytest
License
This project is licensed under the MIT License - see the LICENSE file for details.
Support
- Documentation: docs/README.md
- Issues: GitHub Issues
- Discussions: GitHub Discussions
Acknowledgments
- Nortek for ADCP instruments and NMEA specifications
- DuckDB for the embedded database engine
- The Python community for excellent libraries
Built with ❤️ for oceanographic research and marine monitoring
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file adcp_recorder-0.1.0.tar.gz.
File metadata
- Download URL: adcp_recorder-0.1.0.tar.gz
- Upload date:
- Size: 142.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0981a01c33837509d01f9528e98367e1177591018893eb8ca2c3792d65b0a827
|
|
| MD5 |
47eee38248e5a37095f2ecb17990dd2d
|
|
| BLAKE2b-256 |
73d17aae80e9f4abb43e3c89dea9dc1a6caf170eab8787efdccea6dee070e969
|
Provenance
The following attestation bundles were made for adcp_recorder-0.1.0.tar.gz:
Publisher:
publish.yml on vpatrinica/adcp-recorder
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
adcp_recorder-0.1.0.tar.gz -
Subject digest:
0981a01c33837509d01f9528e98367e1177591018893eb8ca2c3792d65b0a827 - Sigstore transparency entry: 817309313
- Sigstore integration time:
-
Permalink:
vpatrinica/adcp-recorder@ab81cfc6d80e26fcc038dbf809c19e99cf6b458b -
Branch / Tag:
refs/heads/main - Owner: https://github.com/vpatrinica
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@ab81cfc6d80e26fcc038dbf809c19e99cf6b458b -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file adcp_recorder-0.1.0-py3-none-any.whl.
File metadata
- Download URL: adcp_recorder-0.1.0-py3-none-any.whl
- Upload date:
- Size: 63.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e0f581ab3a4daf3f2a35f293aa869b4fee8256b82b6a8225dbc5f95507d8bf02
|
|
| MD5 |
abdcbda0842e7464f2e54e63db804171
|
|
| BLAKE2b-256 |
2cd7e0feff0f4736b8a7b29440ba06c897d47c11a91e8005043776401a4d3533
|
Provenance
The following attestation bundles were made for adcp_recorder-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on vpatrinica/adcp-recorder
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
adcp_recorder-0.1.0-py3-none-any.whl -
Subject digest:
e0f581ab3a4daf3f2a35f293aa869b4fee8256b82b6a8225dbc5f95507d8bf02 - Sigstore transparency entry: 817309362
- Sigstore integration time:
-
Permalink:
vpatrinica/adcp-recorder@ab81cfc6d80e26fcc038dbf809c19e99cf6b458b -
Branch / Tag:
refs/heads/main - Owner: https://github.com/vpatrinica
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@ab81cfc6d80e26fcc038dbf809c19e99cf6b458b -
Trigger Event:
workflow_dispatch
-
Statement type: