linux: add start script and fixes; diagnostic outputs
This commit is contained in:
@@ -7,21 +7,82 @@ import os
|
||||
from pathlib import Path
|
||||
from typing import Dict, Optional, List
|
||||
|
||||
# Prefer the packaged app.ipm module, but keep a fallback to the legacy
|
||||
# IPM_DLL folder for development compatibility.
|
||||
try:
|
||||
from app.ipm.simple_refrig_api import Refifc, MockRefifc # type: ignore
|
||||
except Exception:
|
||||
# Fall back to loading from IPM_DLL directory as before. Import the
|
||||
# module and pick attributes if present; older legacy wrappers may not
|
||||
# define MockRefifc.
|
||||
_current_dir = Path(__file__).parent.parent.parent
|
||||
_ipm_dll_dir = _current_dir / "IPM_DLL"
|
||||
if str(_ipm_dll_dir) not in sys.path:
|
||||
sys.path.insert(0, str(_ipm_dll_dir))
|
||||
import simple_refrig_api as _sr # type: ignore
|
||||
Refifc = getattr(_sr, 'Refifc')
|
||||
MockRefifc = getattr(_sr, 'MockRefifc', None)
|
||||
# If IPM_DISABLE_NATIVE=1 is set, use a lightweight MockRefifc to avoid
|
||||
# loading the native shared libraries during tests or environments where
|
||||
# the native binaries are not available. This is a fast, deterministic
|
||||
# fallback and prevents expensive or failing native loads at import time.
|
||||
_USE_MOCK = os.environ.get("IPM_DISABLE_NATIVE", "0") in ("1", "true", "True")
|
||||
|
||||
class MockRefifc:
|
||||
"""Minimal mock of the Refifc interface used for fast tests.
|
||||
|
||||
It implements only the methods the app commonly calls (p_begin, p_end,
|
||||
hsl_px, hsv_px, T_px, h_pT, h_px, p_Tx) with simple deterministic
|
||||
formulas so tests and diagram generation can run without native libs.
|
||||
"""
|
||||
def __init__(self, refrig_name: str):
|
||||
self.refrig_name = refrig_name
|
||||
|
||||
def p_begin(self):
|
||||
return 1e4 # Pa
|
||||
|
||||
def p_end(self):
|
||||
return 4e6 # Pa
|
||||
|
||||
def hsl_px(self, p, x):
|
||||
# return a plausible enthalpy (J/kg)
|
||||
return 1e5 + 0.1 * p
|
||||
|
||||
def hsv_px(self, p, x):
|
||||
return 2e5 + 0.1 * p
|
||||
|
||||
def T_px(self, p, x):
|
||||
# return Kelvin
|
||||
return 273.15 + 20.0 + (p / 1e5) * 5.0
|
||||
|
||||
def h_pT(self, p, T):
|
||||
return 1.5e5 + (T - 273.15) * 1000.0
|
||||
|
||||
def h_px(self, p, x):
|
||||
return self.hsl_px(p, x) if x == 0 else self.hsv_px(p, x)
|
||||
|
||||
def p_Tx(self, T, x):
|
||||
# inverse of T_px approximately
|
||||
return ( (T - 273.15 - 20.0) / 5.0 ) * 1e5
|
||||
|
||||
|
||||
if _USE_MOCK:
|
||||
# Use the lightweight mock implementation defined above
|
||||
Refifc = MockRefifc
|
||||
else:
|
||||
# Prefer the packaged app.ipm module. For very old/legacy setups that still
|
||||
# ship a top-level `simple_refrig_api.py` in an `IPM_DLL` folder we keep a
|
||||
# fallback, but only if that file actually exists. This avoids attempting a
|
||||
# top-level import when the module is provided as `app.ipm.simple_refrig_api`.
|
||||
try:
|
||||
# Import the package module and read attributes to allow the wrapper to
|
||||
# work even when `MockRefifc` is not defined in the implementation.
|
||||
import importlib
|
||||
_sr_pkg = importlib.import_module('app.ipm.simple_refrig_api')
|
||||
Refifc = getattr(_sr_pkg, 'Refifc')
|
||||
MockRefifc = getattr(_sr_pkg, 'MockRefifc', None)
|
||||
except Exception as _first_exc:
|
||||
# If a legacy IPM_DLL/simple_refrig_api.py file exists, import it as a
|
||||
# top-level module; otherwise re-raise the original exception.
|
||||
_current_dir = Path(__file__).parent.parent.parent
|
||||
_ipm_dll_dir = _current_dir / "IPM_DLL"
|
||||
legacy_module_file = _ipm_dll_dir / "simple_refrig_api.py"
|
||||
|
||||
if legacy_module_file.exists():
|
||||
if str(_ipm_dll_dir) not in sys.path:
|
||||
sys.path.insert(0, str(_ipm_dll_dir))
|
||||
import simple_refrig_api as _sr # type: ignore
|
||||
Refifc = getattr(_sr, 'Refifc')
|
||||
MockRefifc = getattr(_sr, 'MockRefifc', None)
|
||||
else:
|
||||
# No legacy file found; re-raise the original import error so the
|
||||
# caller sees the underlying cause (missing dependency, etc.).
|
||||
raise _first_exc
|
||||
|
||||
|
||||
class RefrigerantLibrary:
|
||||
@@ -134,16 +195,23 @@ class RefrigerantManager:
|
||||
Liste de dictionnaires avec nom et disponibilite
|
||||
"""
|
||||
available = []
|
||||
|
||||
|
||||
# Instead of attempting to load every refrigerant (which triggers
|
||||
# potentially expensive native library loads), prefer a fast check by
|
||||
# detecting whether the corresponding shared object exists in the
|
||||
# repository's ipm lib/so directory. Loading is left for explicit
|
||||
# requests (POST /{refrig}/load) or when a refrigerant is already
|
||||
# present in memory.
|
||||
repo_app_dir = Path(__file__).parent.parent
|
||||
libs_dir = repo_app_dir / 'ipm' / 'lib' / 'so'
|
||||
|
||||
for refrig in self.SUPPORTED_REFRIGERANTS:
|
||||
try:
|
||||
# Tenter de charger pour verifier disponibilite
|
||||
if refrig not in self._loaded_refrigerants:
|
||||
self.load_refrigerant(refrig)
|
||||
|
||||
lib_file = libs_dir / f"lib{refrig}.so"
|
||||
exists = lib_file.exists()
|
||||
available.append({
|
||||
"name": refrig,
|
||||
"available": True,
|
||||
"available": bool(exists or (refrig in self._loaded_refrigerants)),
|
||||
"loaded": refrig in self._loaded_refrigerants
|
||||
})
|
||||
except Exception as e:
|
||||
@@ -152,7 +220,7 @@ class RefrigerantManager:
|
||||
"available": False,
|
||||
"error": str(e)
|
||||
})
|
||||
|
||||
|
||||
return available
|
||||
|
||||
def load_refrigerant(self, refrig_name: str) -> RefrigerantLibrary:
|
||||
|
||||
Reference in New Issue
Block a user