Files
slmm/migrate_revert_field_names.py
serversdwn 1fb786c262 Fix NL43 DRD field mapping to match official specification
Corrected the parsing of NL43 DRD (Dynamic Range Data) and DOD (Data On Demand)
responses according to the NL43 Communications Guide. The previous implementation
incorrectly mapped d0 (counter field) as a measurement.

Changes:
- Updated DRD/DOD parsing to skip d0 (counter: 1-600)
- Correctly map d1-d5 to lp/leq/lmax/lmin/lpeak measurements
- Added inline documentation referencing DRD format specification
- Included database migration script to revert incorrect field names

DRD format per NL43 spec:
- d0 = counter (1-600) - NOT a measurement
- d1 = Lp (instantaneous sound pressure level)
- d2 = Leq (equivalent continuous sound level)
- d3 = Lmax (maximum level)
- d4 = Lmin (minimum level)
- d5 = Lpeak (peak level)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-07 03:42:26 +00:00

117 lines
3.6 KiB
Python

#!/usr/bin/env python3
"""
Migration script to revert NL43 measurement field names back to correct DRD format.
The previous migration was incorrect. According to NL43 DRD documentation:
- d0 = counter (1-600) - NOT a measurement!
- d1 = Lp (instantaneous sound pressure level)
- d2 = Leq (equivalent continuous sound level)
- d3 = Lmax (maximum level)
- d4 = Lmin (minimum level)
- d5 = Lpeak (peak level)
Changes:
- laeq -> lp (was incorrectly mapped to counter field!)
- lae -> leq
- lasmax -> lmax
- lasmin -> lmin
- lapeak -> lpeak
"""
import sqlite3
import sys
from pathlib import Path
def migrate_database(db_path: str):
"""Revert database schema to correct DRD field names."""
print(f"Reverting database migration: {db_path}")
# Connect to database
conn = sqlite3.connect(db_path)
cur = conn.cursor()
try:
# Check if migration is needed
cur.execute("PRAGMA table_info(nl43_status)")
columns = [row[1] for row in cur.fetchall()]
if 'lp' in columns:
print("✓ Database already has correct field names")
return
if 'laeq' not in columns:
print("✗ Database schema does not match expected format")
sys.exit(1)
print("Starting revert migration...")
# Create new table with correct column names
cur.execute("""
CREATE TABLE nl43_status_new (
unit_id VARCHAR PRIMARY KEY,
last_seen DATETIME,
measurement_state VARCHAR,
lp VARCHAR,
leq VARCHAR,
lmax VARCHAR,
lmin VARCHAR,
lpeak VARCHAR,
battery_level VARCHAR,
power_source VARCHAR,
sd_remaining_mb VARCHAR,
sd_free_ratio VARCHAR,
raw_payload TEXT
)
""")
print("✓ Created new table with correct DRD field names")
# Copy data from old table to new table
# Note: laeq was incorrectly mapped to d0 (counter), so we discard it
# The actual measurements start from d1
cur.execute("""
INSERT INTO nl43_status_new
(unit_id, last_seen, measurement_state, lp, leq, lmax, lmin, lpeak,
battery_level, power_source, sd_remaining_mb, sd_free_ratio, raw_payload)
SELECT
unit_id, last_seen, measurement_state, lae, lasmax, lasmin, lapeak, NULL,
battery_level, power_source, sd_remaining_mb, sd_free_ratio, raw_payload
FROM nl43_status
""")
rows_copied = cur.rowcount
print(f"✓ Copied {rows_copied} rows (note: discarded incorrect 'laeq' counter field)")
# Drop old table
cur.execute("DROP TABLE nl43_status")
print("✓ Dropped old table")
# Rename new table
cur.execute("ALTER TABLE nl43_status_new RENAME TO nl43_status")
print("✓ Renamed new table to nl43_status")
# Commit changes
conn.commit()
print("✓ Revert migration completed successfully")
print("\nNote: The 'lp' field will be populated correctly on next device measurement")
except Exception as e:
conn.rollback()
print(f"✗ Migration failed: {e}")
sys.exit(1)
finally:
conn.close()
if __name__ == "__main__":
# Default database path
db_path = Path(__file__).parent / "data" / "slmm.db"
# Allow custom path as command line argument
if len(sys.argv) > 1:
db_path = Path(sys.argv[1])
if not db_path.exists():
print(f"✗ Database not found: {db_path}")
sys.exit(1)
migrate_database(str(db_path))