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
84 lines
2.4 KiB
Python
84 lines
2.4 KiB
Python
#!/usr/bin/env python3
|
|
"""Compare old offsets vs new 0x006b offset for wind direction."""
|
|
|
|
import struct
|
|
from collections import defaultdict
|
|
|
|
def decode_float(data, offset):
|
|
if offset + 4 > len(data):
|
|
return None
|
|
try:
|
|
val = struct.unpack('<f', data[offset:offset+4])[0]
|
|
if val != val: # NaN check
|
|
return None
|
|
return val
|
|
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
|
|
|
|
# Current offsets from decoder
|
|
OLD_OFFSETS = {
|
|
344: 0x00a0,
|
|
446: 0x00a7,
|
|
788: 0x00c5,
|
|
888: 0x00c5,
|
|
931: 0x00c5,
|
|
1031: 0x00c5,
|
|
1472: 0x00fc,
|
|
}
|
|
|
|
NEW_OFFSET = 0x006b
|
|
|
|
for pcap_file in ["raymarine_sample.pcap", "raymarine_sample_twd_69-73.pcap"]:
|
|
print(f"\n{'='*70}")
|
|
print(f"FILE: {pcap_file}")
|
|
print("="*70)
|
|
|
|
packets = read_pcap(pcap_file)
|
|
print(f"Loaded {len(packets)} packets\n")
|
|
|
|
print(f"{'Pkt Size':<10} {'Old Offset':<12} {'Old Value':<15} {'New (0x006b)':<15}")
|
|
print("-" * 55)
|
|
|
|
for pkt_len in sorted(OLD_OFFSETS.keys()):
|
|
old_offset = OLD_OFFSETS[pkt_len]
|
|
|
|
# Find packets of this size
|
|
matching = [p for p in packets if len(p) == pkt_len]
|
|
if not matching:
|
|
continue
|
|
|
|
# Sample first packet of this size
|
|
pkt = matching[0]
|
|
|
|
old_val = decode_float(pkt, old_offset)
|
|
new_val = decode_float(pkt, NEW_OFFSET)
|
|
|
|
old_deg = f"{old_val * 57.2958:.1f}°" if old_val and 0 <= old_val <= 6.5 else "invalid"
|
|
new_deg = f"{new_val * 57.2958:.1f}°" if new_val and 0 <= new_val <= 6.5 else "invalid"
|
|
|
|
print(f"{pkt_len:<10} 0x{old_offset:04x} {old_deg:<15} {new_deg:<15}")
|