import json from fastapi import APIRouter, Request, HTTPException from fastapi.responses import PlainTextResponse from typing import Any, Dict import app.services.project_info as project_info from app.native.api import ChangeSet from app.services.tjnetwork import ( list_project, have_project, create_project, delete_project, is_project_open, open_project, close_project, copy_project, import_inp, export_inp, read_inp, dump_inp, get_all_vertices, get_all_scada_elements, get_all_district_metering_areas, get_all_service_areas, get_all_virtual_districts, get_extension_data, convert_inp_v3_to_v2, ) # For inp file upload/download import os from fastapi import Response, status from fastapi.responses import FileResponse inpDir = "data/" # Assuming data directory exists or is defined somewhere. # In main.py it was likely global. For safety, let's use a relative path or get from config. # But let's stick to what main.py probably used or a default. router = APIRouter() lockedPrjs: Dict[str, str] = {} @router.get("/listprojects/") async def list_projects_endpoint() -> list[str]: return list_project() @router.get("/haveproject/") async def have_project_endpoint(network: str): return have_project(network) @router.post("/createproject/") async def create_project_endpoint(network: str): create_project(network) return network @router.post("/deleteproject/") async def delete_project_endpoint(network: str): delete_project(network) return True @router.get("/isprojectopen/") async def is_project_open_endpoint(network: str): return is_project_open(network) @router.post("/openproject/") async def open_project_endpoint(network: str): open_project(network) return network @router.post("/closeproject/") async def close_project_endpoint(network: str): close_project(network) return True @router.post("/copyproject/") async def copy_project_endpoint(source: str, target: str): copy_project(source, target) return True @router.post("/importinp/") async def import_inp_endpoint(network: str, req: Request): jo_root = await req.json() inp_text = jo_root["inp"] ps = {"inp": inp_text} ret = import_inp(network, ChangeSet(ps)) print(ret) return ret @router.get("/exportinp/", response_model=None) async def export_inp_endpoint(network: str, version: str) -> ChangeSet: cs = export_inp(network, version) op = cs.operations[0] open_project(network) op["vertex"] = json.dumps(get_all_vertices(network)) op["scada"] = json.dumps(get_all_scada_elements(network)) op["dma"] = json.dumps(get_all_district_metering_areas(network)) op["sa"] = json.dumps(get_all_service_areas(network)) op["vd"] = json.dumps(get_all_virtual_districts(network)) op["legend"] = get_extension_data(network, "legend") db = get_extension_data(network, "scada_db") print(db) scada_db = "" if db: scada_db = db print(scada_db) op["scada_db"] = scada_db close_project(network) return cs @router.post("/readinp/") async def read_inp_endpoint(network: str, inp: str) -> bool: read_inp(network, inp) return True @router.get("/dumpinp/") async def dump_inp_endpoint(network: str, inp: str) -> bool: dump_inp(network, inp) return True @router.get("/isprojectlocked/") async def is_project_locked_endpoint(network: str, req: Request): return network in lockedPrjs.keys() @router.get("/isprojectlockedbyme/") async def is_project_locked_by_me_endpoint(network: str, req: Request): client_host = req.client.host return lockedPrjs.get(network) == client_host # 0 successfully locked # 1 already locked by you # 2 locked by others @router.post("/lockproject/") async def lock_project_endpoint(network: str, req: Request): client_host = req.client.host if not network in lockedPrjs.keys(): lockedPrjs[network] = client_host return 0 else: if lockedPrjs.get(network) == client_host: return 1 else: return 2 @router.post("/unlockproject/") def unlock_project_endpoint(network: str, req: Request): client_host = req.client.host if lockedPrjs.get(network) == client_host: print("delete key") del lockedPrjs[network] return True return False # inp file operations @router.post("/uploadinp/", status_code=status.HTTP_200_OK) async def fastapi_upload_inp(afile: bytes, name: str): if not os.path.exists(inpDir): os.makedirs(inpDir, exist_ok=True) filePath = inpDir + str(name) with open(filePath, "wb") as f: f.write(afile) return True @router.get("/downloadinp/", status_code=status.HTTP_200_OK) async def fastapi_download_inp(name: str, response: Response): filePath = inpDir + name if os.path.exists(filePath): return FileResponse( filePath, media_type="application/octet-stream", filename="inp.inp" ) else: response.status_code = status.HTTP_400_BAD_REQUEST return True # DingZQ, 2024-12-28, convert v3 to v2 @router.get("/convertv3tov2/", response_model=None) async def fastapi_convert_v3_to_v2(req: Request) -> ChangeSet: network = "v3Tov2" jo_root = await req.json() inp = jo_root["inp"] cs = convert_inp_v3_to_v2(inp) op = cs.operations[0] open_project(network) op["vertex"] = json.dumps(get_all_vertices(network)) op["scada"] = json.dumps(get_all_scada_elements(network)) op["dma"] = json.dumps(get_all_district_metering_areas(network)) op["sa"] = json.dumps(get_all_service_areas(network)) op["vd"] = json.dumps(get_all_virtual_districts(network)) op["legend"] = get_extension_data(network, "legend") db = get_extension_data(network, "scada_db") print(db) scada_db = "" if db: scada_db = db print(scada_db) op["scada_db"] = scada_db close_project(network) return cs