Browse Source

update type hints

highing666 2 years ago
parent
commit
61d60397be
64 changed files with 515 additions and 650 deletions
  1. 1 1
      app/api/routers/algorithms.py
  2. 2 3
      app/api/routers/bluetooth.py
  3. 0 1
      app/api/routers/diagnosis.py
  4. 2 3
      app/api/routers/item.py
  5. 6 8
      app/api/routers/model_path/early_start.py
  6. 2 4
      app/api/routers/positioning.py
  7. 2 3
      app/api/routers/space.py
  8. 11 14
      app/api/routers/targets.py
  9. 4 6
      app/api/routers/user.py
  10. 6 7
      app/controllers/algorithms/graph_coloring.py
  11. 4 4
      app/controllers/algorithms/meeting_attendee_recommendation.py
  12. 51 68
      app/controllers/diagnosis/thermal_comfort.py
  13. 2 4
      app/controllers/equipment/ahu/basic.py
  14. 4 6
      app/controllers/equipment/ahu/common.py
  15. 1 3
      app/controllers/equipment/ahu/supply_air_temperature_set.py
  16. 1 3
      app/controllers/equipment/ahu/thermal_mode.py
  17. 5 7
      app/controllers/equipment/ashp/basic.py
  18. 1 2
      app/controllers/equipment/fcu/basic.py
  19. 7 9
      app/controllers/equipment/pau/freq_set.py
  20. 5 6
      app/controllers/equipment/pau/switch.py
  21. 1 1
      app/controllers/equipment/switch.py
  22. 5 6
      app/controllers/equipment/vav.py
  23. 2 3
      app/controllers/equipment/vrf/basic.py
  24. 2 7
      app/controllers/location/ble/space.py
  25. 10 12
      app/controllers/nlp/meeting.py
  26. 53 78
      app/controllers/targets/temperature.py
  27. 6 7
      app/core/config.py
  28. 2 6
      app/core/events.py
  29. 1 1
      app/core/logger.py
  30. 9 9
      app/crud/base.py
  31. 4 6
      app/crud/device/status_timestamp.py
  32. 2 3
      app/crud/model_path/early_start.py
  33. 3 4
      app/crud/space/weight.py
  34. 1 1
      app/models/domain/algorithms.py
  35. 92 95
      app/models/domain/devices.py
  36. 5 7
      app/models/domain/diagnosis.py
  37. 1 3
      app/models/domain/equipment.py
  38. 3 5
      app/models/domain/location.py
  39. 6 7
      app/models/domain/nlp.py
  40. 4 6
      app/models/domain/targets.py
  41. 6 7
      app/schemas/bluetooth.py
  42. 4 5
      app/schemas/device/status_timestamp.py
  43. 13 14
      app/schemas/diagnosis.py
  44. 50 51
      app/schemas/equipment.py
  45. 1 3
      app/schemas/item.py
  46. 5 7
      app/schemas/model_path/early_start.py
  47. 7 8
      app/schemas/sapce_weight.py
  48. 14 15
      app/schemas/space.py
  49. 1 2
      app/schemas/system.py
  50. 1 3
      app/schemas/target.py
  51. 1 2
      app/schemas/user.py
  52. 1 3
      app/services/duckling.py
  53. 13 15
      app/services/milvus.py
  54. 6 7
      app/services/milvus_helpers.py
  55. 15 16
      app/services/platform.py
  56. 10 15
      app/services/rwd.py
  57. 8 10
      app/services/service.py
  58. 6 8
      app/services/tencent_nlp.py
  59. 19 22
      app/services/transfer.py
  60. 1 2
      app/services/weather.py
  61. 1 2
      app/utils/date.py
  62. 1 2
      app/utils/helpers.py
  63. 1 1
      docker-compose.yml
  64. 1 1
      requirements.txt

+ 1 - 1
app/api/routers/algorithms.py

@@ -40,4 +40,4 @@ async def get_recommended(meeting_info: AttendeesRecommendationRequest):
         logger.error(e)
         return {"code": 500, "message": "Recommend failure."}
     else:
-        return {"code": 200, "message": "sucess", "data": {"userIdList": res}}
+        return {"code": 200, "message": "success", "data": {"userIdList": res}}

+ 2 - 3
app/api/routers/bluetooth.py

@@ -1,8 +1,7 @@
 # -*- coding: utf-8 -*-
 
-from typing import List
 
-from fastapi import APIRouter, Depends, HTTPException, Query
+from fastapi import APIRouter
 from loguru import logger
 
 from app.controllers.location.ble.space import get_space_location
@@ -13,7 +12,7 @@ router = APIRouter()
 
 
 @router.post("/user/{user_id}", response_model=BluetoothUserResponse)
-async def create_bluetooth_info(user_id: str, bluetooth_info: List[IBeaconBase]):
+async def create_bluetooth_info(user_id: str, bluetooth_info: list[IBeaconBase]):
     info_list = [item.dict() for item in bluetooth_info]
     logger.info(f"{user_id}: {info_list}")
     sp_id = await get_space_location("Pj1101080259", bluetooth_info)

+ 0 - 1
app/api/routers/diagnosis.py

@@ -1,5 +1,4 @@
 from fastapi import APIRouter
-from loguru import logger
 
 from app.models.domain.diagnosis import (
     ThermalComfortDiagnosisRequest,

+ 2 - 3
app/api/routers/item.py

@@ -1,4 +1,3 @@
-from typing import Any, List
 
 from fastapi import APIRouter, Depends
 from sqlalchemy.orm import Session
@@ -10,12 +9,12 @@ from app.schemas.item import Item
 router = APIRouter()
 
 
-@router.get("/", response_model=List[Item])
+@router.get("/", response_model=list[Item])
 def read_items(
     skip: int = 0,
     limit: int = 100,
     db: Session = Depends(get_db),
-) -> Any:
+):
     """
     Retrieve items.
     """

+ 6 - 8
app/api/routers/model_path/early_start.py

@@ -1,5 +1,3 @@
-from typing import List
-
 from fastapi import APIRouter, Depends, HTTPException
 from sqlalchemy.orm import Session
 
@@ -16,14 +14,14 @@ router = APIRouter()
 
 @router.post("/early-start/dtr", response_model=EarlyStartDTRModelPath)
 async def create_model_path(
-    model_path: EarlyStartDTRModelPathCreate, db: Session = Depends(get_db)
+        model_path: EarlyStartDTRModelPathCreate, db: Session = Depends(get_db)
 ):
     return model_path_early_start_dtr.create(db=db, obj_in=model_path)
 
 
-@router.get("/early-start/dtr", response_model=List[EarlyStartDTRModelPath])
+@router.get("/early-start/dtr", response_model=list[EarlyStartDTRModelPath])
 async def read_model_path(
-    skip: int = 0, limit: int = 100, db: Session = Depends(get_db)
+        skip: int = 0, limit: int = 100, db: Session = Depends(get_db)
 ):
     model_paths = model_path_early_start_dtr.get_multi(db, skip=skip, limit=limit)
     return model_paths
@@ -39,9 +37,9 @@ async def read_model_path_by_device(device_id: str, db: Session = Depends(get_db
 
 @router.put("/early-start/dtr/{device_id}", response_model=EarlyStartDTRModelPath)
 async def update_model_path(
-    device_id: str,
-    model_path_in: EarlyStartDTRModelPathUpdate,
-    db: Session = Depends(get_db),
+        device_id: str,
+        model_path_in: EarlyStartDTRModelPathUpdate,
+        db: Session = Depends(get_db),
 ):
     model_path = model_path_early_start_dtr.get_path_by_device(
         db=db, device_id=device_id

+ 2 - 4
app/api/routers/positioning.py

@@ -1,6 +1,4 @@
-from typing import List
-
-from fastapi import APIRouter, HTTPException, Query
+from fastapi import APIRouter
 from loguru import logger
 
 from app.controllers.location.ble.space import get_space_location
@@ -14,7 +12,7 @@ router = APIRouter()
     "/space/users/{user_id}/projects/{project_id}", response_model=PositionSpaceResponse
 )
 async def update_in_space(
-    user_id: str, project_id: str, ibeacon_list: List[IBeaconBase]
+        user_id: str, project_id: str, ibeacon_list: list[IBeaconBase]
 ):
     space_id = await get_space_location(project_id, ibeacon_list)
     logger.debug(f"{user_id} is in {space_id}")

+ 2 - 3
app/api/routers/space.py

@@ -1,6 +1,5 @@
 # -*- coding: utf-8 -*-
 
-from typing import List
 
 from fastapi import APIRouter, Depends, HTTPException, Query
 from sqlalchemy.orm import Session
@@ -40,13 +39,13 @@ async def create_space_weight(weight: SpaceWeightCreate, db: Session = Depends(g
     return create_weight(db=db, weight=weight)
 
 
-@router.get("/weight/{space_id}", response_model=List[SpaceWeight])
+@router.get("/weight/{space_id}", response_model=list[SpaceWeight])
 async def read_weight_by_space(space_id: str, db: Session = Depends(get_db)):
     db_weights = get_weights_by_space(db, space_id=space_id)
     return db_weights
 
 
-@router.get("/weight/vav/{vav_id}", response_model=List[SpaceWeight])
+@router.get("/weight/vav/{vav_id}", response_model=list[SpaceWeight])
 async def read_weight_by_vav(vav_id: str, db: Session = Depends(get_db)):
     db_weights = get_weights_by_vav(db, vav_id=vav_id)
     return db_weights

+ 11 - 14
app/api/routers/targets.py

@@ -1,12 +1,9 @@
 # -*- coding: utf-8 -*-
 
-from typing import Optional
 
-from fastapi import APIRouter, Depends, HTTPException, Query
+from fastapi import APIRouter, HTTPException, Query
 from loguru import logger
-from sqlalchemy.orm import Session
 
-from app.api.dependencies.db import get_db
 from app.controllers.targets.temperature import (
     temperature_target_control_v1,
     temperature_target_control_v2,
@@ -26,10 +23,10 @@ router = APIRouter()
 
 @router.get("/adjust", response_model=TargetReadjustResponse)
 async def readjust_target(
-    project_id: str = Query(..., max_length=50, regex="^Pj", alias="projectId"),
-    space_id: str = Query(..., max_length=50, regex="^Sp", alias="roomId"),
-    timestamp: Optional[str] = Query(None, min_length=14, max_length=14, alias="time"),
-    feedback: Optional[FeedbackValue] = Query(None, alias="itemId"),
+        project_id: str = Query(..., max_length=50, regex="^Pj", alias="projectId"),
+        space_id: str = Query(..., max_length=50, regex="^Sp", alias="roomId"),
+        timestamp: str | None = Query(None, min_length=14, max_length=14, alias="time"),
+        feedback: FeedbackValue | None = Query(None, alias="itemId"),
 ):
     if not timestamp:
         timestamp = get_time_str()
@@ -62,9 +59,9 @@ async def readjust_target(
 
 @router.get("/adjust/v2", response_model=TargetReadjustResponse)
 async def readjust_target_v2(
-    project_id: str = Query(..., max_length=50, regex="^Pj", alias="project-id"),
-    space_id: str = Query(..., max_length=50, regex="^Sp", alias="space-id"),
-    feedback: Optional[FeedbackValue] = Query(None),
+        project_id: str = Query(..., max_length=50, regex="^Pj", alias="project-id"),
+        space_id: str = Query(..., max_length=50, regex="^Sp", alias="space-id"),
+        feedback: FeedbackValue | None = Query(None),
 ):
     if feedback != FeedbackValue.null:
         try:
@@ -95,9 +92,9 @@ async def get_readjusted_target(params: TargetReadjustRequestV2):
 
 @router.get("/regulated/value", response_model=RegulatedTargetResponse)
 async def read_regulated_value(
-    project_id: str = Query(..., max_length=50, regex="^Pj", alias="projectId"),
-    space_id: str = Query(..., max_length=50, regex="^Sp", alias="spaceId"),
-    feedback: Optional[FeedbackValue] = Query(None),
+        project_id: str = Query(..., max_length=50, regex="^Pj", alias="projectId"),
+        space_id: str = Query(..., max_length=50, regex="^Sp", alias="spaceId"),
+        feedback: FeedbackValue | None = Query(None),
 ):
     new_actual_target = await get_target_after_feedback(project_id, space_id, feedback)
     response = {

+ 4 - 6
app/api/routers/user.py

@@ -1,13 +1,11 @@
-from typing import Any, List
-
 from fastapi import APIRouter, Depends, HTTPException
 from sqlalchemy.orm import Session
 
 from app.api.dependencies.db import get_db
-from app.schemas.user import User, UserCreate
-from app.schemas.item import Item, ItemCreate
-from app.crud.crud_user import get_user_by_email, create_user, get_users, get_user
 from app.crud.crud_item import create_user_item
+from app.crud.crud_user import get_user_by_email, create_user, get_users, get_user
+from app.schemas.item import Item, ItemCreate
+from app.schemas.user import User, UserCreate
 
 router = APIRouter()
 
@@ -20,7 +18,7 @@ def create_new_user(user: UserCreate, db: Session = Depends(get_db)):
     return create_user(db=db, user=user)
 
 
-@router.get("/", response_model=List[User])
+@router.get("/", response_model=list[User])
 def read_users(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)):
     users = get_users(db, skip=skip, limit=limit)
     return users

+ 6 - 7
app/controllers/algorithms/graph_coloring.py

@@ -1,5 +1,4 @@
 from queue import Queue
-from typing import Dict, List, Optional, Tuple
 
 from loguru import logger
 from pydantic import BaseModel
@@ -7,12 +6,12 @@ from pydantic import BaseModel
 
 class Vertex(BaseModel):
     id: str
-    color: Optional[int]
-    edges: Optional[set]
+    color: int | None
+    edges: set | None
 
 
 class ColoringProblemBFSSolution:
-    def __init__(self, vertexes: List[Vertex]):
+    def __init__(self, vertexes: list[Vertex]):
         self._vertexes = vertexes
         self._is_solvable = True
 
@@ -47,7 +46,7 @@ class ColoringProblemBFSSolution:
                             visited[j] = True
                             q.put(j)
 
-    def get_colored(self) -> Tuple[bool, Dict[str, int]]:
+    def get_colored(self) -> tuple[bool, dict[str, int]]:
         colored = dict()
         for v in self._vertexes:
             colored.update({v.id: v.color})
@@ -55,7 +54,7 @@ class ColoringProblemBFSSolution:
         return self._is_solvable, colored
 
 
-def reformat(graph: Dict[str, List]) -> List[Vertex]:
+def reformat(graph: dict[str, list[str]]) -> list[Vertex]:
     vertex_idx_dic = dict()
     idx = 0
     for k in graph.keys():
@@ -71,7 +70,7 @@ def reformat(graph: Dict[str, List]) -> List[Vertex]:
 
 
 @logger.catch()
-async def get_graph_coloring(graph: Dict[str, List]) -> Tuple[bool, Dict[str, int]]:
+async def get_graph_coloring(graph: dict[str, list[str]]) -> tuple[bool, dict[str, int]]:
     vertexes = reformat(graph)
     solution = ColoringProblemBFSSolution(vertexes)
     solution.bfs()

+ 4 - 4
app/controllers/algorithms/meeting_attendee_recommendation.py

@@ -1,14 +1,14 @@
 import time
-from typing import List
+
 from loguru import logger
 
-from app.services.my_redis import MyRedis
 from app.services.milvus import Milvus
 from app.services.milvus_helpers import my_milvus
+from app.services.my_redis import MyRedis
 
 
 @logger.catch()
-async def build_recommendations(company_id: str, user_id: str) -> List:
+async def build_recommendations(company_id: str, user_id: str) -> list[str]:
     MILVUS_CLI = my_milvus.get("cli")
     myredis = MyRedis()
     r = myredis.get_client()
@@ -34,7 +34,7 @@ async def build_recommendations(company_id: str, user_id: str) -> List:
 
 
 @logger.catch()
-async def build_recommendations_v2(company_id: str, user_id: str) -> List:
+async def build_recommendations_v2(company_id: str, user_id: str) -> list[str]:
     old_milvus = Milvus()
     myredis = MyRedis()
     r = myredis.get_client()

+ 51 - 68
app/controllers/diagnosis/thermal_comfort.py

@@ -1,8 +1,4 @@
-from abc import ABC, abstractmethod
-from typing import Optional
-
-import numpy as np
-from loguru import logger
+from abc import ABC
 
 from app.models.domain.diagnosis import ThermalComfortDiagnosisRequest
 from app.schemas.diagnosis import FaultCategory
@@ -15,21 +11,17 @@ class DiagnotorBase(ABC):
         self._result = FaultCategory()
 
     def controller_check(
-        self,
-        setting_value: float,
-        feedback_value: float,
-        is_categorical: bool = True,
-        tolerance_pct: float = 0.0,
+            self,
+            setting_value: float,
+            feedback_value: float,
+            is_categorical: bool = True,
+            tolerance_pct: float = 0.0,
     ) -> None:
         if is_categorical:
             if setting_value != feedback_value:
                 self._result.controller_err = True
         else:
-            if (
-                not setting_value * (1 - tolerance_pct)
-                <= feedback_value
-                <= setting_value * (1 + tolerance_pct)
-            ):
+            if not setting_value * (1 - tolerance_pct) <= feedback_value <= setting_value * (1 + tolerance_pct):
                 self._result.controller_err = True
 
 
@@ -40,13 +32,13 @@ class ThermalComfortDiagnotor(DiagnotorBase):
 
 class FCUDiagnotor(DiagnotorBase):
     def __init__(
-        self,
-        fcu: FCU,
-        ahu: AHU,
-        duration: float,
-        target_temp: float,
-        realtime_temp: float,
-        season: Season,
+            self,
+            fcu: FCU,
+            ahu: AHU,
+            duration: float,
+            target_temp: float,
+            realtime_temp: float,
+            season: Season,
     ):
         super(FCUDiagnotor, self).__init__()
         self._fcu = fcu
@@ -111,16 +103,16 @@ class FCUDiagnotor(DiagnotorBase):
 
     def run(self) -> None:
         if (
-            self._season == Season.heating
-            or self._fcu.supply_air_temperature > self._target_temp
+                self._season == Season.heating
+                or self._fcu.supply_air_temperature > self._target_temp
         ):
             if self._realtime_temp < self._target_temp - 1:
                 self.low_in_heating()
             elif self._realtime_temp > self._target_temp + 1:
                 self.high_in_heating()
         elif (
-            self._season == Season.cooling
-            or self._fcu.supply_air_temperature < self._target_temp
+                self._season == Season.cooling
+                or self._fcu.supply_air_temperature < self._target_temp
         ):
             if self._realtime_temp < self._target_temp - 1:
                 self.low_in_cooling()
@@ -130,12 +122,12 @@ class FCUDiagnotor(DiagnotorBase):
 
 class VAVDiagnotor(DiagnotorBase):
     def __init__(
-        self,
-        vav: VAVBox,
-        ahu: AHU,
-        known_err: FaultCategory,
-        duration: float,
-        season: Season,
+            self,
+            vav: VAVBox,
+            ahu: AHU,
+            known_err: FaultCategory,
+            duration: float,
+            season: Season,
     ):
         super(VAVDiagnotor, self).__init__()
         self._vav = vav
@@ -152,17 +144,17 @@ class VAVDiagnotor(DiagnotorBase):
             tolerance_pct=0.1,
         )
         if (
-            self._vav.recommended_supply_air_flow
-            >= self._vav.supply_air_flow_upper_limit
+                self._vav.recommended_supply_air_flow
+                >= self._vav.supply_air_flow_upper_limit
         ):
             if self._vav.recommended_supply_air_flow == self._vav.supply_air_flow_set:
                 if not self._result.controller_err:
                     if self._duration > 120.0:
                         if (
-                            self._vav.supply_air_temperature
-                            < self._vav.virtual_target_temperature + 1
-                            or self._ahu.supply_air_temperature
-                            < self._vav.virtual_target_temperature + 2
+                                self._vav.supply_air_temperature
+                                < self._vav.virtual_target_temperature + 1
+                                or self._ahu.supply_air_temperature
+                                < self._vav.virtual_target_temperature + 2
                         ):
                             self._result.insufficient_heating = True
                         else:
@@ -195,8 +187,8 @@ class VAVDiagnotor(DiagnotorBase):
                         else:
                             if not self._known_err.sensor_err:
                                 if (
-                                    self._vav.supply_air_temperature < 18
-                                    or self._ahu.supply_air_temperature < 18
+                                        self._vav.supply_air_temperature < 18
+                                        or self._ahu.supply_air_temperature < 18
                                 ):
                                     self._result.excessive_cooling = True
                                 else:
@@ -217,47 +209,47 @@ class VAVDiagnotor(DiagnotorBase):
     def high_in_cooling(self) -> None:
         self.low_in_heating()
         if (
-            self._vav.recommended_supply_air_flow
-            >= self._vav.supply_air_flow_upper_limit
+                self._vav.recommended_supply_air_flow
+                >= self._vav.supply_air_flow_upper_limit
         ):
             if self._vav.recommended_supply_air_flow == self._vav.supply_air_flow_set:
                 if not self._result.controller_err:
                     if self._duration > 120.0:
                         if (
-                            self._vav.supply_air_temperature
-                            > self._vav.virtual_target_temperature + 1
-                            or self._ahu.supply_air_temperature
-                            > self._vav.virtual_target_temperature + 2
+                                self._vav.supply_air_temperature
+                                > self._vav.virtual_target_temperature + 1
+                                or self._ahu.supply_air_temperature
+                                > self._vav.virtual_target_temperature + 2
                         ):
                             self._result.insufficient_cooling = True
 
     def run(self) -> None:
         if (
-            self._season == Season.heating
-            or self._vav.supply_air_temperature > self._vav.virtual_target_temperature
+                self._season == Season.heating
+                or self._vav.supply_air_temperature > self._vav.virtual_target_temperature
         ):
             if (
-                self._vav.virtual_realtime_temperature
-                < self._vav.virtual_target_temperature - 1
+                    self._vav.virtual_realtime_temperature
+                    < self._vav.virtual_target_temperature - 1
             ):
                 self.low_in_heating()
             elif (
-                self._vav.virtual_realtime_temperature
-                > self._vav.virtual_target_temperature + 1
+                    self._vav.virtual_realtime_temperature
+                    > self._vav.virtual_target_temperature + 1
             ):
                 self.high_in_heating()
         elif (
-            self._season == Season.cooling
-            or self._vav.supply_air_temperature < self._vav.virtual_target_temperature
+                self._season == Season.cooling
+                or self._vav.supply_air_temperature < self._vav.virtual_target_temperature
         ):
             if (
-                self._vav.virtual_realtime_temperature
-                < self._vav.virtual_target_temperature - 1
+                    self._vav.virtual_realtime_temperature
+                    < self._vav.virtual_target_temperature - 1
             ):
                 self.low_in_cooling()
             elif (
-                self._vav.virtual_realtime_temperature
-                > self._vav.virtual_target_temperature + 1
+                    self._vav.virtual_realtime_temperature
+                    > self._vav.virtual_target_temperature + 1
             ):
                 self.high_in_cooling()
 
@@ -269,13 +261,4 @@ class VRFDiagnotor(DiagnotorBase):
 
 
 def get_diagnosis_result(params: ThermalComfortDiagnosisRequest) -> FaultCategory:
-    if params.fcu_list:
-        for fcu in params.fcu_list:
-            fcu_diagnotor = FCUDiagnotor(
-                fcu,
-                params.ahu,
-                params.duration_minutes,
-                params.target_temp,
-                params.realtime_temp,
-                params.season,
-            )
+    pass

+ 2 - 4
app/controllers/equipment/ahu/basic.py

@@ -1,7 +1,5 @@
 # -*- coding: utf-8 -*-
 
-from typing import List, Optional
-
 import numpy as np
 
 from app.models.domain.devices import ACATAHFreqSetRequest
@@ -10,12 +8,12 @@ from app.schemas.system import ACAT
 
 
 class AHUController:
-    def __init__(self, equipment: Optional[AHU] = None, system: Optional[ACAT] = None):
+    def __init__(self, equipment: AHU | None, system: ACAT | None):
         super(AHUController, self).__init__()
         self._equipment = equipment
         self._system = system
 
-    async def build_freq_set(self, supply_air_temperature_set_duration: List, hot_rate: float) -> float:
+    async def build_freq_set(self, supply_air_temperature_set_duration: list[float], hot_rate: float) -> float:
         extent = 5
         if (
                 self._equipment.freq_set is None

+ 4 - 6
app/controllers/equipment/ahu/common.py

@@ -1,8 +1,6 @@
 # -*- coding: utf-8 -*-
 
 
-from typing import List, Tuple
-
 import numpy as np
 from loguru import logger
 
@@ -15,7 +13,7 @@ from app.utils.date import get_time_str
 
 
 class ATAHController:
-    def __init__(self, ahu: AHU, spaces: List[SpaceATAH], season: Season) -> None:
+    def __init__(self, ahu: AHU, spaces: list[SpaceATAH], season: Season) -> None:
         self._ahu = ahu
         self._spaces = spaces
         self._season = season
@@ -103,7 +101,7 @@ class ATAHController:
 
         return next_freq_set
 
-    def get_valid_spaces(self) -> List:
+    def get_valid_spaces(self) -> list[SpaceATAH]:
         valid_spaces = list()
         for sp in self._spaces:
             if sp.realtime_temperature and sp.temperature_target:
@@ -111,7 +109,7 @@ class ATAHController:
 
         return valid_spaces
 
-    def build_virtual_temperature(self) -> Tuple[float, float]:
+    def build_virtual_temperature(self) -> tuple[float, float]:
         valid_spaces = self.get_valid_spaces()
 
         if not valid_spaces:
@@ -143,7 +141,7 @@ class ATAHController:
 
         return virtual_realtime, virtual_target
 
-    def run(self) -> Tuple[str, float, float, float]:
+    def run(self) -> tuple[str, float, float, float]:
         try:
             virtual_realtime, virtual_target = self.build_virtual_temperature()
             new_switch_set = self.get_switch_set()

+ 1 - 3
app/controllers/equipment/ahu/supply_air_temperature_set.py

@@ -1,5 +1,3 @@
-from typing import List
-
 import arrow
 import numpy as np
 from loguru import logger
@@ -19,7 +17,7 @@ class ACATAHSupplyAirTemperatureController:
 
     def __init__(
             self,
-            vav_boxes_list: List[VAVBox],
+            vav_boxes_list: list[VAVBox],
             current_set: float,
             return_air: float,
             thermal_mode: ThermalMode,

+ 1 - 3
app/controllers/equipment/ahu/thermal_mode.py

@@ -1,5 +1,3 @@
-from typing import List
-
 from app.api.errors.iot import MissingIOTDataError
 from app.models.domain.devices import ACATAHThermalModeSetRequest
 from app.schemas.equipment import VAVBox
@@ -51,7 +49,7 @@ class ACATAHThermalModeController:
     Writen by WuXu
     """
 
-    def __init__(self, vav_boxes_list: List[VAVBox], season: Season):
+    def __init__(self, vav_boxes_list: list[VAVBox], season: Season):
         super(ACATAHThermalModeController, self).__init__()
         self.vav_boxes_list = vav_boxes_list
         self.season = season

+ 5 - 7
app/controllers/equipment/ashp/basic.py

@@ -1,7 +1,5 @@
 # -*- coding: utf-8 -*-
 
-from typing import Dict, List, Tuple
-
 import arrow
 import numpy as np
 
@@ -12,14 +10,14 @@ from app.schemas.season import Season
 
 
 class ASHPGroupController:
-    def __init__(self, ashp_list: List[ASHP], outdoor_temp_list: List[float], season: Season):
+    def __init__(self, ashp_list: list[ASHP], outdoor_temp_list: list[float], season: Season):
         self._season = season
         self._ashp_list = ashp_list
         self._outdoor_temp_list = outdoor_temp_list
         self._interval = 0
         self._is_warning = False
 
-    def initialization(self) -> Tuple[float, float]:
+    def initialization(self) -> tuple[float, float]:
         if self._season == Season.cooling:
             if self._outdoor_temp_list:
                 outdoor_temp_avg = np.mean(self._outdoor_temp_list)
@@ -77,7 +75,7 @@ class ASHPGroupController:
 
         return device_num, out_temp_set
 
-    def device_num_adjustment(self) -> Tuple[float, float]:
+    def device_num_adjustment(self) -> tuple[float, float]:
         out_temp_15_avg = np.mean(
             [np.mean(device.out_temp_15min) for device in self._ashp_list if device.running_status])
         out_temp_set_15_avg = np.mean(
@@ -192,11 +190,11 @@ class ASHPGroupController:
             out_temp_set = self.out_temp_set_adjustment()
             self.build_up(0, out_temp_set)
 
-    def get_results(self) -> Tuple[List[ASHP], float, bool]:
+    def get_results(self) -> tuple[list[ASHP], float, bool]:
         return self._ashp_list, self._interval, self._is_warning
 
 
-async def build_ashp_instructions(params: ASHPRequest) -> Dict:
+async def build_ashp_instructions(params: ASHPRequest) -> dict[str, list | float | bool]:
     controller = ASHPGroupController(params.device_list, params.outdoor_temp, params.season)
     try:
         controller.run()

+ 1 - 2
app/controllers/equipment/fcu/basic.py

@@ -1,6 +1,5 @@
 # -*- coding: utf-8 -*-
 
-from typing import Tuple
 
 from app.api.errors.iot import MissingIOTDataError
 from app.controllers.equipment.controller import EquipmentController
@@ -346,7 +345,7 @@ class ATFC4Controller(ATFC2Controller):
 
         return speed
 
-    def build_water_valve_set(self, new_switch_set: str) -> Tuple[str, str]:
+    def build_water_valve_set(self, new_switch_set: str) -> tuple[str, str]:
         if new_switch_set == "off":
             chill_water_valve_set = "off"
             hot_water_valve_set = "off"

+ 7 - 9
app/controllers/equipment/pau/freq_set.py

@@ -1,7 +1,5 @@
 # -*- coding: utf-8 -*-
 
-from typing import List, Tuple
-
 import numpy as np
 
 from app.api.errors.iot import MissingIOTDataError
@@ -26,7 +24,7 @@ class ACATFUFanFreqController:
         self._fresh_air_temperature = fresh_air_temperature
         self._season = season
 
-    def get_next_set(self, spaces_params: List[SpaceATFU], on_flag: bool) -> float:
+    def get_next_set(self, spaces_params: list[SpaceATFU], on_flag: bool) -> float:
         try:
             if self._season == Season.transition:
                 next_freq_set = self.get_transition_logic(spaces_params, on_flag)
@@ -42,7 +40,7 @@ class ACATFUFanFreqController:
 
         return next_freq_set
 
-    def get_transition_logic(self, spaces_params: List[SpaceATFU], on_flag: bool) -> float:
+    def get_transition_logic(self, spaces_params: list[SpaceATFU], on_flag: bool) -> float:
         temp_avg, co2_avg = self.get_avg(spaces_params)
         if on_flag:
             if self._fresh_air_temperature <= 16.0:
@@ -108,7 +106,7 @@ class ACATFUFanFreqController:
 
         return freq_set
 
-    def get_cooling_logic(self, spaces_params: List[SpaceATFU], on_flag: bool) -> float:
+    def get_cooling_logic(self, spaces_params: list[SpaceATFU], on_flag: bool) -> float:
         _, co2_avg = self.get_avg(spaces_params)
         if on_flag:
             freq_set = 30.0
@@ -133,14 +131,14 @@ class ACATFUFanFreqController:
 
         return freq_set
 
-    def get_heating_logic(self, spaces_params: List[SpaceATFU], on_flag: bool) -> float:
+    def get_heating_logic(self, spaces_params: list[SpaceATFU], on_flag: bool) -> float:
         # The same with cooling logic.
         freq_set = self.get_cooling_logic(spaces_params, on_flag)
 
         return freq_set
 
     @staticmethod
-    def get_avg(spaces_params: List[SpaceATFU]) -> Tuple[float, float]:
+    def get_avg(spaces_params: list[SpaceATFU]) -> tuple[float, float]:
         valid_temperature_list, valid_co2_list = list(), list()
         for space in spaces_params:
             if space.realtime_temperature:
@@ -163,7 +161,7 @@ class ACATFUFanFreqController:
         return temp_avg, co2_avg
 
     @staticmethod
-    def get_high_co2_ratio(spaces_params: List[SpaceATFU]) -> float:
+    def get_high_co2_ratio(spaces_params: list[SpaceATFU]) -> float:
         valid_co2_count, high_co2_count = 0, 0
         for space in spaces_params:
             if space.realtime_co2:
@@ -180,7 +178,7 @@ class ACATFUFanFreqController:
         return ratio
 
     @staticmethod
-    def hcho_logic(spaces_params: List[SpaceATFU], next_freq_set: float) -> float:
+    def hcho_logic(spaces_params: list[SpaceATFU], next_freq_set: float) -> float:
         diff = 0.0
         for space in spaces_params:
             if space.hcho:

+ 5 - 6
app/controllers/equipment/pau/switch.py

@@ -1,6 +1,5 @@
 # -*- coding: utf-8 -*-
 
-from typing import List
 
 import numpy as np
 from loguru import logger
@@ -42,22 +41,22 @@ class PAUSwitch(Switch):
 
 class PAUSwitchWithCO2(PAUSwitch):
     def __int__(self, equipment: PAU):
-        super(PAUSwitchWithCO2, self).__int__(equipment)
+        super(PAUSwitchWithCO2, self).__init__(equipment)
 
     @staticmethod
-    def co2_logic(co2_list: List[float]) -> SwitchSet:
+    def co2_logic(co2_list: list[float]) -> SwitchSet:
         co2_list = np.array(co2_list)
         action = SwitchSet.hold
         if co2_list.size > 0:
-            if co2_list.mean() >= 800.0 or co2_list.max() > 1000.0:
+            if co2_list.mean() >= 800.0 or co2_list.max(initial=0.0) > 1000.0:
                 action = SwitchSet.on
-            if co2_list.mean() <= 650.0 and co2_list.max() < 1000.0:
+            if co2_list.mean() <= 650.0 and co2_list.max(initial=0.0) < 1000.0:
                 action = SwitchSet.off
 
         return action
 
     async def run(self, is_workday: bool, break_start_time: str, break_end_time: str,
-                  co2_list: List[float]) -> SwitchSet:
+                  co2_list: list[float]) -> SwitchSet:
         action = await self.build_next_action(is_workday)
         break_action = self.break_time_action(break_start_time, break_end_time, is_workday)
         if break_action == SwitchSet.off:

+ 1 - 1
app/controllers/equipment/switch.py

@@ -4,9 +4,9 @@ from enum import Enum
 
 import arrow
 
+from app.api.errors.iot import MissingIOTDataError
 from app.schemas.equipment import BaseEquipment
 from app.utils.date import get_time_str, TIME_FMT
-from app.api.errors.iot import MissingIOTDataError
 
 
 class SwitchSet(str, Enum):

+ 5 - 6
app/controllers/equipment/vav.py

@@ -1,7 +1,6 @@
 # -*- coding: utf-8 -*-
 
 from operator import attrgetter
-from typing import List, Optional, Tuple
 
 import numpy as np
 from fastapi import HTTPException
@@ -33,7 +32,7 @@ class VAVController(EquipmentController):
 
         return strategy
 
-    async def build_virtual_temperature(self) -> Tuple[float, float]:
+    async def build_virtual_temperature(self) -> tuple[float, float]:
         target_list, realtime_list = [], []
         buffer_list = []
         strategy = await self.get_strategy()
@@ -102,14 +101,14 @@ class VAVControllerV2(VAVController):
     def __init__(
             self,
             equipment: VAVBox,
-            weights: Optional[List[SpaceWeight]] = None,
-            season: Optional[Season] = None,
+            weights: list[SpaceWeight] | None = None,
+            season: Season | None = None,
     ):
         super(VAVControllerV2, self).__init__(equipment)
         self.weights = weights
         self.season = season
 
-    def get_valid_spaces(self) -> List:
+    def get_valid_spaces(self) -> list[SpaceATVA]:
         valid_spaces = list()
         for sp in self.equipment.spaces:
             if sp.realtime_temperature and sp.temperature_target:
@@ -167,7 +166,7 @@ class VAVControllerV2(VAVController):
             self.equipment.virtual_target_temperature = np.NAN
             self.equipment.virtual_realtime_temperature = np.NAN
 
-    async def rectify(self) -> Tuple[float, float]:
+    async def rectify(self) -> tuple[float, float]:
         bad_spaces = list()
         valid_spaces = self.get_valid_spaces()
         for sp in valid_spaces:

+ 2 - 3
app/controllers/equipment/vrf/basic.py

@@ -1,5 +1,4 @@
 from datetime import datetime
-from typing import Dict, Tuple
 
 import arrow
 import numpy as np
@@ -278,7 +277,7 @@ class VRFController(EquipmentController):
         return self.device
 
 
-async def query_status_time(db: Session, device_id: str) -> Tuple[datetime, datetime]:
+async def query_status_time(db: Session, device_id: str) -> tuple[datetime, datetime]:
     feedback_time_in_db = blowy_feedback_time.get_time_by_device(db, device_id)
     if feedback_time_in_db:
         feedback_time = feedback_time_in_db.timestamp
@@ -307,7 +306,7 @@ async def query_status_time(db: Session, device_id: str) -> Tuple[datetime, date
     return feedback_time, high_time
 
 
-async def build_acatvi_instructions(params: ACATVIInstructionsRequest) -> Dict:
+async def build_acatvi_instructions(params: ACATVIInstructionsRequest) -> dict[str, str | float]:
     vrf = VRF(
         return_air_temp=params.return_air_temperature,
         current_temperature_set=params.current_temperature_set,

+ 2 - 7
app/controllers/location/ble/space.py

@@ -1,5 +1,4 @@
 from operator import attrgetter
-from typing import Dict, List
 
 from httpx import AsyncClient
 from loguru import logger
@@ -9,9 +8,7 @@ from app.services.platform import DataPlatformService
 
 
 class SpacePositioningController:
-    def __init__(
-        self, realtime_ibeacon_list: List[IBeaconBase], ibeacon_space_dict: Dict
-    ):
+    def __init__(self, realtime_ibeacon_list: list[IBeaconBase], ibeacon_space_dict: dict[str, str]):
         super(SpacePositioningController, self).__init__()
         self.realtime_ibeacon_list = realtime_ibeacon_list
         self.ibeacon_space_dict = ibeacon_space_dict
@@ -37,9 +34,7 @@ class SpacePositioningController:
 
 
 @logger.catch()
-async def get_space_location(
-    project_id: str, realtime_ibeacon_list: List[IBeaconBase]
-) -> str:
+async def get_space_location(project_id: str, realtime_ibeacon_list: list[IBeaconBase]) -> str:
     async with AsyncClient() as client:
         platform = DataPlatformService(client, project_id)
         spaces = await platform.get_items_by_category("Sp")

+ 10 - 12
app/controllers/nlp/meeting.py

@@ -1,5 +1,3 @@
-from typing import Dict, List, Tuple
-
 from httpx import AsyncClient
 from loguru import logger
 
@@ -13,7 +11,7 @@ class MeetingInfoCatcher:
         self.nlp_service = nlp_service
         self.duckling = duckling
 
-    async def extract_time(self, sentence: str) -> Tuple[str, str, int]:
+    async def extract_time(self, sentence: str) -> tuple[str, str, int]:
         start_time, end_time, duration = "", "", -1
         parsed = await self.duckling.parse(sentence)
         for dim in parsed:
@@ -34,18 +32,18 @@ class MeetingInfoCatcher:
                 for item in dp_tokens:
                     if item.HeadId == index:
                         if (
-                            await self.nlp_service.get_word_similarity(item.Word, "小")
-                            > 0.9
+                                await self.nlp_service.get_word_similarity(item.Word, "小")
+                                > 0.9
                         ):
                             size = "small"
                         if (
-                            await self.nlp_service.get_word_similarity(item.Word, "中")
-                            > 0.9
+                                await self.nlp_service.get_word_similarity(item.Word, "中")
+                                > 0.9
                         ):
                             size = "medium"
                         if (
-                            await self.nlp_service.get_word_similarity(item.Word, "大")
-                            > 0.9
+                                await self.nlp_service.get_word_similarity(item.Word, "大")
+                                > 0.9
                         ):
                             size = "large"
                 break
@@ -57,7 +55,7 @@ class MeetingInfoCatcher:
 
         return summarization
 
-    async def extract_name(self, sentence: str) -> List[str]:
+    async def extract_name(self, sentence: str) -> list[str]:
         _, ner_tokens = await self.nlp_service.get_lexical_analysis_result(sentence)
         name_list = []
         if ner_tokens:
@@ -67,7 +65,7 @@ class MeetingInfoCatcher:
 
         return name_list
 
-    async def run(self, sentence: str) -> Tuple:
+    async def run(self, sentence: str) -> tuple[str, str, int, str, str, list[str]]:
         similarity = await self.nlp_service.get_text_similarity_result(
             "我要开会", [sentence]
         )
@@ -83,7 +81,7 @@ class MeetingInfoCatcher:
 
 
 @logger.catch()
-async def get_caught_result(sentence: str) -> Tuple:
+async def get_caught_result(sentence: str) -> tuple[str, str, int, str, str, list[str]]:
     async with AsyncClient() as client:
         duckling = Duckling(client)
         service = TencentNLP()

+ 53 - 78
app/controllers/targets/temperature.py

@@ -1,7 +1,6 @@
 # -*- coding: utf-8 -*-
 
 from abc import ABCMeta, abstractmethod
-from typing import Dict, Tuple
 
 import arrow
 import numpy as np
@@ -25,24 +24,16 @@ class StepSizeCalculator:
     Calculate adjustment step size of environment target when a user send feedback.
     """
 
-    def __init__(self, weight: Dict):
+    def __init__(self, weight: dict[str, int]):
         self.weight = weight
 
-    def run(
-        self,
-        realtime_temperature: float,
-        comfortable_temperature: float,
-        feedback: FeedbackValue,
-    ) -> float:
+    def run(self, realtime_temperature: float, comfortable_temperature: float, feedback: FeedbackValue) -> float:
         if feedback == FeedbackValue.so_hot or feedback == FeedbackValue.a_little_hot:
-            base_step_size = 1.8 / (
-                1 + np.exp((comfortable_temperature - realtime_temperature) / 2)
-            )
+            base_step_size = 1.8 / (1 + np.exp((comfortable_temperature - realtime_temperature) / 2))
         else:
-            base_step_size = 1.8 / (
-                1 + np.exp((realtime_temperature - comfortable_temperature) / 2)
-            )
-        return self.weight.get(feedback.value) * base_step_size
+            base_step_size = 1.8 / (1 + np.exp((realtime_temperature - comfortable_temperature) / 2))
+
+        return self.weight.get(str(feedback.value)) * base_step_size
 
 
 class NewTargetBuilder(metaclass=ABCMeta):
@@ -76,7 +67,7 @@ class NewTemperatureTargetBuilder(NewTargetBuilder):
     """
 
     def __init__(
-        self, realtime_temperature: float, actual_target: float, step_size: float
+            self, realtime_temperature: float, actual_target: float, step_size: float
     ):
         self.realtime_temperature = realtime_temperature
         self.actual_target = actual_target
@@ -104,11 +95,11 @@ class TemporaryTargetInit:
         self.default_target = default_target
 
     def build(
-        self,
-        extent: float,
-        season: Season,
-        realtime_temperature: float,
-    ) -> Tuple[float, float]:
+            self,
+            extent: float,
+            season: Season,
+            realtime_temperature: float,
+    ) -> tuple[float, float]:
         if np.isnan(realtime_temperature):
             upper_bound, lower_bound = (
                 self.default_target + 1.0,
@@ -124,7 +115,7 @@ class TemporaryTargetInit:
             clipper = Clipper()
             actual_target = clipper.cut(actual_target)
             upper_bound, lower_bound = actual_target + (extent / 2), actual_target - (
-                extent / 2
+                    extent / 2
             )
 
         return lower_bound, upper_bound
@@ -136,7 +127,7 @@ class GlobalTargetBaseBuilder(metaclass=ABCMeta):
     """
 
     @abstractmethod
-    def build(self, new_actual_target: float) -> Dict:
+    def build(self, new_actual_target: float) -> dict:
         raise NotImplementedError
 
 
@@ -148,20 +139,11 @@ class SimpleGlobalTemperatureTargetBuilder(GlobalTargetBaseBuilder):
     def __init__(self, current_global_target: TemperatureTarget):
         self.current_global_target = current_global_target
 
-    def build(self, new_actual_target: float) -> Dict:
+    def build(self, new_actual_target: float) -> dict:
         result = {}
         half_extent = self.current_global_target.extent / 2
-        for time_index in self.current_global_target.target_schedule[
-            "temperatureMin"
-        ].keys():
-            result.update(
-                {
-                    time_index: [
-                        new_actual_target - half_extent,
-                        new_actual_target + half_extent,
-                    ]
-                }
-            )
+        for time_index in self.current_global_target.target_schedule["temperatureMin"].keys():
+            result.update({time_index: [new_actual_target - half_extent, new_actual_target + half_extent]})
 
         return result
 
@@ -172,12 +154,12 @@ class ExpSmoothingTemperatureTargetBuilder(GlobalTargetBaseBuilder):
     """
 
     def __init__(
-        self, current_global_target: TemperatureTarget, previous_changes: pd.DataFrame
+            self, current_global_target: TemperatureTarget, previous_changes: pd.DataFrame
     ):
         self.current_global_target = current_global_target
         self.previous_changes = previous_changes
 
-    def build(self, new_actual_target: float) -> Dict:
+    def build(self, new_actual_target: float) -> dict:
         now_time = arrow.get(get_time_str(), TIME_FMT).time().strftime("%H%M%S")
         half_extent = self.current_global_target.extent / 2
         previous_changes = pd.concat(
@@ -194,20 +176,13 @@ class ExpSmoothingTemperatureTargetBuilder(GlobalTargetBaseBuilder):
         time_index = self.current_global_target.target_schedule["temperatureMin"].keys()
         for item in time_index:
             previous_changes["delta"] = previous_changes["timestamp"].apply(
-                lambda x: abs(
-                    arrow.get(str(x), "HHmmss") - arrow.get(item, "HHmmss")
-                ).seconds
-                // (15 * 60)
-            )
-            previous_changes["weight2"] = previous_changes["delta"].apply(
-                lambda x: 0.5 ** x
-            )
-            previous_changes["weight"] = (
-                previous_changes["weight1"] * previous_changes["weight2"]
+                lambda x: abs(arrow.get(str(x), "HHmmss") - arrow.get(item, "HHmmss")).seconds // (15 * 60)
             )
+            previous_changes["weight2"] = previous_changes["delta"].apply(lambda x: 0.5 ** x)
+            previous_changes["weight"] = (previous_changes["weight1"] * previous_changes["weight2"])
             temp_target = (
-                previous_changes["value"] * previous_changes["weight"]
-            ).sum() / previous_changes["weight"].sum()
+                                  previous_changes["value"] * previous_changes["weight"]
+                          ).sum() / previous_changes["weight"].sum()
             new_targets.update(
                 {item: [temp_target - half_extent, temp_target + half_extent]}
             )
@@ -224,7 +199,7 @@ class TemporaryTargetBuilder:
         self.lower_target = lower_target
         self.upper_target = upper_target
 
-    def build(self) -> Dict:
+    def build(self) -> dict:
         now_str = get_time_str()
         time_index = (
             arrow.get(
@@ -255,7 +230,7 @@ class Packer(metaclass=ABCMeta):
     """
 
     @abstractmethod
-    def run(self) -> Dict:
+    def run(self) -> dict:
         raise NotImplementedError
 
 
@@ -306,7 +281,7 @@ class TemperatureTargetCarrier(Carrier):
             "season": season,
         }
 
-    async def get_result(self) -> Dict:
+    async def get_result(self) -> dict:
         await self.fetch_all()
         return self.result
 
@@ -323,7 +298,7 @@ class TemperatureTargetV2Carrier(TemperatureTargetCarrier):
 
         self.result.update({"previous_changes": previous_changes["temperature"]})
 
-    async def get_result(self) -> Dict:
+    async def get_result(self) -> dict:
         await self.fetch_all()
         await self.fetch_previous_changes()
         return self.result
@@ -341,8 +316,8 @@ class TemperatureTargetPacker:
         all_day_targets = self.result["all_day_targets"]
         if len(all_day_targets) > 0:
             extent = (
-                all_day_targets["temperatureMax"].iloc[0]
-                - all_day_targets["temperatureMin"].iloc[0]
+                    all_day_targets["temperatureMax"].iloc[0]
+                    - all_day_targets["temperatureMin"].iloc[0]
             )
             temperature_all_day_targets = (
                 all_day_targets[["temperatureMin", "temperatureMax"]].copy().to_dict()
@@ -359,7 +334,7 @@ class TemperatureTargetPacker:
         target = TemperatureTarget(**target_params)
         self.result.update({"target": target})
 
-    def get_result(self) -> Dict:
+    def get_result(self) -> dict:
         self.get_temperature_target()
         return self.result
 
@@ -373,7 +348,7 @@ class TargetDeliver:
         self.project_id = project_id
         self.space_id = space_id
 
-    async def send(self, controlled_result: Dict):
+    async def send(self, controlled_result: dict):
         async with AsyncClient() as client:
             transfer = SpaceInfoService(client, self.project_id, self.space_id)
             if controlled_result["need_switch_off"]:
@@ -387,8 +362,8 @@ class TargetDeliver:
                     "temperature", controlled_result["new_global_target"], "1"
                 )
             if (
-                controlled_result["new_actual_target"] > 0
-                and controlled_result["need_run_room_control"]
+                    controlled_result["new_actual_target"] > 0
+                    and controlled_result["need_run_room_control"]
             ):
                 await transfer.env_database_set(
                     "temperature", controlled_result["new_actual_target"]
@@ -407,10 +382,10 @@ class WeightFlagDeliver:
 
     def is_temperature_feedback(self) -> bool:
         if (
-            self.feedback == FeedbackValue.a_little_hot
-            or self.feedback == FeedbackValue.so_hot
-            or self.feedback == FeedbackValue.a_little_cold
-            or self.feedback == FeedbackValue.so_cold
+                self.feedback == FeedbackValue.a_little_hot
+                or self.feedback == FeedbackValue.so_hot
+                or self.feedback == FeedbackValue.a_little_cold
+                or self.feedback == FeedbackValue.so_cold
         ):
             flag = True
         else:
@@ -431,7 +406,7 @@ class TemperatureTargetController:
     Primary flow of temperature target adjustment for Sequoia.
     """
 
-    def __init__(self, data: Dict):
+    def __init__(self, data: dict):
         self.data = data
         self.result = {}
 
@@ -455,10 +430,10 @@ class TemperatureTargetController:
                     new_lower, new_upper
                 ).build()
         elif (
-            feedback == FeedbackValue.a_little_hot
-            or feedback == FeedbackValue.a_little_cold
-            or feedback == FeedbackValue.so_hot
-            or feedback == FeedbackValue.so_cold
+                feedback == FeedbackValue.a_little_hot
+                or feedback == FeedbackValue.a_little_cold
+                or feedback == FeedbackValue.so_hot
+                or feedback == FeedbackValue.so_cold
         ):
             step_size = StepSizeCalculator(TEMPERATURE_TARGET_WEIGHT).run(
                 self.data["realtime_temperature"], 25.0, feedback
@@ -486,7 +461,7 @@ class TemperatureTargetController:
             }
         )
 
-    def get_result(self) -> Dict:
+    def get_result(self) -> dict:
         return self.result
 
 
@@ -495,7 +470,7 @@ class TemperatureTargetControllerV2:
     Primary flow of temperature target adjustment for Zhonghai.
     """
 
-    def __init__(self, data: Dict):
+    def __init__(self, data: dict):
         self.data = data
         self.result = {}
 
@@ -519,10 +494,10 @@ class TemperatureTargetControllerV2:
                     new_lower, new_upper
                 ).build()
         elif (
-            feedback == FeedbackValue.a_little_hot
-            or feedback == FeedbackValue.a_little_cold
-            or feedback == FeedbackValue.so_hot
-            or feedback == FeedbackValue.so_cold
+                feedback == FeedbackValue.a_little_hot
+                or feedback == FeedbackValue.a_little_cold
+                or feedback == FeedbackValue.so_hot
+                or feedback == FeedbackValue.so_cold
         ):
             step_size = StepSizeCalculator(TEMPERATURE_TARGET_WEIGHT).run(
                 self.data["realtime_temperature"], 25.0, feedback
@@ -550,13 +525,13 @@ class TemperatureTargetControllerV2:
             }
         )
 
-    def get_result(self) -> Dict:
+    def get_result(self) -> dict:
         return self.result
 
 
 @logger.catch()
 async def temperature_target_control_v1(
-    project_id: str, space_id: str, feedback: FeedbackValue
+        project_id: str, space_id: str, feedback: FeedbackValue
 ) -> bool:
     temperature_target_raw_data = await TemperatureTargetCarrier(
         project_id, space_id
@@ -576,7 +551,7 @@ async def temperature_target_control_v1(
 
 @logger.catch()
 async def temperature_target_control_v2(
-    project_id: str, space_id: str, feedback: FeedbackValue
+        project_id: str, space_id: str, feedback: FeedbackValue
 ) -> bool:
     temperature_target_raw_data = await TemperatureTargetV2Carrier(
         project_id, space_id
@@ -594,7 +569,7 @@ async def temperature_target_control_v2(
 
 @logger.catch()
 async def get_target_after_feedback(
-    project_id: str, space_id: str, feedback: FeedbackValue
+        project_id: str, space_id: str, feedback: FeedbackValue
 ) -> float:
     if project_id == "Pj1101050030" or project_id == "Pj1101140020" or project_id == "Pj1101050039":
         temperature_target_raw_data = await TemperatureTargetCarrier(

+ 6 - 7
app/core/config.py

@@ -1,7 +1,6 @@
 # -*- coding: utf-8 -*-
 
 import os
-from typing import Any, Dict, Optional
 
 from pydantic import (
     AnyHttpUrl,
@@ -42,21 +41,21 @@ class Settings(BaseSettings):
     REDIS_DB: int
     REDIS_PASSWORD: str
 
-    MILVUS_HOST: Optional[str] = None
-    MILVUS_PORT: Optional[str] = None
-    METRIC_TYPE: Optional[str] = None
-    VECTOR_DIMENSION: Optional[int] = None
+    MILVUS_HOST: str | None
+    MILVUS_PORT: str | None
+    METRIC_TYPE: str | None
+    VECTOR_DIMENSION: int | None
 
     POSTGRES_SERVER: str
     POSTGRES_USER: str
     POSTGRES_PASSWORD: str
     POSTGRES_DB: str
-    SQLALCHEMY_DATABASE_URL: Optional[PostgresDsn] = None
+    SQLALCHEMY_DATABASE_URL: PostgresDsn | None
 
     NEED_MILVUS: str
 
     @validator("SQLALCHEMY_DATABASE_URL", pre=True)
-    def assemble_db_connection(cls, v: Optional[str], values: Dict[str, Any]) -> Any:
+    def assemble_db_connection(cls, v: str | None, values: dict[str, str | int | bool]):
         if isinstance(v, str):
             return v
         return PostgresDsn.build(

+ 2 - 6
app/core/events.py

@@ -1,17 +1,13 @@
 # -*- coding: utf-8 -*-
 
 import os
-from typing import Callable, Optional
+from typing import Callable
 
-from fastapi import FastAPI
-
-# from app.controllers.equipment.events import regulate_ahu_freq
 from app.services.milvus_helpers import get_milvus_cli
 
 
-def create_start_app_handler(app: Optional[FastAPI] = None) -> Callable:
+def create_start_app_handler() -> Callable:
     async def start_app() -> None:
-        # await regulate_ahu_freq()
         if os.getenv("NEED_MILVUS", "yes") == "yes":
             await get_milvus_cli()
 

+ 1 - 1
app/core/logger.py

@@ -7,7 +7,7 @@ from loguru import logger
 
 class InterceptHandler(logging.Handler):
     """
-    Default handler from examples in loguru documentaion.
+    Default handler from examples in loguru documentation.
     See https://loguru.readthedocs.io/en/stable/overview.html#entirely-compatible-with-standard-logging
     """
 

+ 9 - 9
app/crud/base.py

@@ -1,4 +1,4 @@
-from typing import Any, Dict, Generic, List, Optional, Type, TypeVar, Union
+from typing import Any, Generic, Type, TypeVar
 
 from fastapi.encoders import jsonable_encoder
 from pydantic import BaseModel
@@ -23,12 +23,12 @@ class CRUDBase(Generic[ModelType, CreateSchemaType, UpdateSchemaType]):
         """
         self.model = model
 
-    def get(self, db: Session, id: Any) -> Optional[ModelType]:
+    def get(self, db: Session, id: Any) -> ModelType | None:
         return db.query(self.model).filter(self.model.id == id).first()
 
     def get_multi(
-        self, db: Session, *, skip: int = 0, limit: int = 100
-    ) -> List[ModelType]:
+            self, db: Session, *, skip: int = 0, limit: int = 100
+    ) -> list[ModelType]:
         return db.query(self.model).offset(skip).limit(limit).all()
 
     def create(self, db: Session, *, obj_in: CreateSchemaType) -> ModelType:
@@ -40,11 +40,11 @@ class CRUDBase(Generic[ModelType, CreateSchemaType, UpdateSchemaType]):
         return db_obj
 
     def update(
-        self,
-        db: Session,
-        *,
-        db_obj: ModelType,
-        obj_in: Union[UpdateSchemaType, Dict[str, Any]]
+            self,
+            db: Session,
+            *,
+            db_obj: ModelType,
+            obj_in: UpdateSchemaType | dict[str, Any]
     ) -> ModelType:
         obj_data = jsonable_encoder(db_obj)
         if isinstance(obj_in, dict):

+ 4 - 6
app/crud/device/status_timestamp.py

@@ -1,5 +1,3 @@
-from app.schemas.device.device import Device
-from typing import Optional
 from sqlalchemy.orm import Session
 
 from app.crud.base import CRUDBase
@@ -20,8 +18,8 @@ class CRUDBlowyFeedbackTime(
     ]
 ):
     def get_time_by_device(
-        self, db: Session, device_id: str
-    ) -> Optional[BlowyFeedbackTime]:
+            self, db: Session, device_id: str
+    ) -> BlowyFeedbackTime | None:
         return (
             db.query(self.model)
             .filter(BlowyFeedbackTime.device_id == device_id)
@@ -33,8 +31,8 @@ class CRUDHighSpeedTime(
     CRUDBase[HighSpeedTime, HighSpeedTimeCreate, HighSpeedTimeUpdate]
 ):
     def get_time_by_device(
-        self, db: Session, device_id: str
-    ) -> Optional[HighSpeedTime]:
+            self, db: Session, device_id: str
+    ) -> HighSpeedTime | None:
         return db.query(self.model).filter(HighSpeedTime.device_id == device_id).first()
 
 

+ 2 - 3
app/crud/model_path/early_start.py

@@ -1,4 +1,3 @@
-from typing import Optional
 from sqlalchemy.orm import Session
 
 from app.crud.base import CRUDBase
@@ -17,8 +16,8 @@ class CRUDModelPathEarlyStartDTR(
     ]
 ):
     def get_path_by_device(
-        self, db: Session, device_id: str
-    ) -> Optional[EarlyStartDTRModelPath]:
+            self, db: Session, device_id: str
+    ) -> EarlyStartDTRModelPath | None:
         return (
             db.query(self.model)
             .filter(EarlyStartDTRModelPath.device_id == device_id)

+ 3 - 4
app/crud/space/weight.py

@@ -1,6 +1,5 @@
 # -*- coding: utf-8 -*-
 
-from typing import List
 
 from fastapi.encoders import jsonable_encoder
 from sqlalchemy.orm import Session
@@ -10,11 +9,11 @@ from app.schemas.sapce_weight import SpaceWeightCreate, SpaceWeightUpdate
 from app.utils.date import get_time_str
 
 
-def get_weights_by_space(db: Session, space_id: str) -> List[VAVRoomWeight]:
+def get_weights_by_space(db: Session, space_id: str) -> list[VAVRoomWeight]:
     return db.query(VAVRoomWeight).filter(VAVRoomWeight.space_id == space_id).all()
 
 
-def get_weights_by_vav(db: Session, vav_id: str) -> List[VAVRoomWeight]:
+def get_weights_by_vav(db: Session, vav_id: str) -> list[VAVRoomWeight]:
     return db.query(VAVRoomWeight).filter(VAVRoomWeight.vav_box_id == vav_id).all()
 
 
@@ -32,7 +31,7 @@ def create_weight(db: Session, weight: SpaceWeightCreate) -> VAVRoomWeight:
 
 
 def update_weight(
-    db: Session, db_weight: VAVRoomWeight, weight_in: SpaceWeightUpdate
+        db: Session, db_weight: VAVRoomWeight, weight_in: SpaceWeightUpdate
 ) -> VAVRoomWeight:
     weight_data = jsonable_encoder(db_weight)
     update_data = weight_in.dict(exclude_unset=True)

+ 1 - 1
app/models/domain/algorithms.py

@@ -11,7 +11,7 @@ class GraphColoringResponse(BaseModel):
 
 
 class GraphColoringRequest(BaseModel):
-    graph: Dict[str, List]
+    graph: dict[str, list[str]]
 
 
 class AttendeesRecommendationRequest(BaseModel):

+ 92 - 95
app/models/domain/devices.py

@@ -1,5 +1,4 @@
 from enum import Enum
-from typing import List, Optional
 
 from pydantic import BaseModel, Field
 
@@ -26,27 +25,27 @@ class Speed(str, Enum):
 
 class ACATVIInstructionsRequest(BaseModel):
     device_id: str
-    return_air_temperature: Optional[float]
-    running_status: Optional[bool]
+    return_air_temperature: float | None
+    running_status: bool | None
     work_mode: VRFMode
-    current_speed: Optional[str]
-    current_temperature_set: Optional[float]
-    space_temperature_target: Optional[float]
-    space_realtime_temperature: Optional[float]
+    current_speed: str | None
+    current_temperature_set: float | None
+    space_temperature_target: float | None
+    space_realtime_temperature: float | None
     feedback: FeedbackValue
-    on_time: Optional[str]
-    off_time: Optional[str]
+    on_time: str | None
+    off_time: str | None
 
 
 class ACATVIInstructionsResponse(BaseModel):
-    switch_set: Optional[str]
-    speed_set: Optional[str]
-    temperature_set: Optional[float]
+    switch_set: str | None
+    speed_set: str | None
+    temperature_set: float | None
 
 
 class ACATVIModeRequest(BaseModel):
     season: Season
-    space_temperature_list: List[float]
+    space_temperature_list: list[float]
 
 
 class ACATVIModeResponse(BaseModel):
@@ -56,10 +55,10 @@ class ACATVIModeResponse(BaseModel):
 class ACATFCInstructionsRequestBase(BaseModel):
     device_id: str
     season: str
-    space_temperature_target: Optional[float]
-    space_realtime_temperature: Optional[float]
-    running_status: Optional[bool]
-    speed: Optional[Speed]
+    space_temperature_target: float | None
+    space_realtime_temperature: float | None
+    running_status: bool | None
+    speed: Speed | None
     feedback: FeedbackValue
 
 
@@ -95,10 +94,10 @@ class ACATFCInstructionsResponse(BaseModel):
 
 class ACATFCEarlyStartPredictionRequest(BaseModel):
     season: Season
-    space_id: Optional[str]
+    space_id: str | None
     device_id: str
-    space_realtime_temperature: Optional[float]
-    outdoor_realtime_temperature: Optional[float]
+    space_realtime_temperature: float | None
+    outdoor_realtime_temperature: float | None
 
 
 class ACATFCEarlyStartPredictionResponse(BaseModel):
@@ -106,53 +105,51 @@ class ACATFCEarlyStartPredictionResponse(BaseModel):
 
 
 class Space(BaseModel):
-    realtime_temperature: Optional[float]
+    realtime_temperature: float | None
 
 
 class ACATVASpace(Space):
-    temperature_target: Optional[float]
-    vav_default_weight: Optional[float]
-    vav_temporary_weight: Optional[float]
-    vav_temporary_update_time: Optional[str]
+    temperature_target: float | None
+    vav_default_weight: float | None
+    vav_temporary_weight: float | None
+    vav_temporary_update_time: str | None
 
 
 class ACATAHSpace(Space):
-    temperature_target: Optional[float]
-    ahu_default_weight: Optional[float]
-    ahu_temporary_weight: Optional[float]
-    ahu_temporary_update_time: Optional[str]
+    temperature_target: float | None
+    ahu_default_weight: float | None
+    ahu_temporary_weight: float | None
+    ahu_temporary_update_time: str | None
 
 
 class ACATFUSpace(Space):
-    realtime_co2: Optional[float]
-    hcho: Optional[float]
+    realtime_co2: float | None
+    hcho: float | None
 
 
 class ACATVAInstructionsRequestBase(BaseModel):
     device_id: str
-    spaces: List[ACATVASpace]
+    spaces: list[ACATVASpace]
 
 
 class ACATVAInstructionsRequest(ACATVAInstructionsRequestBase):
     season: str
-    supply_air_temperature: Optional[float]
-    acatah_supply_air_temperature: Optional[float]
-    supply_air_flow: Optional[float]
-    supply_air_flow_lower_limit: Optional[float]
-    supply_air_flow_upper_limit: Optional[float]
+    supply_air_temperature: float | None
+    acatah_supply_air_temperature: float | None
+    supply_air_flow: float | None
+    supply_air_flow_lower_limit: float | None
+    supply_air_flow_upper_limit: float | None
 
 
 class ACATVAInstructionsRequestV2(ACATVAInstructionsRequestBase):
     season: str
-    return_air_temperature: Optional[float]
+    return_air_temperature: float | None
 
 
 class ACATVAInstructionsResponse(BaseModel):
     supply_air_flow_set: float = Field(None, alias="SupplyAirFlowSet")
     virtual_temperature_target_set: float = Field(None, alias="TargetTemperatureSet")
-    virtual_realtime_temperature: float = Field(
-        None, alias="VirtualRealtimeTemperature"
-    )
+    virtual_realtime_temperature: float = Field(None, alias="VirtualRealtimeTemperature")
 
 
 class ACATVAInstructionsResponseV2(BaseModel):
@@ -163,11 +160,11 @@ class ACATVAInstructionsResponseV2(BaseModel):
 
 class ACATAHFreqSetRequest(BaseModel):
     device_id: str
-    system_supply_static_press: Optional[float]
-    system_supply_static_press_set: Optional[float]
-    current_freq_set: Optional[float]
-    supply_air_temperature_set_list: List[float]
-    spaces_hot_rate: Optional[float]
+    system_supply_static_press: float | None
+    system_supply_static_press_set: float | None
+    current_freq_set: float | None
+    supply_air_temperature_set_list: list[float]
+    spaces_hot_rate: float | None
 
 
 class ACATAHFreqSetResponse(BaseModel):
@@ -177,32 +174,32 @@ class ACATAHFreqSetResponse(BaseModel):
 class ACATAHInstructionsRequest(BaseModel):
     device_id: str
     season: Season
-    spaces: List[ACATAHSpace]
-    running_status: Optional[bool]
-    return_air_temperature: Optional[float]
-    return_air_temperature_set: Optional[float]
-    supply_air_temperature: Optional[float]
-    supply_air_temperature_set: Optional[float]
-    freq: Optional[float]
-    freq_set: Optional[float]
-    fan_freq_upper_limit_set: Optional[float]
-    fan_freq_lower_limit_set: Optional[float]
+    spaces: ACATAHSpace | None
+    running_status: bool | None
+    return_air_temperature: float | None
+    return_air_temperature_set: float | None
+    supply_air_temperature: float | None
+    supply_air_temperature_set: float | None
+    freq: float | None
+    freq_set: float | None
+    fan_freq_upper_limit_set: float | None
+    fan_freq_lower_limit_set: float | None
 
 
 class ACATAHInstructionsResponse(BaseModel):
     switch_set: str
-    return_air_temp_set: Optional[float]
-    supply_air_temp_set: Optional[float]
-    freq_set: Optional[float]
+    return_air_temp_set: float | None
+    supply_air_temp_set: float | None
+    freq_set: float | None
 
 
 class SwitchSetRequestBase(BaseModel):
     device_id: str
-    running_status: Optional[bool]
-    in_cloud_status: Optional[bool]
-    on_time: Optional[str]
-    off_time: Optional[str]
-    is_workday: Optional[bool]
+    running_status: bool | None
+    in_cloud_status: bool | None
+    on_time: str | None
+    off_time: str | None
+    is_workday: bool | None
 
 
 class SwitchSetResponseBase(BaseModel):
@@ -218,12 +215,12 @@ class ACVTSFSwitchSetResponse(SwitchSetResponseBase):
 
 
 class ACATFUSwitchSetRequest(SwitchSetRequestBase):
-    break_start_time: Optional[str]
-    break_end_time: Optional[str]
+    break_start_time: str | None
+    break_end_time: str | None
 
 
 class ACATFUCO2SwitchSetRequest(ACATFUSwitchSetRequest):
-    co2_list: List[float]
+    co2_list: list[float]
 
 
 class ACATFUSwitchSetResponse(SwitchSetResponseBase):
@@ -231,8 +228,8 @@ class ACATFUSwitchSetResponse(SwitchSetResponseBase):
 
 
 class ACATAHSwitchSetRequest(SwitchSetRequestBase):
-    break_start_time: Optional[str]
-    break_end_time: Optional[str]
+    break_start_time: str | None
+    break_end_time: str | None
 
 
 class ACATAHSwitchSetResponse(SwitchSetResponseBase):
@@ -241,19 +238,19 @@ class ACATAHSwitchSetResponse(SwitchSetResponseBase):
 
 class VAV(BaseModel):
     id: str
-    virtual_realtime_temperature: Optional[float]
-    virtual_temperature_target: Optional[float]
-    supply_air_flow_lower_limit: Optional[float]
-    supply_air_flow_upper_limit: Optional[float]
-    supply_air_flow_set: Optional[float]
-    supply_air_temperature: Optional[float]
-    valve_opening: Optional[float]
+    virtual_realtime_temperature: float | None
+    virtual_temperature_target: float | None
+    supply_air_flow_lower_limit: float | None
+    supply_air_flow_upper_limit: float | None
+    supply_air_flow_set: float | None
+    supply_air_temperature: float | None
+    valve_opening: float | None
 
 
 class ACATAHRequestBase(BaseModel):
     device_id: str
     season: str
-    vav_list: List[VAV]
+    vav_list: list[VAV]
 
 
 class ACATAHThermalModeSetRequest(ACATAHRequestBase):
@@ -265,13 +262,13 @@ class ACATAHThermalModeSetResponse(BaseModel):
 
 
 class ACATAHSupplyAirTempSetRequest(ACATAHRequestBase):
-    supply_air_temperature: Optional[float]
-    supply_air_temperature_set: Optional[float]
-    return_air_temperature: Optional[float]
-    chill_water_valve_opening_set_list: List[float]
-    hot_water_valve_opening_set_list: List[float]
-    equip_switch_set_list: List[float]
-    is_clear_day: Optional[bool]
+    supply_air_temperature: float | None
+    supply_air_temperature_set: float | None
+    return_air_temperature: float | None
+    chill_water_valve_opening_set_list: list[float]
+    hot_water_valve_opening_set_list: list[float]
+    equip_switch_set_list: list[float]
+    is_clear_day: bool | None
 
 
 class ACATAHSupplyAirTempSetResponse(BaseModel):
@@ -281,10 +278,10 @@ class ACATAHSupplyAirTempSetResponse(BaseModel):
 class ACATFUSupplyAirTempSetRequest(BaseModel):
     device_id: str
     season: Season
-    supply_air_temperature_set: Optional[float]
-    hot_ratio: Optional[float]
-    cold_ratio: Optional[float]
-    running_status_list: List[float]
+    supply_air_temperature_set: float | None
+    hot_ratio: float | None
+    cold_ratio: float | None
+    running_status_list: list[float]
 
 
 class ACATFUSupplyAirTempSetResponse(BaseModel):
@@ -293,11 +290,11 @@ class ACATFUSupplyAirTempSetResponse(BaseModel):
 
 class ACATFUFreqSetRequest(BaseModel):
     device_id: str
-    freq: Optional[float]
-    fresh_air_temperature: Optional[float]
-    spaces: List[ACATFUSpace]
+    freq: float | None
+    fresh_air_temperature: float | None
+    spaces: list[ACATFUSpace]
     season: Season
-    running_status_list: List[float]
+    running_status_list: list[float]
 
 
 class ACATFUFreqSetResponse(BaseModel):
@@ -306,11 +303,11 @@ class ACATFUFreqSetResponse(BaseModel):
 
 class ASHPRequest(BaseModel):
     season: Season
-    outdoor_temp: List[float]  # 30min
-    device_list: List[ASHP]
+    outdoor_temp: list[float]  # 30min
+    device_list: list[ASHP]
 
 
 class ASHPResponse(BaseModel):
-    device_list: List[ASHP]
+    device_list: list[ASHP]
     interval: float
     is_warning: bool

+ 5 - 7
app/models/domain/diagnosis.py

@@ -1,9 +1,7 @@
-from typing import List, Optional
-
 from pydantic import BaseModel
 
-from app.schemas.equipment import AHU, FCU, VAVBox
 from app.schemas.diagnosis import FaultCategory
+from app.schemas.equipment import AHU, FCU, VAVBox
 from app.services.transfer import Season
 
 
@@ -12,10 +10,10 @@ class ThermalComfortDiagnosisRequest(BaseModel):
     target_temp: float
     season: Season
     duration_minutes: float
-    fcu_list: Optional[List[FCU]] = None
-    vav_list: Optional[List[VAVBox]] = None
-    ahu: Optional[AHU] = None
-    known_err: Optional[FaultCategory] = None
+    fcu_list: list[FCU]
+    vav_list: list[VAVBox]
+    ahu: AHU | None
+    known_err: FaultCategory | None
 
 
 class ThermalComfortDiagnosisResponse(BaseModel):

+ 1 - 3
app/models/domain/equipment.py

@@ -1,7 +1,5 @@
 # -*- coding: utf-8 -*-
 
-from typing import Optional
-
 from pydantic import BaseModel
 
 from app.schemas.equipment import BaseEquipment
@@ -24,4 +22,4 @@ class EquipmentControlRequest(BaseModel):
 
 class EquipmentInstructionsResponse(BaseModel):
     project: str
-    instructions: Optional[BaseEquipment] = None
+    instructions: BaseEquipment | None

+ 3 - 5
app/models/domain/location.py

@@ -1,13 +1,11 @@
-from typing import Optional
-
 from pydantic import BaseModel
 
 
 class PositionResponseBase(BaseModel):
     result: str
-    userId: Optional[str]
+    userId: str | None
 
 
 class PositionSpaceResponse(PositionResponseBase):
-    spaceId: Optional[str]
-    projectId: Optional[str]
+    spaceId: str | None
+    projectId: str | None

+ 6 - 7
app/models/domain/nlp.py

@@ -1,5 +1,4 @@
 from enum import Enum
-from typing import List, Optional
 
 from pydantic import BaseModel
 
@@ -16,9 +15,9 @@ class NLPResponseBase(BaseModel):
 
 
 class MeetingInfoResponse(NLPResponseBase):
-    AcceptableStartTime: Optional[str]
-    AcceptableEndTime: Optional[str]
-    MeetingDurationSeconds: Optional[int]
-    MeetingRoomSize: Optional[RoomSize]
-    Topic: Optional[str]
-    Participants: Optional[List[str]]
+    AcceptableStartTime: str | None
+    AcceptableEndTime: str | None
+    MeetingDurationSeconds: int | None
+    MeetingRoomSize: RoomSize | None
+    Topic: str | None
+    Participants: list[str]

+ 4 - 6
app/models/domain/targets.py

@@ -1,10 +1,8 @@
 # -*- coding: utf-8 -*-
 
-from typing import Dict, List
-
 from pydantic import BaseModel
-from app.schemas.feedback import Feedback
 
+from app.schemas.feedback import Feedback
 from app.schemas.season import Season
 
 
@@ -20,14 +18,14 @@ class RegulatedTargetResponse(BaseModel):
     projectId: str
     spaceId: str
     isTemporary: bool
-    temperature: Dict
+    temperature: dict
 
 
 class TargetReadjustRequestBase(BaseModel):
     feedback: Feedback
     season: Season
     realtime_temperature: float
-    targets: Dict
+    targets: dict
 
 
 class TargetReadjustRequestV2(TargetReadjustRequestBase):
@@ -39,7 +37,7 @@ class TargetReadjustResponseV2(BaseModel):
 
 
 class TargetReadjustRequestV3(TargetReadjustRequestBase):
-    pre_changes: Dict
+    pre_changes: dict
 
 
 class TargetReadjustResponseV3(BaseModel):

+ 6 - 7
app/schemas/bluetooth.py

@@ -1,14 +1,13 @@
 # -*- coding: utf-8 -*-
 
-from typing import Optional
 
 from pydantic import BaseModel
 
 
 class IBeaconBase(BaseModel):
-    minor: Optional[int] = None
-    major: Optional[int] = None
-    rssi: Optional[float] = None
-    proximity: Optional[int] = None
-    accuracy: Optional[float] = None
-    uuid: Optional[str] = None
+    minor: int | None
+    major: int | None
+    rssi: float | None
+    proximity: int | None
+    accuracy: float | None
+    uuid: str | None

+ 4 - 5
app/schemas/device/status_timestamp.py

@@ -1,12 +1,11 @@
 from datetime import datetime
-from typing import Optional
 
 from pydantic.main import BaseModel
 
 
 class BlowyFeedbackTimeBase(BaseModel):
-    timestamp: Optional[datetime] = None
-    device_id: Optional[str] = None
+    timestamp: datetime | None
+    device_id: str | None
 
 
 class BlowyFeedbackTimeCreate(BlowyFeedbackTimeBase):
@@ -35,8 +34,8 @@ class BlowyFeedbackTimeInDB(BlowyFeedbackTimeInDBBase):
 
 
 class HighSpeedTimeBase(BaseModel):
-    timestamp: Optional[datetime] = None
-    device_id: Optional[str] = None
+    timestamp: datetime | None
+    device_id: str | None
 
 
 class HighSpeedTimeCreate(HighSpeedTimeBase):

+ 13 - 14
app/schemas/diagnosis.py

@@ -1,20 +1,19 @@
 from enum import Enum
-from typing import Optional
 
 from pydantic import BaseModel
 
 
 class FaultCategory(BaseModel):
-    no_problems_found: Optional[bool] = False
-    control_logic_err: Optional[bool] = False
-    over_constrained: Optional[bool] = False
-    insufficient_heating: Optional[bool] = False
-    insufficient_cooling: Optional[bool] = False
-    excessive_heating: Optional[bool] = False
-    excessive_cooling: Optional[bool] = False
-    controller_err: Optional[bool] = False
-    sensor_err: Optional[bool] = False
-    unreasonable_vav_flow_limit: Optional[bool] = False
-    obj_info_err: Optional[bool] = False
-    undefined_err: Optional[bool] = True
-    hardware_err: Optional[bool] = False
+    no_problems_found: bool | None = False
+    control_logic_err: bool | None = False
+    over_constrained: bool | None = False
+    insufficient_heating: bool | None = False
+    insufficient_cooling: bool | None = False
+    excessive_heating: bool | None = False
+    excessive_cooling: bool | None = False
+    controller_err: bool | None = False
+    sensor_err: bool | None = False
+    unreasonable_vav_flow_limit: bool | None = False
+    obj_info_err: bool | None = False
+    undefined_err: bool | None = True
+    hardware_err: bool | None = False

+ 50 - 51
app/schemas/equipment.py

@@ -1,7 +1,6 @@
 # -*- coding: utf-8 -*-
 
 from enum import Enum
-from typing import List, Optional
 
 import numpy as np
 from pydantic import BaseModel
@@ -24,50 +23,50 @@ class VRFMode(str, Enum):
 
 
 class BaseEquipment(BaseModel):
-    id: Optional[str]
-    running_status: Optional[bool]
-    in_cloud_status: Optional[bool]
-    on_time: Optional[str]
-    off_time: Optional[str]
-    equip_switch_set: Optional[bool]
+    id: str | None
+    running_status: bool | None
+    in_cloud_status: bool | None
+    on_time: str | None
+    off_time: str | None
+    equip_switch_set: bool | None
 
 
 class FCU(BaseEquipment):
-    work_mode: Optional[int]
-    air_valve_speed: Optional[AirValveSpeed] = AirValveSpeed.off
-    air_valve_speed_set: Optional[AirValveSpeed] = AirValveSpeed.off
-    recommended_speed: Optional[AirValveSpeed] = AirValveSpeed.off
-    space: Optional[Space]
-    setting_temperature: Optional[float]
-    supply_air_temperature: Optional[float]
-    water_out_temperature: Optional[float]
-    water_in_temperature: Optional[float]
-    speed_limit: Optional[AirValveSpeed] = AirValveSpeed.high
+    work_mode: int | None
+    air_valve_speed: AirValveSpeed | None = AirValveSpeed.off
+    air_valve_speed_set: AirValveSpeed | None = AirValveSpeed.off
+    recommended_speed: AirValveSpeed | None = AirValveSpeed.off
+    space: Space | None
+    setting_temperature: float | None
+    supply_air_temperature: float | None
+    water_out_temperature: float | None
+    water_in_temperature: float | None
+    speed_limit: AirValveSpeed | None = AirValveSpeed.high
 
 
 class VAVBox(BaseEquipment):
-    spaces: Optional[List[Space]]
-    supply_air_temperature: Optional[float] = np.NAN
-    supply_air_flow: Optional[float] = np.NAN
-    supply_air_flow_set: Optional[float] = np.NAN
-    supply_air_flow_lower_limit: Optional[float] = np.NAN
-    supply_air_flow_upper_limit: Optional[float] = np.NAN
-    recommended_supply_air_flow: Optional[float] = np.NAN
-    valve_opening: Optional[float] = np.NAN
-    setting_temperature: Optional[float] = 0.0
-    virtual_realtime_temperature: Optional[float] = np.NAN
-    virtual_target_temperature: Optional[float] = np.NAN
+    spaces: list[Space]
+    supply_air_temperature: float | None = np.NAN
+    supply_air_flow: float | None = np.NAN
+    supply_air_flow_set: float | None = np.NAN
+    supply_air_flow_lower_limit: float | None = np.NAN
+    supply_air_flow_upper_limit: float | None = np.NAN
+    recommended_supply_air_flow: float | None = np.NAN
+    valve_opening: float | None = np.NAN
+    setting_temperature: float | None = 0.0
+    virtual_realtime_temperature: float | None = np.NAN
+    virtual_target_temperature: float | None = np.NAN
 
 
 class AHU(BaseEquipment):
-    supply_air_temperature: Optional[float]
-    supply_air_temperature_set: Optional[float]
-    return_air_temperature: Optional[float]
-    return_air_temperature_set: Optional[float]
-    freq: Optional[float]
-    freq_set: Optional[float]
-    fan_freq_upper_limit_set: Optional[float]
-    fan_freq_lower_limit_set: Optional[float]
+    supply_air_temperature: float | None
+    supply_air_temperature_set: float | None
+    return_air_temperature: float | None
+    return_air_temperature_set: float | None
+    freq: float | None
+    freq_set: float | None
+    fan_freq_upper_limit_set: float | None
+    fan_freq_lower_limit_set: float | None
 
 
 class VentilationFan(BaseEquipment):
@@ -79,21 +78,21 @@ class PAU(BaseEquipment):
 
 
 class VRF(BaseEquipment):
-    equip_switch_set: Optional[str]
-    work_mode: Optional[VRFMode]
-    speed: Optional[str]
-    speed_set: Optional[str]
-    current_temperature_set: Optional[float]
-    temperature_set: Optional[float]
-    mode_set: Optional[str]
-    return_air_temp: Optional[float]
+    equip_switch_set: str | None
+    work_mode: VRFMode | None
+    speed: str | None
+    speed_set: str | None
+    current_temperature_set: float | None
+    temperature_set: float | None
+    mode_set: str | None
+    return_air_temp: float | None
 
 
 class ASHP(BaseEquipment):
-    out_temp_15min: List[float]
-    out_temp_set_15min: List[float]
-    out_temp_30min: List[float]
-    out_temp_set_30min: List[float]
-    out_temp_set: Optional[float]
-    iplr_15min: List[float]
-    iplr_30min: List[float]
+    out_temp_15min: list[float]
+    out_temp_set_15min: list[float]
+    out_temp_30min: list[float]
+    out_temp_set_30min: list[float]
+    out_temp_set: float | None
+    iplr_15min: list[float]
+    iplr_30min: list[float]

+ 1 - 3
app/schemas/item.py

@@ -1,11 +1,9 @@
-from typing import Optional
-
 from pydantic import BaseModel
 
 
 class ItemBase(BaseModel):
     title: str
-    description: Optional[str] = None
+    description: str | None
 
 
 class ItemCreate(ItemBase):

+ 5 - 7
app/schemas/model_path/early_start.py

@@ -1,13 +1,11 @@
-from typing import Optional
-
 from pydantic import BaseModel
 
 
 class EarlyStartDTRModelPathBase(BaseModel):
-    project_id: Optional[str] = None
-    device_id: Optional[str] = None
-    summer_model_path: Optional[str] = None
-    winter_model_path: Optional[str] = None
+    project_id: str | None
+    device_id: str | None
+    summer_model_path: str | None
+    winter_model_path: str | None
 
 
 class EarlyStartDTRModelPathCreate(EarlyStartDTRModelPathBase):
@@ -19,7 +17,7 @@ class EarlyStartDTRModelPathUpdate(EarlyStartDTRModelPathBase):
 
 
 class EarlyStartDTRModelPathInDBBase(EarlyStartDTRModelPathBase):
-    id: Optional[int] = None
+    id: int | None
 
     class Config:
         orm_mode = True

+ 7 - 8
app/schemas/sapce_weight.py

@@ -1,16 +1,15 @@
 # -*- coding: utf-8 -*-
 
-from typing import Optional
 
 from pydantic import BaseModel
 
 
 # Shared properties
 class SpaceWeightBase(BaseModel):
-    project_id: Optional[str] = None
-    space_id: Optional[str] = None
-    vav_box_id: Optional[str] = None
-    default_weight: Optional[float] = 0.0
+    project_id: str | None
+    space_id: str | None
+    vav_box_id: str | None
+    default_weight: float | None = 0.0
 
 
 # Properties to receive via API to creation
@@ -20,12 +19,12 @@ class SpaceWeightCreate(SpaceWeightBase):
 
 # Properties to receive via API on update
 class SpaceWeightUpdate(SpaceWeightBase):
-    temporary_weight: Optional[float] = 0.0
-    temporary_weight_update_time: Optional[str] = None
+    temporary_weight: float | None = 0.0
+    temporary_weight_update_time: str | None
 
 
 class SpaceWeightInDBBase(SpaceWeightUpdate):
-    id: Optional[int] = None
+    id: int | None
 
     class Config:
         orm_mode = True

+ 14 - 15
app/schemas/space.py

@@ -1,35 +1,34 @@
 # -*- coding: utf-8 -*-
 
-from typing import List, Optional
 
 import numpy as np
 from pydantic import BaseModel
 
 
 class SpaceBase(BaseModel):
-    id: Optional[str]
-    realtime_temperature: Optional[float]
+    id: str | None
+    realtime_temperature: float | None
 
 
 class Space(SpaceBase):
-    equipment: Optional[List]
-    temperature_target: Optional[float] = np.NAN
-    comfortable_temperature: Optional[float] = np.NAN
-    diff: Optional[float] = np.NAN
+    equipment: list | None
+    temperature_target: float | None = np.NAN
+    comfortable_temperature: float | None = np.NAN
+    diff: float | None = np.NAN
 
 
 class SpaceATVA(Space):
-    vav_default_weight: Optional[float] = np.NAN
-    vav_temporary_weight: Optional[float] = np.NAN
-    vav_temporary_update_time: Optional[str] = ""
+    vav_default_weight: float | None = np.NAN
+    vav_temporary_weight: float | None = np.NAN
+    vav_temporary_update_time: str | None = ""
 
 
 class SpaceATAH(Space):
-    ahu_default_weight: Optional[float]
-    ahu_temporary_weight: Optional[float]
-    ahu_temporary_update_time: Optional[str] = ""
+    ahu_default_weight: float | None
+    ahu_temporary_weight: float | None
+    ahu_temporary_update_time: str = ""
 
 
 class SpaceATFU(SpaceBase):
-    realtime_co2: Optional[float]
-    hcho: Optional[float]
+    realtime_co2: float
+    hcho: float

+ 1 - 2
app/schemas/system.py

@@ -1,6 +1,5 @@
 # -*- coding: utf-8 -*-
 
-from typing import Optional
 
 from pydantic import BaseModel
 
@@ -10,6 +9,6 @@ class BaseSystem(BaseModel):
 
 
 class ACAT(BaseSystem):
-    id: Optional[str]
+    id: str | None
     supply_static_press: float
     supply_static_press_set: float

+ 1 - 3
app/schemas/target.py

@@ -1,12 +1,10 @@
 # -*- coding: utf-8 -*-
 
-from typing import Dict
-
 from pydantic import BaseModel
 
 
 class TemperatureTarget(BaseModel):
     is_customized: bool
     is_temporary: bool
-    target_schedule: Dict
+    target_schedule: dict
     extent: float

+ 1 - 2
app/schemas/user.py

@@ -1,4 +1,3 @@
-from typing import List
 
 from pydantic import BaseModel
 
@@ -16,7 +15,7 @@ class UserCreate(UserBase):
 class User(UserBase):
     id: int
     is_active: bool
-    items: List[Item] = []
+    items: list[Item] = []
 
     class Config:
         orm_mode = True

+ 1 - 3
app/services/duckling.py

@@ -1,5 +1,3 @@
-from typing import Dict
-
 from httpx import AsyncClient, URL
 
 from app.core.config import settings
@@ -17,7 +15,7 @@ class Duckling:
         self._host = URL(server_settings.DUCKLING_HOST)
 
     @api_exception
-    async def parse(self, text: str, locale: str = "zh_CN") -> Dict:
+    async def parse(self, text: str, locale: str = "zh_CN") -> dict:
         url = self._host.join("parse")
         data = {"locale": locale, "text": text}
         raw_response = await self._client.post(url, data=data)

+ 13 - 15
app/services/milvus.py

@@ -1,5 +1,5 @@
 import time
-from typing import List
+
 from loguru import logger
 from pymilvus import connections, Collection, SearchResult
 
@@ -16,12 +16,12 @@ class Milvus:
         self._port = settings.MILVUS_PORT
 
     async def query_embedding_by_pk(
-        self,
-        collection_name: str,
-        primary_key_name: str,
-        pk: int,
-        output_field: str = "embeddings",
-    ) -> List:
+            self,
+            collection_name: str,
+            primary_key_name: str,
+            pk: int,
+            output_field: str = "embeddings",
+    ) -> list:
         start = time.perf_counter()
         connections.connect("default", host=self._host, port=self._port)
         logger.debug(time.perf_counter() - start)
@@ -47,12 +47,12 @@ class Milvus:
         return emb
 
     async def search(
-        self,
-        vec_list: List,
-        collection_name: str,
-        field_name: str,
-        limit: int,
-    ) -> List:
+            self,
+            vec_list: list,
+            collection_name: str,
+            field_name: str,
+            limit: int,
+    ) -> list:
         connections.connect("default", host=self._host, port=self._port)
         collection = Collection(name=collection_name)
         collection.load()
@@ -66,8 +66,6 @@ class Milvus:
             field_name,
             param=SEARCH_PARAM,
             limit=limit,
-            expr=None,
-            output_fields=None,
         )
         logger.debug(time.perf_counter() - start)
         pk_list = []

+ 6 - 7
app/services/milvus_helpers.py

@@ -1,6 +1,4 @@
 import sys
-import time
-from typing import List
 
 from loguru import logger
 from pymilvus import (
@@ -42,7 +40,8 @@ class MilvusHelper:
             sys.exit(1)
 
     # Return if Milvus has the collection
-    def has_collection(self, collection_name: str):
+    @staticmethod
+    def has_collection(collection_name: str):
         try:
             status = utility.has_collection(collection_name)
             return status
@@ -80,7 +79,7 @@ class MilvusHelper:
             sys.exit(1)
 
     # Batch insert vectors to milvus collection
-    async def insert(self, collection_name: str, vectors: List):
+    async def insert(self, collection_name: str, vectors: list):
         try:
             await self.create_collection(collection_name)
             self.collection = Collection(name=collection_name)
@@ -133,7 +132,7 @@ class MilvusHelper:
             sys.exit(1)
 
     # Search vector in milvus collection
-    async def search_vectors(self, collection_name: str, vectors: List, top_k: int):
+    async def search_vectors(self, collection_name: str, vectors: list, top_k: int):
         # status = utility.list_collections()
         try:
             self.set_collection(collection_name)
@@ -168,7 +167,7 @@ class MilvusHelper:
             logger.error(f"Failed to count vectors in Milvus: {e}")
             sys.exit(1)
 
-    # Query vector by primiary key
+    # Query vector by primary key
     async def query_vector_by_pk(self, collection_name: str, pk: int):
         try:
             self.set_collection(collection_name)
@@ -181,7 +180,7 @@ class MilvusHelper:
             vector = res[0]["embeddings"]
             return vector
         except Exception as e:
-            logger.error(f"Faild to query vector in Milvus: {e}")
+            logger.error(f"Failed to query vector in Milvus: {e}")
             sys.exit(1)
 
 

+ 15 - 16
app/services/platform.py

@@ -1,7 +1,6 @@
 # -*- coding: utf-8 -*-
 
 from enum import Enum
-from typing import Dict, List, Optional, Tuple
 
 import arrow
 import numpy as np
@@ -53,7 +52,7 @@ class DataPlatformService(Service):
         self._now_time = get_time_str()
         self._secret = server_settings.PLATFORM_SECRET
 
-    def _common_parameters(self) -> Dict:
+    def _common_parameters(self) -> dict:
         return {"projectId": self._project_id, "secret": self._secret}
 
     async def get_realtime_data(self, code: InfoCode, object_id: str) -> float:
@@ -76,7 +75,7 @@ class DataPlatformService(Service):
             latest_data = raw_info.get("Content")[-1].get("data")
             latest_time = raw_info.get("Content")[-1].get("receivetime")
             if arrow.get(latest_time, TIME_FMT).shift(minutes=15) < arrow.get(
-                self._now_time, TIME_FMT
+                    self._now_time, TIME_FMT
             ):
                 logger.info(
                     f"delayed data - {object_id}: ({latest_time}, {latest_data})"
@@ -88,8 +87,8 @@ class DataPlatformService(Service):
         return value
 
     async def get_duration(
-        self, code: InfoCode, object_id: str, duration: int
-    ) -> List[Dict]:
+            self, code: InfoCode, object_id: str, duration: int
+    ) -> list[dict]:
         url = self._base_url.join("data-platform-3/hisdata/query_by_obj")
         params = self._common_parameters()
         start_time = get_time_str(duration, flag="ago")
@@ -109,7 +108,7 @@ class DataPlatformService(Service):
             content = raw_info.get("Content")
             latest_time = content[-1].get("receivetime")
             if arrow.get(latest_time, TIME_FMT).shift(minutes=15) < arrow.get(
-                self._now_time, TIME_FMT
+                    self._now_time, TIME_FMT
             ):
                 result = []
                 logger.info(f"delayed data - {object_id}: ({latest_time})")
@@ -124,7 +123,7 @@ class DataPlatformService(Service):
         return result
 
     async def get_past_data(
-        self, code: InfoCode, object_id: str, interval: int
+            self, code: InfoCode, object_id: str, interval: int
     ) -> float:
         """
         Query past data from data platform.
@@ -153,7 +152,7 @@ class DataPlatformService(Service):
             latest_data = raw_info.get("Content")[-1].get("data")
             latest_time = raw_info.get("Content")[-1].get("receivetime")
             if arrow.get(latest_time, TIME_FMT).shift(minutes=15) < arrow.get(
-                end_time, TIME_FMT
+                    end_time, TIME_FMT
             ):
                 logger.info(
                     f"delayed data - {object_id}: ({latest_time}, {latest_data})"
@@ -167,11 +166,11 @@ class DataPlatformService(Service):
         return value
 
     async def query_relations(
-        self,
-        from_id: Optional[str] = None,
-        graph_id: Optional[str] = None,
-        relation_type: Optional[str] = None,
-    ) -> List[Dict]:
+            self,
+            from_id: str | None,
+            graph_id: str | None,
+            relation_type: str | None,
+    ) -> list[dict]:
         url = self._base_url.join("data-platform-3/relation/query")
         params = self._common_parameters()
         criteria = dict()
@@ -234,7 +233,7 @@ class DataPlatformService(Service):
 
         return info
 
-    async def get_air_flow_limit(self, equipment_id: str) -> Tuple[float, float]:
+    async def get_air_flow_limit(self, equipment_id: str) -> tuple[float, float]:
         lower = await self.get_static_info("MinAirFlow", equipment_id)
         upper = await self.get_static_info("MaxAirFlow", equipment_id)
         if lower is None:
@@ -244,7 +243,7 @@ class DataPlatformService(Service):
 
         return lower, upper
 
-    async def get_schedule(self, equipment_id: str) -> Tuple[str, str]:
+    async def get_schedule(self, equipment_id: str) -> tuple[str, str]:
         on_time = await self.get_static_info("ctm-OnTime", equipment_id)
         off_time = await self.get_static_info("ctm-OffTime", equipment_id)
         if not on_time:
@@ -279,7 +278,7 @@ class DataPlatformService(Service):
 
         await self._post(url, params, payload)
 
-    async def get_items_by_category(self, code) -> List:
+    async def get_items_by_category(self, code) -> list:
         url = self._base_url.join("data-platform-3/object/subset_query")
         params = self._common_parameters()
         payload = {"customInfo": True, "criteria": {"type": [code]}}

+ 10 - 15
app/services/rwd.py

@@ -1,24 +1,19 @@
-from typing import Dict, List, Optional, Tuple
-
-import arrow
-import numpy as np
 from httpx import AsyncClient, URL
-from loguru import logger
 
 from app.core.config import settings
 from app.services.service import Service
-from app.utils.date import get_time_str, TIME_FMT
+from app.utils.date import get_time_str
 
 
 class RealWorldService(Service):
     def __init__(
-        self,
-        client: AsyncClient,
-        group_code: str,
-        project_id: str,
-        app_id: Optional[str] = None,
-        user_id: Optional[str] = None,
-        server_settings=settings,
+            self,
+            client: AsyncClient,
+            group_code: str,
+            project_id: str,
+            app_id: str | None,
+            user_id: str | None,
+            server_settings=settings,
     ):
         super(RealWorldService, self).__init__(client)
         self._group_code = group_code
@@ -28,11 +23,11 @@ class RealWorldService(Service):
         self._base_url = URL(server_settings.PLATFORM_HOST)
         self._now_time = get_time_str()
 
-    def _common_parameters(self) -> Dict:
+    def _common_parameters(self) -> dict:
         return {"groupCode": self._group_code, "projectId": self._project_id}
 
     async def query_instance(
-        self, object_id: Optional[List] = None, class_code: Optional[str] = None
+            self, object_id: list | None, class_code: str | None
     ):
         url = self._base_url.join("/rwd/instance/object/query")
         params = self._common_parameters()

+ 8 - 10
app/services/service.py

@@ -1,11 +1,9 @@
 # -*- coding: utf-8 -*-
 
 from functools import wraps
-from typing import Dict, Optional
 
 from fastapi import HTTPException
 from httpx import AsyncClient, URL
-from loguru import logger
 
 
 def api_exception(func):
@@ -30,8 +28,8 @@ class Service:
 
     @api_exception
     async def _get(
-        self, url: URL, params: Optional[Dict] = None, headers: Optional[Dict] = None
-    ) -> Dict:
+            self, url: URL, params: dict | None, headers: dict | None
+    ) -> dict:
         raw_response = await self._client.get(url, params=params, headers=headers)
         # logger.debug(f'{url} - elapsed: {raw_response.elapsed.total_seconds()}')
 
@@ -39,12 +37,12 @@ class Service:
 
     @api_exception
     async def _post(
-        self,
-        url: URL,
-        params: Optional[Dict] = None,
-        payload: Optional[Dict] = None,
-        headers: Optional[Dict] = None,
-    ) -> Dict:
+            self,
+            url: URL,
+            params: dict | None,
+            payload: dict | None,
+            headers: dict | None,
+    ) -> dict:
         raw_response = await self._client.post(
             url, params=params, json=payload, headers=headers
         )

+ 6 - 8
app/services/tencent_nlp.py

@@ -1,14 +1,12 @@
 import json
-from typing import Dict, List, Tuple
 
 from loguru import logger
-
 from tencentcloud.common import credential
-from tencentcloud.common.profile.client_profile import ClientProfile
-from tencentcloud.common.profile.http_profile import HttpProfile
 from tencentcloud.common.exception.tencent_cloud_sdk_exception import (
     TencentCloudSDKException,
 )
+from tencentcloud.common.profile.client_profile import ClientProfile
+from tencentcloud.common.profile.http_profile import HttpProfile
 from tencentcloud.nlp.v20190408 import models, nlp_client
 
 from app.core.config import settings
@@ -46,7 +44,7 @@ class TencentNLP:
         client = nlp_client.NlpClient(cred, "ap-guangzhou", client_profile)
         self.client = client
 
-    async def get_lexical_analysis_result(self, text: str) -> Tuple[List, List]:
+    async def get_lexical_analysis_result(self, text: str) -> tuple[list, list]:
         req = models.LexicalAnalysisRequest()
         params = {"Text": text}
         req.from_json_string(json.dumps(params))
@@ -63,8 +61,8 @@ class TencentNLP:
         return resp.Summary
 
     async def get_text_similarity_result(
-        self, src_text: str, target_text: List[str]
-    ) -> List:
+            self, src_text: str, target_text: list[str]
+    ) -> list:
         req = models.TextSimilarityRequest()
         params = {"SrcText": src_text, "TargetText": target_text}
         req.from_json_string(json.dumps(params))
@@ -72,7 +70,7 @@ class TencentNLP:
 
         return resp.Similarity
 
-    async def get_dependency(self, text: str) -> List:
+    async def get_dependency(self, text: str) -> list:
         req = models.DependencyParsingRequest()
         params = {"Text": text}
         req.from_json_string(json.dumps(params))

+ 19 - 22
app/services/transfer.py

@@ -1,15 +1,12 @@
 # -*- coding: utf-8 -*-
 
 from enum import Enum
-import time
-from typing import Dict, List
 
 import arrow
 import httpx
 import numpy as np
 import pandas as pd
 from httpx import AsyncClient, URL
-from loguru import logger
 
 from app.core.config import settings
 from app.services.service import Service
@@ -25,11 +22,11 @@ class Season(str, Enum):
 
 class SpaceInfoService(Service):
     def __init__(
-        self,
-        client: AsyncClient,
-        project_id: str,
-        space_id: str,
-        server_settings=settings,
+            self,
+            client: AsyncClient,
+            project_id: str,
+            space_id: str,
+            server_settings=settings,
     ) -> None:
         super(SpaceInfoService, self).__init__(client)
         self._project_id = project_id
@@ -37,7 +34,7 @@ class SpaceInfoService(Service):
         self._base_url = URL(server_settings.TRANSFER_HOST)
         self._now_time = get_time_str()
 
-    def _common_parameters(self) -> Dict:
+    def _common_parameters(self) -> dict:
         return {"projectId": self._project_id, "spaceId": self._space_id}
 
     async def is_customized(self) -> bool:
@@ -71,7 +68,7 @@ class SpaceInfoService(Service):
 
         return flag
 
-    async def get_feedback(self, wechat_time: str) -> Dict:
+    async def get_feedback(self, wechat_time: str) -> dict:
         url = self._base_url.join("duoduo-service/transfer/environment/feedbackCount")
         params = self._common_parameters()
         params.update({"time": wechat_time})
@@ -98,7 +95,7 @@ class SpaceInfoService(Service):
 
         return feedback_dic
 
-    async def get_custom_target(self) -> Dict[str, pd.DataFrame]:
+    async def get_custom_target(self) -> dict[str, pd.DataFrame]:
         url = self._base_url.join(
             "duoduo-service/transfer/environment/normalAndPreDayTarget"
         )
@@ -131,9 +128,9 @@ class SpaceInfoService(Service):
         else:
             current_targets = targets.get("normal_targets")
         temp = (
-            arrow.get(self._now_time, TIME_FMT).shift(minutes=15).timestamp()
-            // (15 * 60)
-            * (15 * 60)
+                arrow.get(self._now_time, TIME_FMT).shift(minutes=15).timestamp()
+                // (15 * 60)
+                * (15 * 60)
         )
         next_quarter_minutes = arrow.get(temp).time().strftime("%H%M%S")
         try:
@@ -157,7 +154,7 @@ class SpaceInfoService(Service):
         params.update({"time": time_str, "type": form, "value": value})
         await self._get(url, params)
 
-    async def env_database_get(self) -> Dict[str, pd.DataFrame]:
+    async def env_database_get(self) -> dict[str, pd.DataFrame]:
         url = self._base_url.join("duoduo-service/transfer/environment/hispoint/get")
         params = self._common_parameters()
         params.update(
@@ -181,7 +178,7 @@ class SpaceInfoService(Service):
         return result
 
     def set_custom_target(
-        self, form: str, target_value: Dict[str, List[float]], flag: str = "1"
+            self, form: str, target_value: dict[str, list[float]], flag: str = "1"
     ) -> None:
         url = self._base_url.join("duoduo-service/transfer/environment/target/setting")
         params = {
@@ -200,7 +197,7 @@ class SpaceInfoService(Service):
         params.update({"time": self._now_time})
         await self._get(url, params)
 
-    async def get_equipment(self) -> List[dict]:
+    async def get_equipment(self) -> list[dict]:
         url = self._base_url.join(
             "duoduo-service/object-service/object/equipment/findForServe"
         )
@@ -231,7 +228,7 @@ class Duoduo(Service):
 
         return Season(raw_info.get("data"))
 
-    async def get_fill_count(self) -> Dict:
+    async def get_fill_count(self) -> dict:
         url = self._base_url.join(
             "duoduo-service/review-service/space/report/quarter/query"
         )
@@ -254,7 +251,7 @@ class Duoduo(Service):
 
         return result
 
-    async def get_space_by_equipment(self, equipment_id: str) -> List[dict]:
+    async def get_space_by_equipment(self, equipment_id: str) -> list[dict]:
         url = self._base_url.join(
             "duoduo-service/object-service/object/space/findForServe"
         )
@@ -268,7 +265,7 @@ class Duoduo(Service):
 
         return result
 
-    async def get_system_by_equipment(self, equipment_id: str) -> List:
+    async def get_system_by_equipment(self, equipment_id: str) -> list:
         url = self._base_url.join(
             "duoduo-service/object-service/object/system/findForCompose"
         )
@@ -281,7 +278,7 @@ class Duoduo(Service):
 
         return system_list
 
-    async def get_day_type(self) -> Dict:
+    async def get_day_type(self) -> dict:
         url = self._base_url.join("duoduo-service/custom-service/custom/getDateInfo")
         params = {
             "projectId": self._project_id,
@@ -312,7 +309,7 @@ class Duoduo(Service):
             latest_data = raw_info.get("data")[-1].get("value")
             latest_time = raw_info.get("data")[-1].get("realTime")
             if arrow.get(latest_time, TIME_FMT).shift(minutes=15) < arrow.get(
-                self._now_time, TIME_FMT
+                    self._now_time, TIME_FMT
             ):
                 value = np.NAN
             else:

+ 1 - 2
app/services/weather.py

@@ -1,7 +1,6 @@
 # -*- coding: utf-8 -*-
 
 import json
-from typing import Dict
 
 from httpx import AsyncClient, URL
 
@@ -16,7 +15,7 @@ class WeatherService(Service):
         self._base_url = URL(server_settings.WEATHER_HOST)
         self._now_time = get_time_str(fmt="YYYY-MM-DD HH:mm:ss")
 
-    async def get_realtime_weather(self, project_id: str) -> Dict:
+    async def get_realtime_weather(self, project_id: str) -> dict:
         url = self._base_url.join(
             "EMS_Weather/Spring/MVC/entrance/unifier/HourHistoryData"
         )

+ 1 - 2
app/utils/date.py

@@ -1,6 +1,5 @@
 # -*- coding: utf-8 -*-
 
-from typing import Optional
 
 import arrow
 
@@ -8,7 +7,7 @@ TIME_FMT = "YYYYMMDDHHmmss"
 
 
 def get_time_str(
-    delta: int = 0, flag: str = "now", fmt: Optional[str] = TIME_FMT
+        delta: int = 0, flag: str = "now", fmt: str | None = TIME_FMT
 ) -> str:
     """
     Return a Beijing time strings.

+ 1 - 2
app/utils/helpers.py

@@ -1,7 +1,6 @@
-from typing import List
 
 
-def is_off_to_on(running_status_list: List[float]) -> bool:
+def is_off_to_on(running_status_list: list[float]) -> bool:
     flag = False
     if running_status_list:
         if running_status_list[-1] == 1.0:

+ 1 - 1
docker-compose.yml

@@ -2,7 +2,7 @@ version: "3"
 
 services:
   app:
-      image: registry.persagy.com/sagacloud/saga_algo_api:0.5.4
+      image: registry.persagy.com/sagacloud/saga_algo_api:0.5.5
       container_name: saga_algo_api
       ports:
         - "8002:8002"

+ 1 - 1
requirements.txt

@@ -5,7 +5,7 @@ certifi==2022.6.15
 charset-normalizer==2.1.0
 click==8.1.3
 Deprecated==1.2.13
-fastapi==0.80.0
+fastapi==0.81.0
 grpcio==1.47.0
 grpcio-tools==1.47.0
 h11==0.12.0