aee0f09db8
- Datafabrik: Dockerfile fix, agentorkestrering fungerar - Vision: Identify-modell, FAISS, OCR alla testade - API: Alla 7 integrationstester passerade - Upplösare: Entitetsupplösning verifierad
124 lines
3.7 KiB
Python
124 lines
3.7 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
ObservationStore - Sparar och hämtar observationer
|
|
"""
|
|
import sqlite3
|
|
import json
|
|
from datetime import datetime
|
|
from pathlib import Path
|
|
|
|
DB_PATH = "/home/bernt/.openclaw/workspace/rivp-pilot-1/rivp.db"
|
|
RAW_DIR = Path("/home/bernt/.openclaw/workspace/life-weather/raw")
|
|
RAW_DIR.mkdir(exist_ok=True)
|
|
|
|
class ObservationStore:
|
|
def __init__(self, db_path=DB_PATH):
|
|
self.db_path = db_path
|
|
self._init_db()
|
|
|
|
def _init_db(self):
|
|
"""Initiera databasen"""
|
|
conn = sqlite3.connect(self.db_path)
|
|
c = conn.cursor()
|
|
|
|
# Huvudtabell för väderobservationer
|
|
c.execute('''
|
|
CREATE TABLE IF NOT EXISTS weather_observations (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
road_id INTEGER,
|
|
station_id TEXT,
|
|
observation_type TEXT,
|
|
value REAL,
|
|
unit TEXT,
|
|
timestamp TEXT,
|
|
raw_data TEXT,
|
|
source TEXT,
|
|
created_at TEXT
|
|
)
|
|
''')
|
|
|
|
# Index för snabbare sökning
|
|
c.execute('''
|
|
CREATE INDEX IF NOT EXISTS idx_weather_road
|
|
ON weather_observations(road_id, timestamp)
|
|
''')
|
|
|
|
conn.commit()
|
|
conn.close()
|
|
|
|
def save_raw_data(self, weather_data, filename=None):
|
|
"""Spara rådata oförändrad"""
|
|
if filename is None:
|
|
filename = f"weather_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json"
|
|
|
|
filepath = RAW_DIR / filename
|
|
with open(filepath, 'w') as f:
|
|
json.dump(weather_data, f, indent=2)
|
|
|
|
return filepath
|
|
|
|
def save_observation(self, road_id, observation_type, value, unit, timestamp, raw_data, source="smhi"):
|
|
"""Spara normaliserad observation"""
|
|
conn = sqlite3.connect(self.db_path)
|
|
c = conn.cursor()
|
|
|
|
# Idempotent - kolla om observation redan finns
|
|
c.execute('''
|
|
SELECT id FROM weather_observations
|
|
WHERE road_id = ? AND observation_type = ? AND timestamp = ?
|
|
''', (road_id, observation_type, timestamp))
|
|
|
|
if c.fetchone():
|
|
conn.close()
|
|
return None # Redan sparad
|
|
|
|
c.execute('''
|
|
INSERT INTO weather_observations
|
|
(road_id, station_id, observation_type, value, unit, timestamp, raw_data, source, created_at)
|
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
''', (
|
|
road_id,
|
|
"97530", # Uppsala station
|
|
observation_type,
|
|
value,
|
|
unit,
|
|
timestamp,
|
|
json.dumps(raw_data),
|
|
source,
|
|
datetime.now().isoformat()
|
|
))
|
|
|
|
obs_id = c.lastrowid
|
|
conn.commit()
|
|
conn.close()
|
|
|
|
return obs_id
|
|
|
|
def get_latest_for_road(self, road_id, observation_type=None):
|
|
"""Hämta senaste observation för väg"""
|
|
conn = sqlite3.connect(self.db_path)
|
|
c = conn.cursor()
|
|
|
|
if observation_type:
|
|
c.execute('''
|
|
SELECT * FROM weather_observations
|
|
WHERE road_id = ? AND observation_type = ?
|
|
ORDER BY timestamp DESC LIMIT 1
|
|
''', (road_id, observation_type))
|
|
else:
|
|
c.execute('''
|
|
SELECT * FROM weather_observations
|
|
WHERE road_id = ?
|
|
ORDER BY timestamp DESC LIMIT 1
|
|
''', (road_id,))
|
|
|
|
row = c.fetchone()
|
|
conn.close()
|
|
|
|
return row
|
|
|
|
if __name__ == "__main__":
|
|
store = ObservationStore()
|
|
print("ObservationStore initierad")
|
|
print(f"Rådata sparas i: {RAW_DIR}")
|