Files
venus/axiom-nmea/debug/debug_decode.py
dev 9756538f16 Initial commit: Venus OS boat addons monorepo
Organizes 11 projects for Cerbo GX/Venus OS into a single repository:
- axiom-nmea: Raymarine LightHouse protocol decoder
- dbus-generator-ramp: Generator current ramp controller
- dbus-lightning: Blitzortung lightning monitor
- dbus-meteoblue-forecast: Meteoblue weather forecast
- dbus-no-foreign-land: noforeignland.com tracking
- dbus-tides: Tide prediction from depth + harmonics
- dbus-vrm-history: VRM cloud history proxy
- dbus-windy-station: Windy.com weather upload
- mfd-custom-app: MFD app deployment package
- venus-html5-app: Custom Victron HTML5 app fork
- watermaker: Watermaker PLC control UI

Adds root README, .gitignore, project template, and per-project
.gitignore files. Sensitive config files excluded via .gitignore
with .example templates provided.

Made-with: Cursor
2026-03-16 17:04:16 +00:00

97 lines
2.9 KiB
Python

#!/usr/bin/env python3
"""Debug the full decode process."""
import struct
from collections import Counter
def decode_float(data, offset):
if offset + 4 > len(data):
return None
try:
return struct.unpack('<f', data[offset:offset+4])[0]
except:
return None
def read_pcap(filename):
packets = []
with open(filename, 'rb') as f:
header = f.read(24)
magic = struct.unpack('<I', header[0:4])[0]
swapped = magic == 0xd4c3b2a1
endian = '>' if swapped else '<'
while True:
pkt_header = f.read(16)
if len(pkt_header) < 16:
break
ts_sec, ts_usec, incl_len, orig_len = struct.unpack(f'{endian}IIII', pkt_header)
pkt_data = f.read(incl_len)
if len(pkt_data) < incl_len:
break
if len(pkt_data) > 42 and pkt_data[12:14] == b'\x08\x00':
ip_header_len = (pkt_data[14] & 0x0F) * 4
payload_start = 14 + ip_header_len + 8
if payload_start < len(pkt_data):
packets.append(pkt_data[payload_start:])
return packets
packets = read_pcap("raymarine_sample.pcap")
# Count packet sizes
size_counts = Counter(len(p) for p in packets)
print("Packet size distribution:")
for size, count in sorted(size_counts.items(), key=lambda x: -x[1])[:15]:
print(f" {size:5d} bytes: {count:4d} packets")
print("\n" + "="*60)
print("Simulating wind extraction logic:")
print("="*60)
last_speed = None
last_dir = None
extractions = 0
for pkt in packets:
pkt_len = len(pkt)
# Same logic as decoder
if 340 <= pkt_len <= 350:
offset_pairs = [(0x00a5, 0x00a0), (0x00c3, 0x00a0), (0x00c8, 0x00a0)]
elif 440 <= pkt_len <= 500:
offset_pairs = [(0x00ac, 0x00a7), (0x00ca, 0x00a7), (0x00b1, 0x00a7)]
elif 780 <= pkt_len <= 1100:
offset_pairs = [(0x00ca, 0x00c5), (0x00e8, 0x0090), (0x00cf, 0x00c5)]
elif 1400 <= pkt_len <= 1500:
offset_pairs = [(0x0101, 0x00fc), (0x0106, 0x00fc), (0x011f, 0x00fc)]
else:
offset_pairs = [(0x00ca, 0x00c5), (0x00a5, 0x00a0)]
for speed_offset, dir_offset in offset_pairs:
if speed_offset + 4 > pkt_len or dir_offset + 4 > pkt_len:
continue
speed_val = decode_float(pkt, speed_offset)
dir_val = decode_float(pkt, dir_offset)
if speed_val is None or dir_val is None:
continue
# Validate
if not (0 < speed_val < 60):
continue
if not (0 <= dir_val <= 6.5):
continue
speed_kts = speed_val * 1.94384
dir_deg = (dir_val * 57.2958) % 360
last_speed = speed_kts
last_dir = dir_deg
extractions += 1
break
print(f"\nTotal successful extractions: {extractions}")
print(f"Last wind speed: {last_speed:.1f} kts" if last_speed else "No speed")
print(f"Last wind direction: {last_dir:.1f}°" if last_dir else "No direction")