Files
boc/life-weather/pipeline_v2.py
T
Bernt aee0f09db8 landvex: Fixar och tester klara för alla komponenter
- Datafabrik: Dockerfile fix, agentorkestrering fungerar
- Vision: Identify-modell, FAISS, OCR alla testade
- API: Alla 7 integrationstester passerade
- Upplösare: Entitetsupplösning verifierad
2026-07-05 06:41:32 +00:00

237 lines
8.0 KiB
Python

#!/usr/bin/env python3
"""
Weather Intelligence Pipeline v2
Road Binding → Risk Profiles → Event Generation → Mission Engine
"""
import sys
import json
import logging
from datetime import datetime
from pathlib import Path
sys.path.insert(0, '/home/bernt/.openclaw/workspace/life-weather')
from providers.weather_provider import WeatherProvider
from storage.observation_store import ObservationStore
from engine.risk_engine import RiskEngine
LOG_DIR = Path("/home/bernt/.openclaw/workspace/life-weather/logs")
LOG_DIR.mkdir(exist_ok=True)
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler(LOG_DIR / "pipeline_v2.log"),
logging.StreamHandler()
]
)
logger = logging.getLogger(__name__)
class RoadBinding:
"""Steg 1: Koppla väg till väderobservation"""
def __init__(self, store):
self.store = store
def bind_road(self, road_id, weather_data):
"""Koppla väg till väderobservation"""
logger.info(f"Road {road_id}: Binding to weather observation")
observations = []
if weather_data.get("temperature"):
obs_id = self.store.save_observation(
road_id=road_id,
observation_type="temperature",
value=weather_data["temperature"]["value"],
unit="celsius",
timestamp=weather_data["timestamp"],
raw_data=weather_data["temperature"]
)
if obs_id:
observations.append(obs_id)
if weather_data.get("precipitation"):
obs_id = self.store.save_observation(
road_id=road_id,
observation_type="precipitation",
value=weather_data["precipitation"]["value"],
unit="mm",
timestamp=weather_data["timestamp"],
raw_data=weather_data["precipitation"]
)
if obs_id:
observations.append(obs_id)
if weather_data.get("wind"):
obs_id = self.store.save_observation(
road_id=road_id,
observation_type="wind",
value=weather_data["wind"]["value"],
unit="m/s",
timestamp=weather_data["timestamp"],
raw_data=weather_data["wind"]
)
if obs_id:
observations.append(obs_id)
return {
"road_id": road_id,
"observations": observations,
"timestamp": weather_data["timestamp"]
}
class RiskProfile:
"""Steg 2: Skapa riskprofil för väg"""
def __init__(self, engine):
self.engine = engine
def create_profile(self, road_id, road_type, weather_data):
"""Skapa riskprofil"""
logger.info(f"Road {road_id}: Creating risk profile")
temp = weather_data.get("temperature", {}).get("value") if weather_data.get("temperature") else None
precip = weather_data.get("precipitation", {}).get("value") if weather_data.get("precipitation") else None
wind = weather_data.get("wind", {}).get("value") if weather_data.get("wind") else None
risks = self.engine.calculate_risk(road_id, road_type, temp, precip, wind)
profile = {
"road_id": road_id,
"road_type": road_type,
"timestamp": weather_data["timestamp"],
"weather": {
"temperature": temp,
"precipitation": precip,
"wind": wind
},
"risks": [
{
"type": r.risk_type,
"severity": r.severity,
"score": r.score,
"description": r.description
}
for r in risks
],
"risk_count": len(risks),
"max_severity": max([r.severity for r in risks], key=lambda x: {"low": 1, "medium": 2, "high": 3, "critical": 4}.get(x, 0)) if risks else "none"
}
return profile
class EventGenerator:
"""Steg 3: Generera händelser från risker"""
def __init__(self):
self.events = []
def generate_events(self, risk_profile):
"""Generera händelser från riskprofil"""
road_id = risk_profile["road_id"]
risks = risk_profile["risks"]
events = []
for risk in risks:
if risk["severity"] in ["high", "critical"]:
event = {
"event_id": f"evt_{road_id}_{risk['type']}_{datetime.now().strftime('%Y%m%d_%H%M%S')}",
"road_id": road_id,
"event_type": risk["type"],
"severity": risk["severity"],
"description": risk["description"],
"timestamp": risk_profile["timestamp"],
"status": "active",
"requires_verification": True
}
events.append(event)
logger.info(f"Road {road_id}: Generated event {event['event_id']}")
return events
class MissionEngine:
"""Steg 4: Generera missions från events"""
def __init__(self):
self.missions = []
def generate_missions(self, events):
"""Generera missions från events"""
missions = []
for event in events:
if event["requires_verification"]:
mission = {
"mission_id": f"mission_{event['event_id']}",
"event_id": event["event_id"],
"road_id": event["road_id"],
"mission_type": "verification",
"description": f"Verify {event['event_type']} on road {event['road_id']}",
"priority": event["severity"],
"status": "pending",
"created_at": event["timestamp"],
"target": "quixzoom" # Skicka till quiXzoom
}
missions.append(mission)
logger.info(f"Road {event['road_id']}: Generated mission {mission['mission_id']}")
return missions
class WeatherPipelineV2:
"""Huvudpipeline"""
def __init__(self):
self.provider = WeatherProvider()
self.store = ObservationStore()
self.engine = RiskEngine()
self.road_binding = RoadBinding(self.store)
self.risk_profile = RiskProfile(self.engine)
self.event_generator = EventGenerator()
self.mission_engine = MissionEngine()
def run_for_road(self, road_id, road_type="primary"):
"""Kör pipeline för en väg"""
logger.info(f"=== Pipeline for Road {road_id} ===")
# Steg 0: Hämta väderdata
weather = self.provider.get_current_weather()
if not weather.get("temperature"):
logger.error("No weather data available")
return None
# Steg 1: Road Binding
binding = self.road_binding.bind_road(road_id, weather)
# Steg 2: Risk Profile
profile = self.risk_profile.create_profile(road_id, road_type, weather)
# Steg 3: Event Generation
events = self.event_generator.generate_events(profile)
# Steg 4: Mission Engine
missions = self.mission_engine.generate_missions(events)
result = {
"road_id": road_id,
"timestamp": weather["timestamp"],
"binding": binding,
"profile": profile,
"events": events,
"missions": missions
}
logger.info(f"Road {road_id}: Pipeline complete - {len(events)} events, {len(missions)} missions")
return result
if __name__ == "__main__":
pipeline = WeatherPipelineV2()
# Kör för första vägen
result = pipeline.run_for_road(road_id=1, road_type="primary")
if result:
print(json.dumps(result, indent=2))