main.py 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. from copy import deepcopy
  2. from typing import Any
  3. from fastapi import FastAPI, Request
  4. from fastapi.exceptions import RequestValidationError
  5. from fastapi.responses import JSONResponse
  6. from uvicorn.config import LOGGING_CONFIG
  7. from app.api.bacnet import router as bacnet_router
  8. from app.api.modbus import router as modbus_router
  9. from app.api.s7 import router as s7_router
  10. from app.response import response_payload
  11. def uvicorn_log_config() -> dict[str, Any]:
  12. config = deepcopy(LOGGING_CONFIG)
  13. config["formatters"]["default"]["fmt"] = "%(asctime)s %(levelprefix)s %(message)s"
  14. config["formatters"]["default"]["datefmt"] = "%Y-%m-%d %H:%M:%S"
  15. config["formatters"]["access"]["fmt"] = '%(asctime)s %(levelprefix)s %(client_addr)s - "%(request_line)s" %(status_code)s'
  16. config["formatters"]["access"]["datefmt"] = "%Y-%m-%d %H:%M:%S"
  17. return config
  18. def validation_error_message(exc: RequestValidationError) -> str:
  19. messages: list[str] = []
  20. for error in exc.errors():
  21. location = ".".join(str(item) for item in error.get("loc", []) if item != "body")
  22. message = error.get("msg", "validation error")
  23. messages.append(f"{location}: {message}" if location else message)
  24. return "; ".join(messages) or "validation error"
  25. def create_app() -> FastAPI:
  26. app = FastAPI(title="Data Collector Gateway")
  27. app.include_router(modbus_router, prefix="/api/dc-gateway")
  28. app.include_router(s7_router, prefix="/api/dc-gateway")
  29. app.include_router(bacnet_router, prefix="/api/dc-gateway")
  30. @app.exception_handler(RequestValidationError)
  31. async def request_validation_exception_handler(
  32. request: Request,
  33. exc: RequestValidationError,
  34. ) -> JSONResponse:
  35. data: dict[str, list] = {}
  36. if request.url.path.endswith("/modbus/read"):
  37. data = {"communication": []}
  38. elif request.url.path.endswith(("/modbus/read_points", "/modbus/read-points")):
  39. data = {"points": []}
  40. elif request.url.path.endswith("/s7/read"):
  41. data = {"communication": []}
  42. elif request.url.path.endswith("/s7/read_points"):
  43. data = {"points": []}
  44. elif request.url.path.endswith("/s7/connect_scan"):
  45. data = {"available": []}
  46. elif request.url.path.endswith(("/bacnet/read_points", "/bacnet/search_points")):
  47. data = {"points": []}
  48. elif request.url.path.endswith("/bacnet/bbmd/whois"):
  49. data = {"devices": []}
  50. return JSONResponse(
  51. status_code=200,
  52. content=response_payload(1, validation_error_message(exc), data),
  53. )
  54. return app
  55. app = create_app()
  56. def main() -> None:
  57. import uvicorn
  58. uvicorn.run(app, host="0.0.0.0", port=8000, log_config=uvicorn_log_config())