feat: Implement RBD integration for EAF simulation and result collection, and enhance equipment data with joined Maximo records.
parent
65308e5735
commit
a2152f33b4
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,24 @@
|
|||||||
|
|
||||||
|
import asyncio
|
||||||
|
import logging
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
|
||||||
|
# Add the project root to sys.path to resolve imports
|
||||||
|
sys.path.append(os.getcwd())
|
||||||
|
|
||||||
|
from src.database.core import get_session
|
||||||
|
from src.modules.plant.fetch_eaf_from_rbd import fetch_simulation_results
|
||||||
|
|
||||||
|
# Setup logging
|
||||||
|
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
logger.info("Starting simulation result collection script...")
|
||||||
|
async with get_session() as session:
|
||||||
|
await fetch_simulation_results(session)
|
||||||
|
logger.info("Simulation result collection script finished.")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
asyncio.run(main())
|
||||||
@ -0,0 +1,154 @@
|
|||||||
|
|
||||||
|
import httpx
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
from datetime import datetime
|
||||||
|
from sqlalchemy import select
|
||||||
|
from src.database.core import DbSession
|
||||||
|
from src.yeardata.model import Yeardata
|
||||||
|
from src.config import RBD_APP_URL
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
current_year = datetime.now().year
|
||||||
|
AUTH_APP_URL = os.getenv("AUTH_APP_URL", "http://192.168.1.82:8000/auth")
|
||||||
|
|
||||||
|
async def sign_in(username: str = "lcca_admin", password: str = "password") -> str:
|
||||||
|
"""
|
||||||
|
Sign in to AUTH_APP_URL/sign-in using provided username/password.
|
||||||
|
Returns the access_token string if successful, else None.
|
||||||
|
"""
|
||||||
|
url = f"{AUTH_APP_URL}/sign-in"
|
||||||
|
logger.info(f"Signing in to {url}...")
|
||||||
|
async with httpx.AsyncClient() as client:
|
||||||
|
try:
|
||||||
|
resp = await client.post(
|
||||||
|
url,
|
||||||
|
json={"username": username, "password": password},
|
||||||
|
timeout=30.0,
|
||||||
|
)
|
||||||
|
resp.raise_for_status()
|
||||||
|
data = resp.json()
|
||||||
|
if isinstance(data, dict) and "data" in data:
|
||||||
|
token = data.get("data", {}).get("access_token")
|
||||||
|
if token:
|
||||||
|
logger.info("Sign-in successful.")
|
||||||
|
return token
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Sign-in failed: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
async def start_simulations(db_session: DbSession):
|
||||||
|
"""
|
||||||
|
Starts simulatios on RBD app for years > current year and saves simulation IDs.
|
||||||
|
"""
|
||||||
|
# 0. Sign in first
|
||||||
|
token = await sign_in()
|
||||||
|
if not token:
|
||||||
|
logger.error("Aborting start_simulations because sign-in failed.")
|
||||||
|
return
|
||||||
|
|
||||||
|
headers = {"Authorization": f"Bearer {token}"}
|
||||||
|
|
||||||
|
# Get all years after current year
|
||||||
|
query = select(Yeardata).filter(Yeardata.year > current_year)
|
||||||
|
result = await db_session.execute(query)
|
||||||
|
yeardata_list = result.scalars().all()
|
||||||
|
|
||||||
|
if not yeardata_list:
|
||||||
|
logger.info("No yeardata found for years > %s", current_year)
|
||||||
|
return
|
||||||
|
|
||||||
|
async with httpx.AsyncClient() as client:
|
||||||
|
# Step 1: Start simulations and get IDs
|
||||||
|
for record in yeardata_list:
|
||||||
|
try:
|
||||||
|
# POST {{RBD_APP_URL}}/aeros/simulation/run/yearly
|
||||||
|
url = f"{RBD_APP_URL}/aeros/simulation/run/yearly"
|
||||||
|
payload = {"year": record.year}
|
||||||
|
logger.info(f"Starting simulation for year {record.year}: POST {url}")
|
||||||
|
|
||||||
|
response = await client.post(url, json=payload, headers=headers, timeout=60.0)
|
||||||
|
response.raise_for_status()
|
||||||
|
|
||||||
|
# Check JSON for ID, fallback to text if needed
|
||||||
|
try:
|
||||||
|
data = response.json()
|
||||||
|
if isinstance(data, dict):
|
||||||
|
simulation_id = data.get("id") or data.get("simulation_id") or data.get("data")
|
||||||
|
if not simulation_id or isinstance(simulation_id, dict):
|
||||||
|
simulation_id = str(data.get("id", ""))
|
||||||
|
else:
|
||||||
|
simulation_id = str(data)
|
||||||
|
except Exception:
|
||||||
|
simulation_id = response.text.strip().strip('"')
|
||||||
|
|
||||||
|
if simulation_id:
|
||||||
|
record.rbd_simulation_id = str(simulation_id)
|
||||||
|
db_session.add(record)
|
||||||
|
logger.info(f"Saved simulation_id {simulation_id} for year {record.year}")
|
||||||
|
else:
|
||||||
|
logger.error(f"Could not extract simulation ID from response for year {record.year}: {response.text}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Failed to start simulation for year {record.year}: {e}")
|
||||||
|
|
||||||
|
# Commit simulation IDs
|
||||||
|
await db_session.commit()
|
||||||
|
logger.info("All simulations started and IDs saved.")
|
||||||
|
|
||||||
|
|
||||||
|
async def fetch_simulation_results(db_session: DbSession):
|
||||||
|
"""
|
||||||
|
Fetches EAF data using simulation IDs for years > current year.
|
||||||
|
Should be called after start_simulations.
|
||||||
|
"""
|
||||||
|
# 0. Sign in first
|
||||||
|
token = await sign_in()
|
||||||
|
if not token:
|
||||||
|
logger.error("Aborting fetch_simulation_results because sign-in failed.")
|
||||||
|
return
|
||||||
|
|
||||||
|
headers = {"Authorization": f"Bearer {token}"}
|
||||||
|
|
||||||
|
# Get all years after current year
|
||||||
|
query = select(Yeardata).filter(Yeardata.year > current_year)
|
||||||
|
result = await db_session.execute(query)
|
||||||
|
yeardata_list = result.scalars().all()
|
||||||
|
|
||||||
|
if not yeardata_list:
|
||||||
|
logger.info("No yeardata found for years > %s", current_year)
|
||||||
|
return
|
||||||
|
|
||||||
|
async with httpx.AsyncClient() as client:
|
||||||
|
# Step 2: Fetch EAF data
|
||||||
|
for record in yeardata_list:
|
||||||
|
if not record.rbd_simulation_id:
|
||||||
|
logger.warning(f"No simulation ID for year {record.year}, skipping.")
|
||||||
|
continue
|
||||||
|
|
||||||
|
try:
|
||||||
|
# GET {{RBD_APP_URL}}/aeros/simulation/result/calc/:simulation_id/plant
|
||||||
|
url = f"{RBD_APP_URL}/aeros/simulation/result/calc/{record.rbd_simulation_id}/plant"
|
||||||
|
logger.info(f"Fetching result for year {record.year}: GET {url}")
|
||||||
|
|
||||||
|
response = await client.get(url, headers=headers, timeout=60.0)
|
||||||
|
response.raise_for_status()
|
||||||
|
|
||||||
|
result_data = response.json()
|
||||||
|
# Expected format: { "data": { "eaf": ... } }
|
||||||
|
eaf_value = result_data.get("data", {}).get("eaf")
|
||||||
|
|
||||||
|
if eaf_value is not None:
|
||||||
|
record.eaf = float(eaf_value)
|
||||||
|
db_session.add(record)
|
||||||
|
logger.info(f"Saved EAF {eaf_value} for year {record.year}")
|
||||||
|
else:
|
||||||
|
logger.warning(f"No EAF value found in response for year {record.year}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Failed to fetch EAF for year {record.year}: {e}")
|
||||||
|
|
||||||
|
# Commit EAF updates
|
||||||
|
await db_session.commit()
|
||||||
|
logger.info("All simulation results fetched and saved.")
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
|
||||||
|
import asyncio
|
||||||
|
import logging
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
|
||||||
|
# Add the project root to sys.path to resolve imports
|
||||||
|
sys.path.append(os.getcwd())
|
||||||
|
|
||||||
|
from src.database.core import get_session
|
||||||
|
from src.modules.plant.fetch_eaf_from_rbd import start_simulations
|
||||||
|
|
||||||
|
# Setup logging
|
||||||
|
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
logger.info("Starting simulation trigger script...")
|
||||||
|
async with get_session() as session:
|
||||||
|
await start_simulations(session)
|
||||||
|
logger.info("Simulation trigger script finished.")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
asyncio.run(main())
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue