Bladeren bron

Format fixes

highing666 3 jaren geleden
bovenliggende
commit
d6b44d3bd0
58 gewijzigde bestanden met toevoegingen van 1420 en 1298 verwijderingen
  1. 12 16
      app/api/routers/algorithms.py
  2. 4 4
      app/api/routers/bluetooth.py
  3. 6 3
      app/api/routers/diagnosis.py
  4. 61 41
      app/api/routers/equipment.py
  5. 3 3
      app/api/routers/item.py
  6. 28 14
      app/api/routers/model_path/early_start.py
  7. 16 9
      app/api/routers/nlp.py
  8. 10 12
      app/api/routers/positioning.py
  9. 27 22
      app/api/routers/space.py
  10. 39 38
      app/api/routers/targets.py
  11. 5 7
      app/api/routers/user.py
  12. 4 2
      app/controllers/algorithms/graph_coloring.py
  13. 0 1
      app/controllers/controller.py
  14. 96 37
      app/controllers/diagnosis/thermal_comfort.py
  15. 43 31
      app/controllers/equipment/ahu/basic.py
  16. 48 28
      app/controllers/equipment/ahu/supply_air_temperature_set.py
  17. 15 18
      app/controllers/equipment/ahu/switch.py
  18. 42 30
      app/controllers/equipment/ahu/thermal_mode.py
  19. 0 1
      app/controllers/equipment/controller.py
  20. 39 30
      app/controllers/equipment/fcu/basic.py
  21. 21 11
      app/controllers/equipment/fcu/early_start.py
  22. 0 234
      app/controllers/equipment/fcu/on_ratio.py
  23. 1 3
      app/controllers/equipment/pau/freq_set.py
  24. 24 13
      app/controllers/equipment/pau/supply_air_temperature_set.py
  25. 7 6
      app/controllers/equipment/pau/switch.py
  26. 13 14
      app/controllers/equipment/switch.py
  27. 111 56
      app/controllers/equipment/vav.py
  28. 7 6
      app/controllers/equipment/ventilation_fan/switch.py
  29. 8 4
      app/controllers/events.py
  30. 16 11
      app/controllers/location/ble/space.py
  31. 28 18
      app/controllers/nlp/meeting.py
  32. 218 126
      app/controllers/targets/temperature.py
  33. 15 8
      app/core/config.py
  34. 6 6
      app/crud/base.py
  35. 5 3
      app/crud/space/weight.py
  36. 6 1
      app/db/session.py
  37. 0 2
      app/main.py
  38. 20 18
      app/models/domain/devices.py
  39. 1 1
      app/models/domain/equipment.py
  40. 13 13
      app/models/domain/feedback.py
  41. 4 4
      app/models/domain/nlp.py
  42. 1 1
      app/models/domain/space.py
  43. 1 1
      app/models/domain/targets.py
  44. 8 8
      app/models/meetings/meeting_info.py
  45. 1 1
      app/models/ml_models_path/early_start.py
  46. 2 2
      app/models/space/weight.py
  47. 25 25
      app/resources/params.py
  48. 12 12
      app/schemas/feedback.py
  49. 0 1
      app/schemas/space.py
  50. 3 6
      app/services/duckling.py
  51. 118 127
      app/services/platform.py
  52. 13 21
      app/services/rwd.py
  53. 12 9
      app/services/service.py
  54. 21 26
      app/services/tencent_nlp.py
  55. 150 129
      app/services/transfer.py
  56. 15 10
      app/services/weather.py
  57. 8 6
      app/utils/date.py
  58. 8 8
      tests/test.py

+ 12 - 16
app/api/routers/algorithms.py

@@ -3,34 +3,30 @@ from loguru import logger
 
 from app.controllers.algorithms.graph_coloring import get_graph_coloring
 from app.models.domain.algorithms import GraphColoringRequest, GraphColoringResponse
-from app.models.domain.algorithms import AttendeesRecommendationRequest, AttendeesRecommendationResponse
+from app.models.domain.algorithms import (
+    AttendeesRecommendationRequest,
+    AttendeesRecommendationResponse,
+)
 
 router = APIRouter()
 
 
-@router.get('/status')
+@router.get("/status")
 async def get_living_condition():
-    return {'message': 'alive'}
+    return {"message": "alive"}
 
 
-@router.post('/graph-coloring', response_model=GraphColoringResponse)
+@router.post("/graph-coloring", response_model=GraphColoringResponse)
 async def get_graph_coloring_result(graph: GraphColoringRequest):
     is_solvable, colored = await get_graph_coloring(graph.graph)
 
-    solution = {
-        'is_solvable': is_solvable,
-        'colored': colored
-    }
+    solution = {"is_solvable": is_solvable, "colored": colored}
 
     return solution
 
 
-@router.post('/attendees-recommendation', response_model=AttendeesRecommendationResponse)
+@router.post(
+    "/attendees-recommendation", response_model=AttendeesRecommendationResponse
+)
 async def get_recommended(meeting_info: AttendeesRecommendationRequest):
-    return {
-        'code': 200,
-        'message': 'Test',
-        'data': {
-            'userIdList': []
-        }
-    }
+    return {"code": 200, "message": "Test", "data": {"userIdList": []}}

+ 4 - 4
app/api/routers/bluetooth.py

@@ -12,11 +12,11 @@ from app.schemas.bluetooth import IBeaconBase
 router = APIRouter()
 
 
-@router.post('/user/{user_id}', response_model=BluetoothUserResponse)
+@router.post("/user/{user_id}", response_model=BluetoothUserResponse)
 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)
-    response = {'Result': sp_id}
+    logger.info(f"{user_id}: {info_list}")
+    sp_id = await get_space_location("Pj1101080259", bluetooth_info)
+    response = {"Result": sp_id}
 
     return response

+ 6 - 3
app/api/routers/diagnosis.py

@@ -1,16 +1,19 @@
 from fastapi import APIRouter
 from loguru import logger
 
-from app.models.domain.diagnosis import ThermalComfortDiagnosisRequest, ThermalComfortDiagnosisResponse
+from app.models.domain.diagnosis import (
+    ThermalComfortDiagnosisRequest,
+    ThermalComfortDiagnosisResponse,
+)
 
 router = APIRouter()
 
 
-@router.post('/space/thermal-comfort', response_model=ThermalComfortDiagnosisResponse)
+@router.post("/space/thermal-comfort", response_model=ThermalComfortDiagnosisResponse)
 async def get_thermal_comfort_diagnosis_result(params: ThermalComfortDiagnosisRequest):
     pass
 
 
-@router.post('/thermal-comfort/fcu', response_model=ThermalComfortDiagnosisResponse)
+@router.post("/thermal-comfort/fcu", response_model=ThermalComfortDiagnosisResponse)
 async def get_thermal_comfort_fcu_diagnosis():
     pass

+ 61 - 41
app/api/routers/equipment.py

@@ -10,90 +10,110 @@ from sqlalchemy.orm import Session
 from app.api.dependencies.db import get_db
 from app.controllers.equipment.fcu.basic import get_fcu_control_result
 from app.controllers.equipment.vav import get_vav_control_v2
-from app.models.domain.equipment import EquipmentControlResponse, EquipmentControlRequest, EquipmentInstructionsResponse
+from app.models.domain.equipment import (
+    EquipmentControlResponse,
+    EquipmentControlRequest,
+)
 from app.schemas.equipment import PAU
 from app.utils.date import get_time_str
 
 
 class EquipmentName(str, Enum):
-    FCU = 'ACATFC'
-    VAV = 'ACATVA'
+    FCU = "ACATFC"
+    VAV = "ACATVA"
 
 
 router = APIRouter()
 
 
-@router.get('/control', response_model=EquipmentControlResponse)
+@router.get("/control", response_model=EquipmentControlResponse)
 async def get_equipment_command_test(
-        project_id: str = Query(..., max_length=50, regex='^Pj', alias='projectId'),
-        equip_id: str = Query(..., max_length=50, regex='^Eq', alias='equipId'),
-        equip_type: EquipmentName = Query(..., alias='equipType'),
-        db: Session = Depends(get_db)
+    project_id: str = Query(..., max_length=50, regex="^Pj", alias="projectId"),
+    equip_id: str = Query(..., max_length=50, regex="^Eq", alias="equipId"),
+    equip_type: EquipmentName = Query(..., alias="equipType"),
+    db: Session = Depends(get_db),
 ):
     if equip_type.value == EquipmentName.FCU:
         output = await get_fcu_control_result(project_id, equip_id)
     elif equip_type.value == EquipmentName.VAV:
         vav = await get_vav_control_v2(db, project_id, equip_id)
         output = {
-            'SupplyAirFlowSet': vav.supply_air_flow_set,
-            'VirtualRealtimeTemperature': vav.virtual_realtime_temperature if not np.isnan(
-                vav.virtual_realtime_temperature) else None,
-            'TargetTemperatureSet': vav.virtual_target_temperature if not np.isnan(
-                vav.virtual_target_temperature) else None
+            "SupplyAirFlowSet": vav.supply_air_flow_set,
+            "VirtualRealtimeTemperature": vav.virtual_realtime_temperature
+            if not np.isnan(vav.virtual_realtime_temperature)
+            else None,
+            "TargetTemperatureSet": vav.virtual_target_temperature
+            if not np.isnan(vav.virtual_target_temperature)
+            else None,
         }
     else:
         output = {}
 
     response = {
-        'projectId': project_id,
-        'equipId': equip_id,
-        'time': get_time_str(),
-        'output': output
+        "projectId": project_id,
+        "equipId": equip_id,
+        "time": get_time_str(),
+        "output": output,
     }
     return response
 
 
-@router.post('/control', response_model=EquipmentControlResponse)
-async def get_equipment_command(equipment_control_info: EquipmentControlRequest, db: Session = Depends(get_db)):
+@router.post("/control", response_model=EquipmentControlResponse)
+async def get_equipment_command(
+    equipment_control_info: EquipmentControlRequest, db: Session = Depends(get_db)
+):
     if equipment_control_info.equipType == EquipmentName.FCU:
-        output = await get_fcu_control_result(equipment_control_info.projectId, equipment_control_info.equipId)
+        output = await get_fcu_control_result(
+            equipment_control_info.projectId, equipment_control_info.equipId
+        )
     elif equipment_control_info.equipType == EquipmentName.VAV:
-        vav = await get_vav_control_v2(db, equipment_control_info.projectId, equipment_control_info.equipId)
+        vav = await get_vav_control_v2(
+            db, equipment_control_info.projectId, equipment_control_info.equipId
+        )
         output = {
-            'SupplyAirFlowSet': vav.supply_air_flow_set,
-            'VirtualRealtimeTemperature': vav.virtual_realtime_temperature if not np.isnan(
-                vav.virtual_realtime_temperature) else None,
-            'TargetTemperatureSet': vav.virtual_target_temperature if not np.isnan(
-                vav.virtual_target_temperature) else None
+            "SupplyAirFlowSet": vav.supply_air_flow_set,
+            "VirtualRealtimeTemperature": vav.virtual_realtime_temperature
+            if not np.isnan(vav.virtual_realtime_temperature)
+            else None,
+            "TargetTemperatureSet": vav.virtual_target_temperature
+            if not np.isnan(vav.virtual_target_temperature)
+            else None,
         }
     else:
         output = {}
 
     response = {
-        'projectId': equipment_control_info.projectId,
-        'equipId': equipment_control_info.equipId,
-        'time': get_time_str(),
-        'output': output
+        "projectId": equipment_control_info.projectId,
+        "equipId": equipment_control_info.equipId,
+        "time": get_time_str(),
+        "output": output,
     }
     logger.info(response)
     return response
 
 
-@router.post('/control/atva/v2', response_model=EquipmentControlResponse)
-async def get_fcu_command(equipment_control_info: EquipmentControlRequest, db: Session = Depends(get_db)):
-    vav = await get_vav_control_v2(db, equipment_control_info.projectId, equipment_control_info.equipId)
+@router.post("/control/atva/v2", response_model=EquipmentControlResponse)
+async def get_fcu_command(
+    equipment_control_info: EquipmentControlRequest, db: Session = Depends(get_db)
+):
+    vav = await get_vav_control_v2(
+        db, equipment_control_info.projectId, equipment_control_info.equipId
+    )
     output = {
-        'SupplyAirFlowSet': vav.supply_air_flow_set,
-        'VirtualRealtimeTemperature': vav.virtual_realtime_temperature if not np.isnan(
-            vav.virtual_realtime_temperature) else None,
-        'TargetTemperatureSet': vav.virtual_target_temperature if not np.isnan(vav.virtual_target_temperature) else None
+        "SupplyAirFlowSet": vav.supply_air_flow_set,
+        "VirtualRealtimeTemperature": vav.virtual_realtime_temperature
+        if not np.isnan(vav.virtual_realtime_temperature)
+        else None,
+        "TargetTemperatureSet": vav.virtual_target_temperature
+        if not np.isnan(vav.virtual_target_temperature)
+        else None,
     }
 
     response = {
-        'projectId': equipment_control_info.projectId,
-        'equipId': equipment_control_info.equipId,
-        'time': get_time_str(),
-        'output': output
+        "projectId": equipment_control_info.projectId,
+        "equipId": equipment_control_info.equipId,
+        "time": get_time_str(),
+        "output": output,
     }
     logger.info(response)
     return response

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

@@ -12,9 +12,9 @@ router = APIRouter()
 
 @router.get("/", response_model=List[Item])
 def read_items(
-        skip: int = 0,
-        limit: int = 100,
-        db: Session = Depends(get_db),
+    skip: int = 0,
+    limit: int = 100,
+    db: Session = Depends(get_db),
 ) -> Any:
     """
     Retrieve items.

+ 28 - 14
app/api/routers/model_path/early_start.py

@@ -8,44 +8,58 @@ from app.crud.model_path.early_start import model_path_early_start_dtr
 from app.schemas.model_path.early_start import (
     EarlyStartDTRModelPath,
     EarlyStartDTRModelPathCreate,
-    EarlyStartDTRModelPathUpdate
+    EarlyStartDTRModelPathUpdate,
 )
 
 router = APIRouter()
 
 
-@router.post('/early-start/dtr', response_model=EarlyStartDTRModelPath)
-async def create_model_path(model_path: EarlyStartDTRModelPathCreate, db: Session = Depends(get_db)):
+@router.post("/early-start/dtr", response_model=EarlyStartDTRModelPath)
+async def create_model_path(
+    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])
-async def read_model_path(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)):
+@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)
+):
     model_paths = model_path_early_start_dtr.get_multi(db, skip=skip, limit=limit)
     return model_paths
 
 
-@router.get('/early-start/dtr/{device_id}', response_model=EarlyStartDTRModelPath)
+@router.get("/early-start/dtr/{device_id}", response_model=EarlyStartDTRModelPath)
 async def read_model_path_by_device(device_id: str, db: Session = Depends(get_db)):
-    db_model_path = model_path_early_start_dtr.get_path_by_device(db=db, device_id=device_id)
+    db_model_path = model_path_early_start_dtr.get_path_by_device(
+        db=db, device_id=device_id
+    )
     return db_model_path
 
 
-@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)):
-    model_path = model_path_early_start_dtr.get_path_by_device(db=db, device_id=device_id)
+@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),
+):
+    model_path = model_path_early_start_dtr.get_path_by_device(
+        db=db, device_id=device_id
+    )
     if model_path.device_id == device_id:
-        new_model_path = model_path_early_start_dtr.update(db=db, db_obj=model_path, obj_in=model_path_in)
+        new_model_path = model_path_early_start_dtr.update(
+            db=db, db_obj=model_path, obj_in=model_path_in
+        )
     else:
-        raise HTTPException(status_code=404, detail='Model path not found')
+        raise HTTPException(status_code=404, detail="Model path not found")
 
     return new_model_path
 
 
-@router.delete('/early-start/dtr/{id}', response_model=EarlyStartDTRModelPath)
+@router.delete("/early-start/dtr/{id}", response_model=EarlyStartDTRModelPath)
 async def delete_model_path(id: int, db: Session = Depends(get_db)):
     model_path = model_path_early_start_dtr.get(db=db, id=id)
     if not model_path:
-        raise HTTPException(status_code=404, detail='Model path not found')
+        raise HTTPException(status_code=404, detail="Model path not found")
     model_path = model_path_early_start_dtr.remove(db=db, id=id)
     return model_path

+ 16 - 9
app/api/routers/nlp.py

@@ -6,17 +6,24 @@ from app.models.domain.nlp import MeetingInfoResponse
 router = APIRouter()
 
 
-@router.get('/meeting/info', response_model=MeetingInfoResponse)
+@router.get("/meeting/info", response_model=MeetingInfoResponse)
 async def catch_meeting_info(sentence: str = Query(..., max_length=100)):
-    start_time, end_time, duration, room_size, topic, name_list = await get_caught_result(sentence)
+    (
+        start_time,
+        end_time,
+        duration,
+        room_size,
+        topic,
+        name_list,
+    ) = await get_caught_result(sentence)
     response = {
-        'Message': 'success',
-        'AcceptableStartTime': start_time,
-        'AcceptableEndTime': end_time,
-        'MeetingDurationSeconds': duration,
-        'MeetingRoomSize': room_size,
-        'Topic': topic,
-        'Participants': name_list
+        "Message": "success",
+        "AcceptableStartTime": start_time,
+        "AcceptableEndTime": end_time,
+        "MeetingDurationSeconds": duration,
+        "MeetingRoomSize": room_size,
+        "Topic": topic,
+        "Participants": name_list,
     }
 
     return response

+ 10 - 12
app/api/routers/positioning.py

@@ -10,21 +10,19 @@ from app.schemas.bluetooth import IBeaconBase
 router = APIRouter()
 
 
-@router.post('/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]):
+@router.post(
+    "/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]
+):
     space_id = await get_space_location(project_id, ibeacon_list)
-    logger.debug(f'{user_id} is in {space_id}')
-    response = {
-        'userId': user_id,
-        'projectId': project_id
-    }
+    logger.debug(f"{user_id} is in {space_id}")
+    response = {"userId": user_id, "projectId": project_id}
 
     if space_id:
-        response.update({
-            'result': 'success',
-            'spaceId': space_id
-        })
+        response.update({"result": "success", "spaceId": space_id})
     else:
-        response.update({'result': 'failure'})
+        response.update({"result": "failure"})
 
     return response

+ 27 - 22
app/api/routers/space.py

@@ -7,7 +7,12 @@ from sqlalchemy.orm import Session
 
 from app.api.dependencies.db import get_db
 from app.controllers.equipment.fcu.q_learning import QLearningCommandBuilder
-from app.crud.space.weight import get_weights_by_space, get_weights_by_vav, create_weight, update_weight
+from app.crud.space.weight import (
+    get_weights_by_space,
+    get_weights_by_vav,
+    create_weight,
+    update_weight,
+)
 from app.models.domain.space import SpaceControlResponse
 from app.schemas.sapce_weight import SpaceWeight, SpaceWeightCreate, SpaceWeightUpdate
 from app.services.transfer import Season
@@ -15,54 +20,54 @@ from app.services.transfer import Season
 router = APIRouter()
 
 
-@router.get('/control', response_model=SpaceControlResponse)
+@router.get("/control", response_model=SpaceControlResponse)
 async def get_space_command(
-        project_id: str = Query(..., max_length=50, regex='^Pj', alias='projectId'),
-        space_id: str = Query(..., max_length=50, regex='^Sp', alias='roomId'),
-        timestamp: str = Query(None, min_length=14, max_length=14, alias='time'),
-        method: int = Query(3),
+    project_id: str = Query(..., max_length=50, regex="^Pj", alias="projectId"),
+    space_id: str = Query(..., max_length=50, regex="^Sp", alias="roomId"),
+    timestamp: str = Query(None, min_length=14, max_length=14, alias="time"),
+    method: int = Query(3),
 ):
     response = {
-        'projectId': project_id,
-        'roomId': space_id,
-        'flag': 1,
-        'time': timestamp,
-        'method': method,
+        "projectId": project_id,
+        "roomId": space_id,
+        "flag": 1,
+        "time": timestamp,
+        "method": method,
     }
     return response
 
 
-@router.get('/test')
+@router.get("/test")
 async def get_test_result(current: float, pre: float, target: float):
-    builder = QLearningCommandBuilder(Season('Cooling'))
+    builder = QLearningCommandBuilder(Season("Cooling"))
     command = await builder.get_command(current, pre, target)
 
     return command
 
 
-@router.post('/weight', response_model=SpaceWeight)
+@router.post("/weight", response_model=SpaceWeight)
 async def create_space_weight(weight: SpaceWeightCreate, db: Session = Depends(get_db)):
     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
 
 
-@router.put('/weight/{space_id}/{vav_id}', response_model=SpaceWeight)
+@router.put("/weight/{space_id}/{vav_id}", response_model=SpaceWeight)
 async def update_weight_by_space(
-        space_id: str,
-        vav_id: str,
-        weight_in: SpaceWeightUpdate,
-        db: Session = Depends(get_db)
+    space_id: str,
+    vav_id: str,
+    weight_in: SpaceWeightUpdate,
+    db: Session = Depends(get_db),
 ):
     weights = get_weights_by_space(db, space_id=space_id)
     new_weight = None
@@ -71,6 +76,6 @@ async def update_weight_by_space(
             new_weight = update_weight(db, db_weight=weight, weight_in=weight_in)
             break
     if not new_weight:
-        raise HTTPException(status_code=404, detail='Wight not found')
+        raise HTTPException(status_code=404, detail="Wight not found")
 
     return new_weight

+ 39 - 38
app/api/routers/targets.py

@@ -10,7 +10,7 @@ from app.api.dependencies.db import get_db
 from app.controllers.targets.temperature import (
     temperature_target_control_v1,
     temperature_target_control_v2,
-    get_target_after_feedback
+    get_target_after_feedback,
 )
 from app.models.domain.feedback import FeedbackValue
 from app.models.domain.targets import TargetReadjustResponse, RegulatedTargetResponse
@@ -19,82 +19,83 @@ from app.utils.date import get_time_str
 router = APIRouter()
 
 
-@router.get('/adjust', response_model=TargetReadjustResponse)
+@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'),
-        db: Session = Depends(get_db)
+    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"),
+    db: Session = Depends(get_db),
 ):
     if not timestamp:
         timestamp = get_time_str()
     try:
         if feedback != FeedbackValue.null:
-            if project_id == 'Pj1101050030':
-                need_run_room_control = await temperature_target_control_v1(project_id, space_id, feedback, db)
+            if project_id == "Pj1101050030":
+                need_run_room_control = await temperature_target_control_v1(
+                    project_id, space_id, feedback, db
+                )
             else:
-                need_run_room_control = await temperature_target_control_v2(project_id, space_id, feedback)
+                need_run_room_control = await temperature_target_control_v2(
+                    project_id, space_id, feedback
+                )
         else:
             need_run_room_control = True
     except Exception as e:
         logger.error(e)
         raise HTTPException(
-            status_code=500,
-            detail='Oops, something wrong has happened'
+            status_code=500, detail="Oops, something wrong has happened"
         )
 
     response = {
-        'projectId': project_id,
-        'roomId': space_id,
-        'flag': 1 if need_run_room_control else 0,
-        'time': timestamp,
+        "projectId": project_id,
+        "roomId": space_id,
+        "flag": 1 if need_run_room_control else 0,
+        "time": timestamp,
     }
     return response
 
 
-@router.get('/adjust/v2', response_model=TargetReadjustResponse)
+@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: Optional[FeedbackValue] = Query(None),
 ):
     if feedback != FeedbackValue.null:
         try:
-            need_run_room_control = await temperature_target_control_v2(project_id, space_id, feedback)
+            need_run_room_control = await temperature_target_control_v2(
+                project_id, space_id, feedback
+            )
         except Exception as e:
             logger.error(e)
             raise HTTPException(
-                status_code=500,
-                detail='Oops, something wrong has happened!'
+                status_code=500, detail="Oops, something wrong has happened!"
             )
     else:
         need_run_room_control = True
 
     response = {
-        'projectId': project_id,
-        'roomId': space_id,
-        'flag': 1 if need_run_room_control else 0,
-        'time': get_time_str()
+        "projectId": project_id,
+        "roomId": space_id,
+        "flag": 1 if need_run_room_control else 0,
+        "time": get_time_str(),
     }
     return response
 
 
-@router.get('/regulated/value', response_model=RegulatedTargetResponse)
+@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: Optional[FeedbackValue] = Query(None),
 ):
     new_actual_target = await get_target_after_feedback(project_id, space_id, feedback)
     response = {
-        'projectId': project_id,
-        'spaceId': space_id,
-        'isTemporary': False,
-        'temperature': {
-            'min': new_actual_target,
-            'max': new_actual_target
-        }
+        "projectId": project_id,
+        "spaceId": space_id,
+        "isTemporary": False,
+        "temperature": {"min": new_actual_target, "max": new_actual_target},
     }
 
     return response

+ 5 - 7
app/api/routers/user.py

@@ -12,7 +12,7 @@ from app.crud.crud_item import create_user_item
 router = APIRouter()
 
 
-@router.post('/', response_model=User)
+@router.post("/", response_model=User)
 def create_new_user(user: UserCreate, db: Session = Depends(get_db)):
     db_user = get_user_by_email(db, email=user.email)
     if db_user:
@@ -20,13 +20,13 @@ 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
 
 
-@router.get('/{user_id}', response_model=User)
+@router.get("/{user_id}", response_model=User)
 def read_user(user_id: int, db: Session = Depends(get_db)):
     db_user = get_user(db, user_id=user_id)
     if db_user is None:
@@ -34,8 +34,6 @@ def read_user(user_id: int, db: Session = Depends(get_db)):
     return db_user
 
 
-@router.post('/{user_id}/item', response_model=Item)
-def create_item_for_user(
-        user_id: int, item: ItemCreate, db: Session = Depends(get_db)
-):
+@router.post("/{user_id}/item", response_model=Item)
+def create_item_for_user(user_id: int, item: ItemCreate, db: Session = Depends(get_db)):
     return create_user_item(db, item=item, user_id=user_id)

+ 4 - 2
app/controllers/algorithms/graph_coloring.py

@@ -12,7 +12,6 @@ class Vertex(BaseModel):
 
 
 class ColoringProblemBFSSolution:
-
     def __init__(self, vertexes: List[Vertex]):
         self._vertexes = vertexes
         self._is_solvable = True
@@ -36,7 +35,10 @@ class ColoringProblemBFSSolution:
                         if self._vertexes[top].color == self._vertexes[j].color:
                             self._vertexes[j].color += 1
 
-                        max_color_count = max(max_color_count, max(self._vertexes[top].color, self._vertexes[j].color))
+                        max_color_count = max(
+                            max_color_count,
+                            max(self._vertexes[top].color, self._vertexes[j].color),
+                        )
                         if max_color_count > m:
                             self._is_solvable = False
                             self._vertexes[j].color = 0

+ 0 - 1
app/controllers/controller.py

@@ -4,7 +4,6 @@ from abc import ABC
 
 
 class Controller(ABC):
-
     def __init__(self):
         self._results = {}
 

+ 96 - 37
app/controllers/diagnosis/thermal_comfort.py

@@ -11,34 +11,43 @@ from app.services.transfer import Season
 
 
 class DiagnotorBase(ABC):
-
     def __init__(self):
         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
 
 
 class ThermalComfortDiagnotor(DiagnotorBase):
-
     def __init__(self):
         super(ThermalComfortDiagnotor, self).__init__()
 
 
 class FCUDiagnotor(DiagnotorBase):
-
-    def __init__(self, fcu: FCU, ahu: AHU, duration: float, target_temp: float, realtime_temp: float, season: Season):
+    def __init__(
+        self,
+        fcu: FCU,
+        ahu: AHU,
+        duration: float,
+        target_temp: float,
+        realtime_temp: float,
+        season: Season,
+    ):
         super(FCUDiagnotor, self).__init__()
         self._fcu = fcu
         self._ahu = ahu
@@ -48,16 +57,18 @@ class FCUDiagnotor(DiagnotorBase):
         self._season = season
 
     def low_in_heating(self) -> None:
-        if self._fcu.air_valve_speed == 'off':
-            if self._fcu.speed_limit == 'off':
+        if self._fcu.air_valve_speed == "off":
+            if self._fcu.speed_limit == "off":
                 self._result.over_constrained = True
             else:
                 self._result.control_logic_err = True
         else:
             if self._fcu.air_valve_speed == self._fcu.recommended_speed:
-                self.controller_check(self._fcu.air_valve_speed_set, self._fcu.air_valve_speed)
+                self.controller_check(
+                    self._fcu.air_valve_speed_set, self._fcu.air_valve_speed
+                )
                 if not self._result.controller_err:
-                    if self._fcu.air_valve_speed_set == 'high':
+                    if self._fcu.air_valve_speed_set == "high":
                         if self._duration > 120:
                             if self._fcu.supply_air_temperature < self._target_temp + 1:
                                 self._result.insufficient_heating = True
@@ -74,9 +85,11 @@ class FCUDiagnotor(DiagnotorBase):
                     self._result.obj_info_err = True
 
     def low_in_cooling(self) -> None:
-        if self._fcu.recommended_speed == 'off':
+        if self._fcu.recommended_speed == "off":
             if self._fcu.air_valve_speed == self._fcu.recommended_speed:
-                self.controller_check(self._fcu.air_valve_speed_set, self._fcu.air_valve_speed)
+                self.controller_check(
+                    self._fcu.air_valve_speed_set, self._fcu.air_valve_speed
+                )
                 if not self._result.controller_err:
                     if self._duration > 120:
                         self._result.undefined_err = True
@@ -97,12 +110,18 @@ class FCUDiagnotor(DiagnotorBase):
             self._result.insufficient_cooling = True
 
     def run(self) -> None:
-        if self._season == Season.heating or self._fcu.supply_air_temperature > self._target_temp:
+        if (
+            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:
+        elif (
+            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()
             elif self._realtime_temp > self._target_temp + 1:
@@ -110,8 +129,14 @@ class FCUDiagnotor(DiagnotorBase):
 
 
 class VAVDiagnotor(DiagnotorBase):
-
-    def __init__(self, vav: VAVBox, ahu: AHU, known_err: FaultCategory, duration: float, season: Season):
+    def __init__(
+        self,
+        vav: VAVBox,
+        ahu: AHU,
+        known_err: FaultCategory,
+        duration: float,
+        season: Season,
+    ):
         super(VAVDiagnotor, self).__init__()
         self._vav = vav
         self._ahu = ahu
@@ -124,14 +149,21 @@ class VAVDiagnotor(DiagnotorBase):
             self._vav.supply_air_flow_set,
             self._vav.supply_air_flow,
             is_categorical=False,
-            tolerance_pct=0.1
+            tolerance_pct=0.1,
         )
-        if 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_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:
+                        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._result.insufficient_heating = True
                         else:
                             if self._vav.supply_air_flow_upper_limit < 1200.0:
@@ -153,7 +185,7 @@ class VAVDiagnotor(DiagnotorBase):
                 self._vav.supply_air_flow_set,
                 self._vav.supply_air_flow,
                 is_categorical=False,
-                tolerance_pct=0.1
+                tolerance_pct=0.1,
             )
             if self._vav.supply_air_flow_set <= self._vav.supply_air_flow_lower_limit:
                 if not self._result.controller_err:
@@ -162,7 +194,10 @@ class VAVDiagnotor(DiagnotorBase):
                             self._result.unreasonable_vav_flow_limit = True
                         else:
                             if not self._known_err.sensor_err:
-                                if self._vav.supply_air_temperature < 18 or self._ahu.supply_air_temperature < 18:
+                                if (
+                                    self._vav.supply_air_temperature < 18
+                                    or self._ahu.supply_air_temperature < 18
+                                ):
                                     self._result.excessive_cooling = True
                                 else:
                                     self._result.obj_info_err = True
@@ -181,29 +216,53 @@ 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:
+        if (
+            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:
+                        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._result.insufficient_cooling = True
 
     def run(self) -> None:
-        if 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:
+        if (
+            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.low_in_heating()
-            elif self._vav.virtual_realtime_temperature > self._vav.virtual_target_temperature + 1:
+            elif (
+                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:
-            if self._vav.virtual_realtime_temperature < self._vav.virtual_target_temperature - 1:
+        elif (
+            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.low_in_cooling()
-            elif self._vav.virtual_realtime_temperature > self._vav.virtual_target_temperature + 1:
+            elif (
+                self._vav.virtual_realtime_temperature
+                > self._vav.virtual_target_temperature + 1
+            ):
                 self.high_in_cooling()
 
 
 class VRFDiagnotor(DiagnotorBase):
-
     def __init__(self, vrf: VRF):
         super(VRFDiagnotor, self).__init__()
         self._vrf = vrf
@@ -218,5 +277,5 @@ def get_diagnosis_result(params: ThermalComfortDiagnosisRequest) -> FaultCategor
                 params.duration_minutes,
                 params.target_temp,
                 params.realtime_temp,
-                params.season
+                params.season,
             )

+ 43 - 31
app/controllers/equipment/ahu/basic.py

@@ -14,34 +14,45 @@ from app.services.transfer import Duoduo
 
 
 class AHUController:
-
     def __init__(self, equipment: Optional[AHU] = None, system: Optional[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, hot_rate: float
+    ) -> float:
         extent = 5
-        if (np.isnan(self._equipment.fan_freq_set)
-                or np.isnan(self._system.supply_static_press)
-                or np.isnan(self._system.supply_static_press_set)):
+        if (
+            np.isnan(self._equipment.fan_freq_set)
+            or np.isnan(self._system.supply_static_press)
+            or np.isnan(self._system.supply_static_press_set)
+        ):
             temp_freq_set = 80.0
         else:
             pre_fan_freq_set = self._equipment.fan_freq_set
 
-            if self._system.supply_static_press < self._system.supply_static_press_set - extent:
+            if (
+                self._system.supply_static_press
+                < self._system.supply_static_press_set - extent
+            ):
                 temp_freq_set = pre_fan_freq_set + 2
-            elif self._system.supply_static_press > self._system.supply_static_press_set + extent:
+            elif (
+                self._system.supply_static_press
+                > self._system.supply_static_press_set + extent
+            ):
                 temp_freq_set = pre_fan_freq_set - 2
             else:
                 temp_freq_set = pre_fan_freq_set
 
         temperature_value_list = np.array(supply_air_temperature_set_duration)
         freq_upper_limit = 90.0
-        if (temperature_value_list.size > 0
-                and np.all(temperature_value_list == temperature_value_list[0])
-                and temperature_value_list[0] <= 18.0
-                and hot_rate >= 0.5):
+        if (
+            temperature_value_list.size > 0
+            and np.all(temperature_value_list == temperature_value_list[0])
+            and temperature_value_list[0] <= 18.0
+            and hot_rate >= 0.5
+        ):
             freq_upper_limit = 100.0
         freq_set = min(temp_freq_set, freq_upper_limit)
 
@@ -58,37 +69,38 @@ async def get_freq_controlled(project_id: str, equipment_id: str) -> None:
 
         fan_freq_set = await platform.get_realtime_fan_freq_set(equipment_id)
         # system = await equip_service.get_system_by_equipment(equipment_id)
-        system = ['Sy1101050030eab54ad66b084a1cb1b919950b263280']
+        system = ["Sy1101050030eab54ad66b084a1cb1b919950b263280"]
         press = await platform.get_realtime_supply_static_press(system[0])
         press_set = await platform.get_realtime_supply_static_press_set(system[0])
         count = await review_service.get_fill_count()
         try:
-            hot_rate = count.get('hotNum') / (count.get('hotNum') + count.get('coldNum') + count.get('normalNum'))
+            hot_rate = count.get("hotNum") / (
+                count.get("hotNum") + count.get("coldNum") + count.get("normalNum")
+            )
         except (ZeroDivisionError, KeyError):
             hot_rate = 0.0
         raw_supply_air_temperature_set = await platform.get_duration(
-            InfoCode.supply_air_temperature_set,
-            equipment_id,
-            30 * 60
+            InfoCode.supply_air_temperature_set, equipment_id, 30 * 60
         )
-        supply_air_temperature_set = [item['value'] for item in raw_supply_air_temperature_set]
+        supply_air_temperature_set = [
+            item["value"] for item in raw_supply_air_temperature_set
+        ]
 
-    equip_params = {
-        'id': equipment_id,
-        'fan_freq_set': fan_freq_set
-    }
+    equip_params = {"id": equipment_id, "fan_freq_set": fan_freq_set}
     ahu = AHU(**equip_params)
 
     system_params = {
-        'id': system[0],
-        'supply_static_press': press,
-        'supply_static_press_set': press_set
+        "id": system[0],
+        "supply_static_press": press,
+        "supply_static_press_set": press_set,
     }
     acat_system = ACAT(**system_params)
 
     ahu_controller = AHUController(ahu, acat_system)
-    new_freq_set = await ahu_controller.build_freq_set(supply_air_temperature_set, hot_rate)
-    logger.debug(f'{equipment_id} freq set: {new_freq_set}')
+    new_freq_set = await ahu_controller.build_freq_set(
+        supply_air_temperature_set, hot_rate
+    )
+    logger.debug(f"{equipment_id} freq set: {new_freq_set}")
 
     async with AsyncClient() as client:
         platform = DataPlatformService(client, project_id)
@@ -99,13 +111,13 @@ async def get_freq_controlled(project_id: str, equipment_id: str) -> None:
 async def build_acatah_freq_set(params: ACATAHFreqSetRequest) -> float:
     acat_system = ACAT(
         supply_static_press=params.system_supply_static_press,
-        supply_static_press_set=params.system_supply_static_press_set
-    )
-    ahu = AHU(
-        fan_freq_set=params.current_freq_set
+        supply_static_press_set=params.system_supply_static_press_set,
     )
+    ahu = AHU(fan_freq_set=params.current_freq_set)
 
     ahu_controller = AHUController(ahu, acat_system)
-    new_freq_set = await ahu_controller.build_freq_set(params.supply_air_temperature_set_list, params.spaces_hot_rate)
+    new_freq_set = await ahu_controller.build_freq_set(
+        params.supply_air_temperature_set_list, params.spaces_hot_rate
+    )
 
     return new_freq_set

+ 48 - 28
app/controllers/equipment/ahu/supply_air_temperature_set.py

@@ -5,7 +5,10 @@ import numpy as np
 from httpx import AsyncClient
 from loguru import logger
 
-from app.controllers.equipment.ahu.thermal_mode import count_vav_box_weight, fetch_status_params
+from app.controllers.equipment.ahu.thermal_mode import (
+    count_vav_box_weight,
+    fetch_status_params,
+)
 from app.models.domain.devices import ThermalMode, ACATAHSupplyAirTempSetRequest
 from app.schemas.equipment import VAVBox
 from app.services.platform import DataPlatformService, InfoCode
@@ -20,14 +23,14 @@ class ACATAHSupplyAirTemperatureController:
     """
 
     def __init__(
-            self,
-            vav_boxes_list: List[VAVBox],
-            current: float,
-            return_air: float,
-            thermal_mode: ThermalMode,
-            is_off_to_on: bool,
-            is_thermal_mode_switched: bool,
-            season: Season
+        self,
+        vav_boxes_list: List[VAVBox],
+        current: float,
+        return_air: float,
+        thermal_mode: ThermalMode,
+        is_off_to_on: bool,
+        is_thermal_mode_switched: bool,
+        season: Season,
     ):
         super(ACATAHSupplyAirTemperatureController, self).__init__()
         self.vav_boxes_list = vav_boxes_list
@@ -80,7 +83,7 @@ class ACATAHSupplyAirTemperatureController:
                 box.supply_air_flow_lower_limit,
                 box.supply_air_flow_set,
                 box.valve_opening,
-                self.season
+                self.season,
             )
             cold += temp if temp < 0 else 0
             total += abs(temp)
@@ -90,14 +93,17 @@ class ACATAHSupplyAirTemperatureController:
         except ZeroDivisionError:
             cold_ratio = np.NAN
 
-        logger.debug(f'cold ratio: {cold_ratio}')
+        logger.debug(f"cold ratio: {cold_ratio}")
 
         return cold_ratio
 
     def get_normal_ratio(self):
         normal = 0
         for box in self.vav_boxes_list:
-            if abs(box.virtual_realtime_temperature - box.virtual_target_temperature) <= 1:
+            if (
+                abs(box.virtual_realtime_temperature - box.virtual_target_temperature)
+                <= 1
+            ):
                 normal += 1
 
         try:
@@ -142,8 +148,8 @@ class ACATAHSupplyAirTemperatureDefaultController:
 
     def build(self) -> float:
         now = get_time_str()
-        now_time_str = arrow.get(now, TIME_FMT).time().strftime('%H%M%S')
-        if '080000' <= now_time_str < '100000':
+        now_time_str = arrow.get(now, TIME_FMT).time().strftime("%H%M%S")
+        if "080000" <= now_time_str < "100000":
             is_morning = True
         else:
             is_morning = False
@@ -161,13 +167,17 @@ class ACATAHSupplyAirTemperatureDefaultController:
 
 async def get_planned(project_id: str, device_id: str) -> float:
     vav_boxes_params = await fetch_status_params(project_id, device_id)
-    vav_boxes_lit = vav_boxes_params['vav_boxes_list']
+    vav_boxes_lit = vav_boxes_params["vav_boxes_list"]
     async with AsyncClient() as client:
         platform = DataPlatformService(client, project_id)
         duoduo = Duoduo(client, project_id)
 
-        current_supply_air_temperature = await platform.get_realtime_supply_air_temperature(device_id)
-        return_air_temperature = await platform.query_realtime_return_air_temperature(device_id)
+        current_supply_air_temperature = (
+            await platform.get_realtime_supply_air_temperature(device_id)
+        )
+        return_air_temperature = await platform.query_realtime_return_air_temperature(
+            device_id
+        )
 
         hot_water_valve_opening_set_duration = await platform.get_duration(
             InfoCode.hot_water_valve_opening_set, device_id, 15 * 60
@@ -175,29 +185,37 @@ async def get_planned(project_id: str, device_id: str) -> float:
         chill_water_valve_opening_set_duration = await platform.get_duration(
             InfoCode.chill_water_valve_opening_set, device_id, 15 * 60
         )
-        on_off_set_duration = await platform.get_duration(InfoCode.equip_switch_set, device_id, 20 * 60)
+        on_off_set_duration = await platform.get_duration(
+            InfoCode.equip_switch_set, device_id, 20 * 60
+        )
 
         season = await duoduo.get_season()
 
         # if hot_water_valve_opening_set_duration[-1]['value'] == 0.0:
         #     thermal_mode = ThermalMode.cooling
-        if chill_water_valve_opening_set_duration[-1]['value'] == 0.0:
+        if chill_water_valve_opening_set_duration[-1]["value"] == 0.0:
             thermal_mode = ThermalMode.heating
         else:
             thermal_mode = ThermalMode.cooling
 
         is_off_to_on = False
-        if on_off_set_duration[-1]['value'] == 1.0:
+        if on_off_set_duration[-1]["value"] == 1.0:
             for item in on_off_set_duration[::-1]:
-                if item['value'] == 0.0:
+                if item["value"] == 0.0:
                     is_off_to_on = True
                     break
         # logger.debug(f'{device_id} was off to on: {is_off_to_on}')
 
         is_thermal_mode_switched = False
-        if len(set([item['value'] for item in hot_water_valve_opening_set_duration])) > 1:
+        if (
+            len(set([item["value"] for item in hot_water_valve_opening_set_duration]))
+            > 1
+        ):
             is_thermal_mode_switched = True
-        if len(set([item['value'] for item in chill_water_valve_opening_set_duration])) > 1:
+        if (
+            len(set([item["value"] for item in chill_water_valve_opening_set_duration]))
+            > 1
+        ):
             is_thermal_mode_switched = True
 
     controller = ACATAHSupplyAirTemperatureController(
@@ -207,7 +225,7 @@ async def get_planned(project_id: str, device_id: str) -> float:
         thermal_mode,
         is_off_to_on,
         is_thermal_mode_switched,
-        season
+        season,
     )
     next_supply_air_temperature_set = controller.build()
 
@@ -219,7 +237,7 @@ async def get_default(project_id: str) -> float:
         weather_service = WeatherService(client)
         realtime_weather = await weather_service.get_realtime_weather(project_id)
 
-        if realtime_weather.get('text') == '晴':
+        if realtime_weather.get("text") == "晴":
             is_clear_day = True
         else:
             is_clear_day = False
@@ -237,13 +255,15 @@ async def get_next_supply_air_temperature_set(project_id: str, device_id: str) -
     except KeyError and IndexError:
         new = await get_default(project_id)
 
-    logger.debug(f'next supply air temperature set: {device_id} - {new}')
+    logger.debug(f"next supply air temperature set: {device_id} - {new}")
 
     return new
 
 
 @logger.catch()
-def build_acatah_supply_air_temperature_set(params: ACATAHSupplyAirTempSetRequest) -> float:
+def build_acatah_supply_air_temperature_set(
+    params: ACATAHSupplyAirTempSetRequest,
+) -> float:
     try:
         vav_list = list()
         for raw_vav in params.vav_list:
@@ -276,7 +296,7 @@ def build_acatah_supply_air_temperature_set(params: ACATAHSupplyAirTempSetReques
             thermal_mode,
             is_off_to_on,
             is_thermal_mode_switched,
-            Season(params.season)
+            Season(params.season),
         )
         supply_air_temperature_set = controller.build()
 

+ 15 - 18
app/controllers/equipment/ahu/switch.py

@@ -12,7 +12,6 @@ from app.services.platform import DataPlatformService
 
 
 class AHUSwitch(Switch):
-
     def __init__(self, equipment: AHU):
         super(AHUSwitch, self).__init__(equipment)
 
@@ -29,15 +28,15 @@ class AHUSwitch(Switch):
                             switch_flag = False
 
                     if not switch_flag:
-                        action = 'off'
+                        action = "off"
                     else:
-                        action = 'hold'
+                        action = "hold"
                 else:
-                    action = 'hold'
+                    action = "hold"
             else:
-                action = 'hold'
+                action = "hold"
         else:
-            action = 'hold'
+            action = "hold"
 
         return action
 
@@ -45,8 +44,8 @@ class AHUSwitch(Switch):
 async def fetch_break_time(project_id: str, device_id: str) -> Tuple[str, str]:
     async with AsyncClient() as client:
         platform = DataPlatformService(client, project_id)
-        begin = await platform.get_static_info('ctm-BeginBreakTime', device_id)
-        end = await platform.get_static_info('ctm-EndBreakTime', device_id)
+        begin = await platform.get_static_info("ctm-BeginBreakTime", device_id)
+        end = await platform.get_static_info("ctm-EndBreakTime", device_id)
 
     return begin, end
 
@@ -54,14 +53,14 @@ async def fetch_break_time(project_id: str, device_id: str) -> Tuple[str, str]:
 @logger.catch()
 async def ahu_switch_control(project_id: str, equipment_id: str) -> None:
     equip_params, day_type = await fetch_data(project_id, equipment_id)
-    is_workday = True if day_type.get('day_type') == 'WeekDay' else False
+    is_workday = True if day_type.get("day_type") == "WeekDay" else False
     begin, end = await fetch_break_time(project_id, equipment_id)
     switch_controller = AHUSwitch(AHU(**equip_params))
     action = await switch_controller.build_next_action(is_workday)
     break_action = switch_controller.break_time_action(begin, end, is_workday)
-    if break_action == 'off':
-        action = 'off'
-    logger.debug(f'AHU-{equipment_id}: {action}')
+    if break_action == "off":
+        action = "off"
+    logger.debug(f"AHU-{equipment_id}: {action}")
     await send_switch_command(project_id, equipment_id, action)
 
 
@@ -71,17 +70,15 @@ async def build_acatah_switch_set(params: ACATAHSwitchSetRequest) -> str:
         running_status=params.running_status,
         in_cloud_status=params.in_cloud_status,
         on_time=params.on_time,
-        off_time=params.off_time
+        off_time=params.off_time,
     )
     ahu_switch_controller = AHUSwitch(ahu)
     action = await ahu_switch_controller.build_next_action(params.is_workday)
     break_action = ahu_switch_controller.break_time_action(
-        params.break_start_time,
-        params.break_end_time,
-        params.is_workday
+        params.break_start_time, params.break_end_time, params.is_workday
     )
 
-    if break_action == 'off':
-        action = 'off'
+    if break_action == "off":
+        action = "off"
 
     return action

+ 42 - 30
app/controllers/equipment/ahu/thermal_mode.py

@@ -11,13 +11,13 @@ from app.services.transfer import Duoduo, Season
 
 
 def count_vav_box_weight(
-        realtime: float,
-        target: float,
-        upper_limit_flow: float,
-        lower_limit_flow: float,
-        current_flow_set: float,
-        valve_opening: float,
-        season: Season
+    realtime: float,
+    target: float,
+    upper_limit_flow: float,
+    lower_limit_flow: float,
+    current_flow_set: float,
+    valve_opening: float,
+    season: Season,
 ) -> float:
     diff = realtime - target
     flag = False
@@ -51,7 +51,8 @@ def count_vav_box_weight(
 
 class ACATAHThermalModeController:
     """
-    Decide whether to use cooling or heating mode according to space condition controlled by VAV Box.
+    Decide whether to use cooling or heating mode according to space condition 
+    controlled by VAV Box.
     Writen by WuXu
     """
 
@@ -70,15 +71,15 @@ class ACATAHThermalModeController:
                 box.supply_air_flow_lower_limit,
                 box.supply_air_flow_set,
                 box.valve_opening,
-                self.season
+                self.season,
             )
 
         if weight > 0:
-            mode = 'cooling'
+            mode = "cooling"
         elif weight < 0:
-            mode = 'heating'
+            mode = "heating"
         else:
-            mode = 'hold'
+            mode = "hold"
 
         return mode
 
@@ -89,37 +90,48 @@ async def fetch_status_params(project_id: str, device_id: str) -> Dict:
         duoduo = Duoduo(client, project_id)
 
         season = duoduo.get_season()
-        relations = await platform.query_relations(from_id=device_id, graph_id='GtControlEquipNetwork001')
-        vav_id_list = [item.get('to_id') for item in relations]
+        relations = await platform.query_relations(
+            from_id=device_id, graph_id="GtControlEquipNetwork001"
+        )
+        vav_id_list = [item.get("to_id") for item in relations]
         vav_boxes_list = []
         for vav_id in vav_id_list:
             virtual_realtime_temperature = await duoduo.query_device_virtual_data(
-                vav_id,
-                'VirtualRealtimeTemperature'
+                vav_id, "VirtualRealtimeTemperature"
+            )
+            virtual_temperature_target = await duoduo.query_device_virtual_data(
+                vav_id, "TargetTemperatureSet"
+            )
+            lower_limit_flow, upper_limit_flow = await platform.get_air_flow_limit(
+                vav_id
+            )
+            current_flow_set = await platform.get_realtime_data(
+                InfoCode.supply_air_flow_set, vav_id
+            )
+            valve_opening = await platform.get_realtime_data(
+                InfoCode.valve_opening, vav_id
             )
-            virtual_temperature_target = await duoduo.query_device_virtual_data(vav_id, 'TargetTemperatureSet')
-            lower_limit_flow, upper_limit_flow = await platform.get_air_flow_limit(vav_id)
-            current_flow_set = await platform.get_realtime_data(InfoCode.supply_air_flow_set, vav_id)
-            valve_opening = await platform.get_realtime_data(InfoCode.valve_opening, vav_id)
             vav_params = {
-                'id': vav_id,
-                'virtual_realtime_temperature': virtual_realtime_temperature,
-                'virtual_target_temperature': virtual_temperature_target,
-                'supply_air_flow_lower_limit': lower_limit_flow,
-                'supply_air_flow_upper_limit': upper_limit_flow,
-                'supply_air_flow_set': current_flow_set,
-                'valve_opening': valve_opening
+                "id": vav_id,
+                "virtual_realtime_temperature": virtual_realtime_temperature,
+                "virtual_target_temperature": virtual_temperature_target,
+                "supply_air_flow_lower_limit": lower_limit_flow,
+                "supply_air_flow_upper_limit": upper_limit_flow,
+                "supply_air_flow_set": current_flow_set,
+                "valve_opening": valve_opening,
             }
             vav = VAVBox(**vav_params)
             vav_boxes_list.append(vav)
 
-        return {'vav_boxes_list': vav_boxes_list, 'season': season}
+        return {"vav_boxes_list": vav_boxes_list, "season": season}
 
 
 @logger.catch()
 async def get_thermal_mode(project_id: str, device_id: str) -> ThermalMode:
     prams = await fetch_status_params(project_id, device_id)
-    controller = ACATAHThermalModeController(prams.get('vav_boxes_list'), prams.get('season'))
+    controller = ACATAHThermalModeController(
+        prams.get("vav_boxes_list"), prams.get("season")
+    )
     mode = controller.build()
 
     return ThermalMode(mode)
@@ -135,7 +147,7 @@ def build_acatah_thermal_mode_set(params: ACATAHThermalModeSetRequest) -> str:
             supply_air_flow_lower_limit=raw_vav.supply_air_flow_lower_limit,
             supply_air_flow_upper_limit=raw_vav.supply_air_flow_upper_limit,
             supply_air_flow_set=raw_vav.supply_air_flow_set,
-            valve_opening=raw_vav.valve_opening
+            valve_opening=raw_vav.valve_opening,
         )
         vav_list.append(vav)
 

+ 0 - 1
app/controllers/equipment/controller.py

@@ -6,7 +6,6 @@ from app.controllers.controller import Controller
 
 
 class EquipmentController(Controller):
-
     def __init__(self):
         super(EquipmentController, self).__init__()
 

+ 39 - 30
app/controllers/equipment/fcu/basic.py

@@ -17,7 +17,6 @@ from app.utils.math import round_half_up
 
 
 class FCUController(EquipmentController):
-
     def __init__(self, equipment: FCU, season: Season):
         super(FCUController, self).__init__()
         self._equipment = equipment
@@ -52,7 +51,9 @@ class FCUController(EquipmentController):
         temperature_target = self._equipment.space.temperature_target
         if temperature_target > 0:
             if self.season == Season.heating:
-                diff = abs(self._equipment.space.realtime_temperature - temperature_target)
+                diff = abs(
+                    self._equipment.space.realtime_temperature - temperature_target
+                )
                 if diff >= 1.5:
                     self._equipment.air_valve_speed = AirValveSpeed.high
                 elif diff >= 1.0:
@@ -100,12 +101,18 @@ class FCUControllerV2(EquipmentController):
 
     def get_mode(self) -> int:
         if self.equipment.water_in_temperature > 0:
-            if self.equipment.water_in_temperature > self.equipment.space.temperature_target:
+            if (
+                self.equipment.water_in_temperature
+                > self.equipment.space.temperature_target
+            ):
                 mode = 2
             else:
                 mode = 1
         elif self.equipment.supply_air_temperature > 0:
-            if self.equipment.supply_air_temperature > self.equipment.space.temperature_target:
+            if (
+                self.equipment.supply_air_temperature
+                > self.equipment.space.temperature_target
+            ):
                 mode = 2
             else:
                 mode = 1
@@ -175,34 +182,38 @@ async def get_fcu_control_result(project_id: str, equipment_id: str) -> Dict:
         duo_duo = Duoduo(client, project_id)
         platform = DataPlatformService(client, project_id)
         spaces = await duo_duo.get_space_by_equipment(equipment_id)
-        if project_id == 'Pj1101150003':
-            supply_air_temperature = await platform.get_realtime_data(InfoCode.supply_temperature, equipment_id)
-            water_in_temperature = await platform.get_realtime_data(InfoCode.water_in_temperature, equipment_id)
+        if project_id == "Pj1101150003":
+            supply_air_temperature = await platform.get_realtime_data(
+                InfoCode.supply_temperature, equipment_id
+            )
+            water_in_temperature = await platform.get_realtime_data(
+                InfoCode.water_in_temperature, equipment_id
+            )
         else:
             supply_air_temperature = np.NAN
             water_in_temperature = np.NAN
         for sp in spaces:
-            transfer = SpaceInfoService(client, project_id, sp.get('id'))
+            transfer = SpaceInfoService(client, project_id, sp.get("id"))
             current_target = await transfer.get_current_temperature_target()
-            realtime_temperature = await platform.get_realtime_temperature(sp.get('id'))
+            realtime_temperature = await platform.get_realtime_temperature(sp.get("id"))
             season = await duo_duo.get_season()
             temp_space_params = {
-                'id': sp.get('id'),
-                'temperature_target': current_target,
-                'realtime_temperature': realtime_temperature
+                "id": sp.get("id"),
+                "temperature_target": current_target,
+                "realtime_temperature": realtime_temperature,
             }
             space = Space(**temp_space_params)
             break
 
         fcu_temp_params = {
-            'id': equipment_id,
-            'space': space,
-            'supply_air_temperature': supply_air_temperature,
-            'water_in_temperature': water_in_temperature
+            "id": equipment_id,
+            "space": space,
+            "supply_air_temperature": supply_air_temperature,
+            "water_in_temperature": water_in_temperature,
         }
         fcu = FCU(**fcu_temp_params)
 
-    if project_id == 'Pj1101050030':
+    if project_id == "Pj1101050030":
         fcu_controller = FCUController(fcu, season)
     else:
         fcu_controller = FCUControllerV2(fcu, season)
@@ -210,27 +221,25 @@ async def get_fcu_control_result(project_id: str, equipment_id: str) -> Dict:
     regulated_fcu = fcu_controller.get_results()
 
     output = {
-        'onOff': 1 if regulated_fcu.running_status else 0,
-        'mode': regulated_fcu.work_mode,
-        'speed': regulated_fcu.air_valve_speed.value,
-        'temperature': float(round_half_up(regulated_fcu.setting_temperature, 1)),
-        'water': 1 if regulated_fcu.running_status else 0
+        "onOff": 1 if regulated_fcu.running_status else 0,
+        "mode": regulated_fcu.work_mode,
+        "speed": regulated_fcu.air_valve_speed.value,
+        "temperature": float(round_half_up(regulated_fcu.setting_temperature, 1)),
+        "water": 1 if regulated_fcu.running_status else 0,
     }
 
     return output
 
 
 @logger.catch()
-async def build_acatfc_instructions(params: ACATFCInstructionsRequest) -> ACATFCInstructions:
+async def build_acatfc_instructions(
+    params: ACATFCInstructionsRequest,
+) -> ACATFCInstructions:
     space = Space(
         temperature_target=params.space_temperature_target,
-        realtime_temperature=params.space_realtime_temperature
-    )
-    fcu = FCU(
-        space=space,
-        supply_air_temperature=-1.0,
-        water_in_temperature=-1.0
+        realtime_temperature=params.space_realtime_temperature,
     )
+    fcu = FCU(space=space, supply_air_temperature=-1.0, water_in_temperature=-1.0)
 
     controller = FCUControllerV2(fcu, Season(params.season))
     await controller.run()
@@ -241,7 +250,7 @@ async def build_acatfc_instructions(params: ACATFCInstructionsRequest) -> ACATFC
         speed_set=regulated_fcu.air_valve_speed.value,
         temperature_set=float(round_half_up(regulated_fcu.setting_temperature, 1)),
         mode_set=regulated_fcu.work_mode,
-        water_valve_switch_set=1 if regulated_fcu.running_status else 0
+        water_valve_switch_set=1 if regulated_fcu.running_status else 0,
     )
 
     return instructions

+ 21 - 11
app/controllers/equipment/fcu/early_start.py

@@ -19,7 +19,7 @@ class EarlyStartTimeDTRBuilder:
     """
 
     def __init__(self, model_path: str):
-        self.model_path = f'{settings.ML_MODELS_DIR}{model_path}'
+        self.model_path = f"{settings.ML_MODELS_DIR}{model_path}"
 
     async def get_prediction(self, indoor_temp: float, outdoor_temp: float) -> float:
         try:
@@ -38,7 +38,9 @@ class EarlyStartTimeDTRBuilder:
         return pre_time
 
 
-async def fetch_params(project_id: str, space_id: str, db: Session) -> Tuple[float, float, str]:
+async def fetch_params(
+    project_id: str, space_id: str, db: Session
+) -> Tuple[float, float, str]:
     async with AsyncClient() as client:
         platform = DataPlatformService(client, project_id)
         space_service = SpaceInfoService(client, project_id, space_id)
@@ -46,41 +48,49 @@ async def fetch_params(project_id: str, space_id: str, db: Session) -> Tuple[flo
 
         indoor_temp = await platform.get_realtime_temperature(space_id)
         weather_info = await weather_service.get_realtime_weather(project_id)
-        outdoor_temp = weather_info.get('temperature')
+        outdoor_temp = weather_info.get("temperature")
 
         device_list = await space_service.get_equipment()
-        device_id = ''
+        device_id = ""
         for device in device_list:
-            if device.get('category') == 'ACATFC':
-                device_id = device.get('id')
+            if device.get("category") == "ACATFC":
+                device_id = device.get("id")
                 break
 
         if device_id:
             model_path = model_path_early_start_dtr.get_path_by_device(db, device_id)
             model_path = model_path.model_path
         else:
-            model_path = ''
+            model_path = ""
 
         return indoor_temp, outdoor_temp, model_path
 
 
 @logger.catch()
-async def get_recommended_early_start_time(db: Session, project_id: str, space_id: str) -> float:
+async def get_recommended_early_start_time(
+    db: Session, project_id: str, space_id: str
+) -> float:
     indoor_temp, outdoor_temp, model_path = await fetch_params(project_id, space_id, db)
 
     builder = EarlyStartTimeDTRBuilder(model_path)
     hour = await builder.get_prediction(indoor_temp, outdoor_temp)
 
-    logger.debug(f'{space_id}: indoor-{indoor_temp}, outdoor-{outdoor_temp}, prediction-{hour * 60}')
+    logger.debug(
+        f"{space_id}: indoor-{indoor_temp}, outdoor-{outdoor_temp}, prediction-{hour * 60}"
+    )
 
     return hour * 60
 
 
 @logger.catch()
-async def build_acatfc_early_start_prediction(params: ACATFCEarlyStartPredictionRequest, db: Session) -> float:
+async def build_acatfc_early_start_prediction(
+    params: ACATFCEarlyStartPredictionRequest, db: Session
+) -> float:
     model_path = model_path_early_start_dtr.get_path_by_device(db, params.device_id)
 
     builder = EarlyStartTimeDTRBuilder(model_path.model_path)
-    hour = await builder.get_prediction(params.space_realtime_temperature, params.outdoor_realtime_temperature)
+    hour = await builder.get_prediction(
+        params.space_realtime_temperature, params.outdoor_realtime_temperature
+    )
 
     return hour * 60

+ 0 - 234
app/controllers/equipment/fcu/on_ratio.py

@@ -1,234 +0,0 @@
-import asyncio
-from typing import Tuple
-
-import arrow
-from fastapi import HTTPException
-from httpx import AsyncClient
-from loguru import logger
-
-from app.controllers.equipment.fcu.basic import FCUControllerV2
-from app.schemas.equipment import FCU
-from app.schemas.space import Space
-from app.services.platform import DataPlatformService, InfoCode
-from app.services.transfer import Season
-from app.utils.date import get_time_str, TIME_FMT
-from app.utils.math import round_half_up
-
-
-class OnRatioController:
-
-    def __init__(self, target: float, return_air: float, period_num: int):
-        super(OnRatioController, self).__init__()
-        self.target = target
-        self.return_air = return_air
-        self.period_num = period_num
-
-    def select_mode(self) -> str:
-        if self.target <= self.return_air:
-            mode = 'off'
-        else:
-            if self.target - self.return_air >= 1.5:
-                mode = 'normal'
-            else:
-                mode = 'on_ratio'
-
-        return mode
-
-    def select_speed(self, delta_all: float) -> str:
-        mode = self.select_mode()
-        if mode == 'off':
-            speed = 'medium'
-        elif mode == 'normal':
-            if delta_all > 0.00088889:
-                speed = 'medium'
-            else:
-                speed = 'high'
-        else:
-            speed = 'medium'
-
-        return speed
-
-    def select_water_valve(self) -> bool:
-        mode = self.select_mode()
-        if mode == 'off':
-            switch = False
-        elif mode == 'normal':
-            switch = True
-        else:
-            switch = True
-
-        return switch
-
-    def calculate_on_ratio(self, period_time: float, delta_on: float, delta_off: float, last_mode: str) -> float:
-        if self.period_num == 0:
-            if last_mode == 'normal':
-                ratio = 0.8
-            elif last_mode == 'off':
-                ratio = 0.2
-            else:
-                if self.return_air > self.target - 0.75:
-                    ratio = 0.2
-                else:
-                    ratio = 0.8
-        else:
-            if delta_on <= 0:
-                ratio = 0.9
-            else:
-                try:
-                    if delta_off > 0:
-                        delta_off = 0.0
-                    ratio = (0.5 * (self.target - self.return_air) / period_time - delta_off) / (delta_on - delta_off)
-                    if ratio > 0.9:
-                        ratio = 0.9
-                    if ratio < 0.1:
-                        ratio = 0.1
-
-                    if delta_on <= 0:
-                        ratio = 0.5
-                    logger.debug(f'delta target: {0.5 * (self.target - self.return_air)}')
-                except ZeroDivisionError:
-                    ratio = 0.1
-
-        return ratio
-
-
-async def send_instructions(device_id: str, switch: bool, speed: str, water_valve: bool) -> None:
-    switch_value = 1.0 if switch else 0.0
-    water_valve_value = 1.0 if water_valve else 0.0
-    speed_value_dict = {
-        'off': 0.0,
-        'low': 1.0,
-        'medium': 2.0,
-        'high': 3.0
-    }
-    speed_value = speed_value_dict.get(speed)
-    async with AsyncClient() as client:
-        platform = DataPlatformService(client, 'Pj1101080259')
-
-        await platform.set_code_value(device_id, code=InfoCode.equip_switch_set, value=switch_value)
-        await platform.set_code_value(device_id, code=InfoCode.water_valve_switch_set, value=water_valve_value)
-        await platform.set_code_value(device_id, code=InfoCode.fan_speed_set, value=speed_value)
-
-        await platform.set_code_value(device_id, code=InfoCode.work_mode_set, value=2.0)
-        # await platform.set_code_value(device_id, code=InfoCode.in_cloud_set, value=1.0)
-
-
-async def fetch_params(device_id: str, period_time: int, last_ratio: float) -> Tuple[float, float, float, float]:
-    async with AsyncClient() as client:
-        middle_time = int(round_half_up(period_time * (1 - last_ratio)))
-        platform = DataPlatformService(client, 'Pj1101080259')
-
-        return_air_c = await platform.get_realtime_data(InfoCode.return_air_temperature, device_id)
-        return_air_a = await platform.get_past_data(InfoCode.return_air_temperature, device_id, period_time)
-        return_air_b = await platform.get_past_data(InfoCode.return_air_temperature, device_id, middle_time)
-
-        delta_all = (return_air_c - return_air_a) / period_time
-        if 0 < last_ratio < 1:
-            delta_on = (return_air_b - return_air_a) / (period_time - middle_time)
-            delta_off = (return_air_c - return_air_b) / middle_time
-        elif last_ratio == 0.0:
-            delta_on = 0.0
-            delta_off = (return_air_c - return_air_b) / middle_time
-        else:
-            delta_on = (return_air_b - return_air_a) / (period_time - middle_time)
-            delta_off = 0.0
-
-        return return_air_c, delta_all, delta_on, delta_off
-
-
-@logger.catch()
-async def start_on_ratio_mode(device_id: str, target: float, period_time: int):
-    _DAILY_ON_TIME = '060000'
-    _DAILY_OFF_TIME = '220000'
-
-    period_num = 0
-    last_on_ratio = 1.0
-    last_mode = 'default'
-    life_count = 0
-    while life_count < 2000:
-        try:
-            time_str = get_time_str()
-            if _DAILY_ON_TIME <= arrow.get(time_str, TIME_FMT).time().strftime('%H%M%S') < _DAILY_OFF_TIME:
-                return_air, delta_all, delta_on, delta_off = await fetch_params(device_id, period_time, last_on_ratio)
-                controller = OnRatioController(target, return_air, period_num)
-                mode = controller.select_mode()
-                speed = controller.select_speed(delta_all)
-                switch = False if speed == 'off' else True
-                water_valve = controller.select_water_valve()
-
-                if mode == 'on_ratio':
-                    on_ratio = controller.calculate_on_ratio(period_time, delta_on, delta_off, last_mode)
-                    on_range = round_half_up(period_time * on_ratio)
-                    off_range = period_time - on_range
-                    logger.debug(f'life count: {life_count}, {device_id}, on time: {on_range}, off time: {off_range}, '
-                                 f'on ratio: {on_ratio}, delta_on: {delta_on * 900}, delta_off: {delta_off * 900}')
-
-                    await send_instructions(device_id, switch, speed, water_valve)
-                    logger.debug(f'{device_id}, {switch}, {speed}, {water_valve}')
-                    await asyncio.sleep(on_range)
-                    await send_instructions(device_id, switch, speed, False)
-                    logger.debug(f'{device_id}, {switch}, {speed}, off')
-                    await asyncio.sleep(off_range)
-
-                    period_num += 1
-                    last_on_ratio = on_ratio
-                    last_mode = mode
-                else:
-                    await send_instructions(device_id, switch, speed, water_valve)
-                    logger.debug(f'life count: {life_count}, {device_id}, {switch}, {speed}, {water_valve}')
-                    await asyncio.sleep(period_time)
-
-                    period_num = 0
-                    last_on_ratio = 1.0
-                    last_mode = mode
-
-                life_count += 1
-
-            else:
-                await send_instructions(device_id, False, 'off', False)
-                period_num = 0
-                last_on_ratio = 0.0
-                last_mode = 'off'
-                await asyncio.sleep(period_time)
-        except (KeyError, IndexError, TypeError, HTTPException):
-            await asyncio.sleep(period_time)
-            continue
-
-
-@logger.catch()
-async def start_control_group_mode(device_id: str, target: float):
-    async with AsyncClient() as client:
-        platform = DataPlatformService(client, 'Pj1101080259')
-
-        return_air = await platform.get_realtime_data(InfoCode.return_air_temperature, device_id)
-        space_params = {
-            'id': device_id,
-            'temperature_target': target,
-            'realtime_temperature': return_air
-        }
-        space = Space(**space_params)
-
-        fcu_params = {
-            'id': device_id,
-            'space': space
-        }
-        fcu = FCU(**fcu_params)
-
-        controller = FCUControllerV2(fcu, Season.heating)
-        await controller.run()
-        regulated_fcu = controller.get_results()
-
-        speed_value_dict = {
-            0.0: 'medium',
-            1.0: 'low',
-            2.0: 'medium',
-            3.0: 'high'
-        }
-
-        await send_instructions(
-            device_id,
-            True,
-            speed_value_dict.get(regulated_fcu.air_valve_speed),
-            regulated_fcu.running_status
-        )
-        logger.info(f'{device_id} - {speed_value_dict.get(regulated_fcu.air_valve_speed)}')

+ 1 - 3
app/controllers/equipment/pau/freq_set.py

@@ -68,9 +68,7 @@ async def get_next_acatfu_freq_set(project_id: str, device_id: str) -> float:
 @logger.catch()
 def build_acatfu_freq_set(params: ACATFUFreqSetRequest) -> float:
     controller = ACATFUFanFreqController(
-        params.freq,
-        params.hot_ratio,
-        params.cold_ratio
+        params.freq, params.hot_ratio, params.cold_ratio
     )
     freq_set = controller.get_next_set()
 

+ 24 - 13
app/controllers/equipment/pau/supply_air_temperature_set.py

@@ -13,7 +13,9 @@ class ACATFUSupplyAirTemperatureController:
     Supply air temperature setting logic version 1 by Wenyan.
     """
 
-    def __init__(self, current_supply_air_temp: float, hot_rate: float, cold_rate: float):
+    def __init__(
+        self, current_supply_air_temp: float, hot_rate: float, cold_rate: float
+    ):
         self.current_air_temp = current_supply_air_temp
         self.hot_rate = hot_rate
         self.cold_rate = cold_rate
@@ -57,19 +59,25 @@ class ACATFUSupplyAirTemperatureController:
         return next_temperature_set
 
 
-async def fetch_params(project_id: str, device_id: str) -> Tuple[float, float, float, bool]:
+async def fetch_params(
+    project_id: str, device_id: str
+) -> Tuple[float, float, float, bool]:
     async with AsyncClient() as client:
         platform = DataPlatformService(client, project_id)
         duoduo = Duoduo(client, project_id)
 
-        current_supply_air_temperature = await platform.get_realtime_supply_air_temperature(device_id)
-        running_status_duration = await platform.get_duration(InfoCode.running_status, device_id, 15 * 60)
+        current_supply_air_temperature = (
+            await platform.get_realtime_supply_air_temperature(device_id)
+        )
+        running_status_duration = await platform.get_duration(
+            InfoCode.running_status, device_id, 15 * 60
+        )
         hot_rate, cold_rate = await duoduo.query_fill_rate_by_device(device_id)
 
         is_just_booted = False
-        if running_status_duration[-1]['value'] == 1.0:
+        if running_status_duration[-1]["value"] == 1.0:
             for item in running_status_duration[::-1]:
-                if item['value'] == 0.0:
+                if item["value"] == 0.0:
                     is_just_booted = True
                     break
 
@@ -77,12 +85,17 @@ async def fetch_params(project_id: str, device_id: str) -> Tuple[float, float, f
 
 
 @logger.catch()
-async def get_next_acatfu_supply_air_temperature_set(project_id: str, device_id: str) -> float:
-    current_supply_air_temperature, hot_rate, cold_rate, is_just_booted = await fetch_params(project_id, device_id)
-    controller = ACATFUSupplyAirTemperatureController(
+async def get_next_acatfu_supply_air_temperature_set(
+    project_id: str, device_id: str
+) -> float:
+    (
         current_supply_air_temperature,
         hot_rate,
-        cold_rate
+        cold_rate,
+        is_just_booted,
+    ) = await fetch_params(project_id, device_id)
+    controller = ACATFUSupplyAirTemperatureController(
+        current_supply_air_temperature, hot_rate, cold_rate
     )
     next_temperature_set = controller.get_next_set(is_just_booted)
 
@@ -99,9 +112,7 @@ def build_acatfu_supply_air_temperature(params: ACATFUSupplyAirTempSetRequest) -
                 break
 
     controller = ACATFUSupplyAirTemperatureController(
-        params.supply_air_temperature,
-        params.hot_ratio,
-        params.cold_ratio
+        params.supply_air_temperature, params.hot_ratio, params.cold_ratio
     )
     supply_air_temperature_set = controller.get_next_set(is_just_booted)
 

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

@@ -8,7 +8,6 @@ from app.schemas.equipment import PAU
 
 
 class PAUSwitch(Switch):
-
     def __init__(self, equipment: PAU):
         super(PAUSwitch, self).__init__(equipment)
 
@@ -16,15 +15,17 @@ class PAUSwitch(Switch):
 @logger.catch()
 async def pau_switch_control(project_id: str, equipment_id: str) -> None:
     equip_params, day_type = await fetch_data(project_id, equipment_id)
-    action = await PAUSwitch(PAU(**equip_params)).build_next_action(day_type.get('day_type'))
-    logger.debug(f'PAU-{equipment_id}: {action}')
+    action = await PAUSwitch(PAU(**equip_params)).build_next_action(
+        day_type.get("day_type")
+    )
+    logger.debug(f"PAU-{equipment_id}: {action}")
     await send_switch_command(project_id, equipment_id, action)
 
 
 @logger.catch()
 async def get_switch_action(project_id: str, device_id: str) -> str:
     device_params, day_type = await fetch_data(project_id, device_id)
-    is_workday = True if day_type.get('day_type') == 'WeekDay' else False
+    is_workday = True if day_type.get("day_type") == "WeekDay" else False
     action = await PAUSwitch(PAU(**device_params)).build_next_action(is_workday)
 
     return action
@@ -36,10 +37,10 @@ async def build_acatfu_switch_set(params: ACATFUSwitchSetRequest) -> str:
         running_status=params.running_status,
         in_cloud_status=params.in_cloud_status,
         on_time=params.on_time,
-        off_time=params.off_time
+        off_time=params.off_time,
     )
     action = await PAUSwitch(pau).build_next_action(params.is_workday)
     if not params.is_workday:
-        action = 'off'
+        action = "off"
 
     return action

+ 13 - 14
app/controllers/equipment/switch.py

@@ -12,11 +12,10 @@ from app.utils.date import get_time_str, TIME_FMT
 
 
 class Switch:
-
     def __init__(self, equipment: BaseEquipment):
         super(Switch, self).__init__()
         self._equip = equipment
-        self._now_time = arrow.get(get_time_str(), TIME_FMT).time().strftime('%H%M%S')
+        self._now_time = arrow.get(get_time_str(), TIME_FMT).time().strftime("%H%M%S")
 
     async def build_next_action(self, is_workday: bool) -> str:
         if self._equip.in_cloud_status:
@@ -33,15 +32,15 @@ class Switch:
                         switch_flag = True
 
                 if switch_flag and not self._equip.running_status:
-                    action = 'on'
+                    action = "on"
                 elif not switch_flag and self._equip.running_status:
-                    action = 'off'
+                    action = "off"
                 else:
-                    action = 'hold'
+                    action = "hold"
             else:
-                action = 'hold'
+                action = "hold"
         else:
-            action = 'hold'
+            action = "hold"
 
         return action
 
@@ -57,11 +56,11 @@ async def fetch_data(project_id: str, equipment_id: str) -> Tuple[Dict, Dict]:
         on_time, off_time = await platform.get_schedule(equipment_id)
 
     equip_params = {
-        'id': equipment_id,
-        'running_status': running_status,
-        'in_cloud_status': True if cloud_status == 1.0 else False,
-        'on_time': on_time,
-        'off_time': off_time
+        "id": equipment_id,
+        "running_status": running_status,
+        "in_cloud_status": True if cloud_status == 1.0 else False,
+        "on_time": on_time,
+        "off_time": off_time,
     }
 
     return equip_params, day_type
@@ -71,9 +70,9 @@ async def send_switch_command(project_id: str, equipment_id: str, action: str) -
     async with AsyncClient() as client:
         platform = DataPlatformService(client, project_id)
 
-        if action == 'on':
+        if action == "on":
             await platform.set_code_value(equipment_id, InfoCode.equip_switch_set, 1.0)
-        elif action == 'off':
+        elif action == "off":
             await platform.set_code_value(equipment_id, InfoCode.equip_switch_set, 0.0)
         else:
             pass

+ 111 - 56
app/controllers/equipment/vav.py

@@ -22,17 +22,16 @@ from app.utils.date import get_time_str
 
 
 class VAVController(EquipmentController):
-
     def __init__(self, equipment: VAVBox):
         super(VAVController, self).__init__()
         self.equipment = equipment
 
     async def get_strategy(self):
-        strategy = 'Plan A'
+        strategy = "Plan A"
         for space in self.equipment.spaces:
             for eq in space.equipment:
                 if isinstance(eq, FCU):
-                    strategy = 'Plan B'
+                    strategy = "Plan B"
                     break
 
         return strategy
@@ -45,7 +44,7 @@ class VAVController(EquipmentController):
             if not np.isnan(space.temperature_target):
                 target_list.append(space.temperature_target)
                 realtime_list.append(space.realtime_temperature)
-                if strategy == 'Plan B':
+                if strategy == "Plan B":
                     for eq in space.equipment:
                         if isinstance(eq, FCU):
                             buffer = (4 - eq.air_valve_speed) / 4
@@ -62,7 +61,9 @@ class VAVController(EquipmentController):
 
         return target_result, realtime_result
 
-    async def get_supply_air_flow_set(self, temperature_set: float, temperature_realtime: float) -> float:
+    async def get_supply_air_flow_set(
+        self, temperature_set: float, temperature_realtime: float
+    ) -> float:
         if np.isnan(temperature_set) or np.isnan(temperature_realtime):
             supply_air_flow_set = 0.0
         else:
@@ -70,13 +71,21 @@ class VAVController(EquipmentController):
             if np.isnan(temperature_supply):
                 temperature_supply = 19.0
             try:
-                ratio = abs(1 + (temperature_realtime - temperature_set) / (temperature_set - temperature_supply))
+                ratio = abs(
+                    1
+                    + (temperature_realtime - temperature_set)
+                    / (temperature_set - temperature_supply)
+                )
             except ZeroDivisionError:
                 ratio = 1
             supply_air_flow_set = self.equipment.supply_air_flow * ratio
 
-        supply_air_flow_set = max(self.equipment.supply_air_flow_lower_limit, supply_air_flow_set)
-        supply_air_flow_set = min(self.equipment.supply_air_flow_upper_limit, supply_air_flow_set)
+        supply_air_flow_set = max(
+            self.equipment.supply_air_flow_lower_limit, supply_air_flow_set
+        )
+        supply_air_flow_set = min(
+            self.equipment.supply_air_flow_upper_limit, supply_air_flow_set
+        )
         self.equipment.supply_air_flow_set = supply_air_flow_set
         self.equipment.virtual_target_temperature = temperature_set
         self.equipment.virtual_realtime_temperature = temperature_realtime
@@ -93,8 +102,12 @@ class VAVController(EquipmentController):
 
 
 class VAVControllerV2(VAVController):
-
-    def __init__(self, equipment: VAVBox, weights: Optional[List[SpaceWeight]] = None, season: Optional[Season] = None):
+    def __init__(
+        self,
+        equipment: VAVBox,
+        weights: Optional[List[SpaceWeight]] = None,
+        season: Optional[Season] = None,
+    ):
         super(VAVControllerV2, self).__init__(equipment)
         self.weights = weights
         self.season = season
@@ -111,17 +124,23 @@ class VAVControllerV2(VAVController):
 
         if valid_spaces:
             weights = sorted(weights, key=lambda x: x.temporary_weight_update_time)
-            if weights[-1].temporary_weight_update_time > get_time_str(60 * 60 * 2, flag='ago'):
+            if weights[-1].temporary_weight_update_time > get_time_str(
+                60 * 60 * 2, flag="ago"
+            ):
                 #  If someone has submitted a feedback in past two hours, meet the need.
                 weight_dic = {weight.space_id: 0.0 for weight in weights}
                 weight_dic.update({weights[-1].space_id: weights[-1].temporary_weight})
             else:
-                weight_dic = {weight.space_id: weight.default_weight for weight in weights}
+                weight_dic = {
+                    weight.space_id: weight.default_weight for weight in weights
+                }
                 total_weight_value = 0.0
                 for v in weight_dic.values():
                     total_weight_value += v
                 if total_weight_value > 0:
-                    weight_dic = {k: v / total_weight_value for k, v in weight_dic.items()}
+                    weight_dic = {
+                        k: v / total_weight_value for k, v in weight_dic.items()
+                    }
                 else:
                     weight_dic.update({list(weight_dic.keys())[0]: 1.0})
 
@@ -131,8 +150,10 @@ class VAVControllerV2(VAVController):
                     virtual_target += sp.temperature_target * weight_dic.get(sp.id)
                     virtual_realtime += sp.realtime_temperature * weight_dic.get(sp.id)
             except KeyError:
-                logger.error(f'{self.equipment.id} has wrong vav-space relation')
-                raise HTTPException(status_code=404, detail='This VAV box has wrong eq-sp relation')
+                logger.error(f"{self.equipment.id} has wrong vav-space relation")
+                raise HTTPException(
+                    status_code=404, detail="This VAV box has wrong eq-sp relation"
+                )
 
             self.equipment.virtual_target_temperature = virtual_target
             self.equipment.virtual_realtime_temperature = virtual_realtime
@@ -143,35 +164,58 @@ class VAVControllerV2(VAVController):
     async def rectify(self) -> Tuple[float, float]:
         bad_spaces = list()
         for sp in self.equipment.spaces:
-            if (sp.realtime_temperature > max(27.0, sp.temperature_target) or
-                    sp.realtime_temperature < min(21.0, sp.temperature_target)):
+            if sp.realtime_temperature > max(
+                27.0, sp.temperature_target
+            ) or sp.realtime_temperature < min(21.0, sp.temperature_target):
                 if sp.temperature_target > 0.0:
                     bad_spaces.append(sp)
 
         if bad_spaces:
-            virtual_diff = self.equipment.virtual_target_temperature - self.equipment.virtual_realtime_temperature
+            virtual_diff = (
+                self.equipment.virtual_target_temperature
+                - self.equipment.virtual_realtime_temperature
+            )
             if self.season == Season.cooling:
-                bad_spaces = sorted(bad_spaces, key=attrgetter('diff'))
+                bad_spaces = sorted(bad_spaces, key=attrgetter("diff"))
                 worst = bad_spaces[0]
                 if worst.diff <= 0:
                     if worst.diff < virtual_diff:
-                        self.equipment.virtual_target_temperature = worst.temperature_target
-                        self.equipment.virtual_realtime_temperature = worst.realtime_temperature
+                        self.equipment.virtual_target_temperature = (
+                            worst.temperature_target
+                        )
+                        self.equipment.virtual_realtime_temperature = (
+                            worst.realtime_temperature
+                        )
                 else:
-                    self.equipment.virtual_target_temperature = min(21.0, worst.temperature_target) + 0.5
-                    self.equipment.virtual_realtime_temperature = worst.realtime_temperature
+                    self.equipment.virtual_target_temperature = (
+                        min(21.0, worst.temperature_target) + 0.5
+                    )
+                    self.equipment.virtual_realtime_temperature = (
+                        worst.realtime_temperature
+                    )
             elif self.season == Season.heating:
-                bad_spaces = sorted(bad_spaces, key=attrgetter('diff'), reverse=True)
+                bad_spaces = sorted(bad_spaces, key=attrgetter("diff"), reverse=True)
                 worst = bad_spaces[0]
                 if worst.diff >= 0:
                     if worst.diff > virtual_diff:
-                        self.equipment.virtual_target_temperature = worst.temperature_target
-                        self.equipment.virtual_realtime_temperature = worst.realtime_temperature
+                        self.equipment.virtual_target_temperature = (
+                            worst.temperature_target
+                        )
+                        self.equipment.virtual_realtime_temperature = (
+                            worst.realtime_temperature
+                        )
                 else:
-                    self.equipment.virtual_target_temperature = max(27.0, worst.temperature_target) - 0.5
-                    self.equipment.virtual_realtime_temperature = worst.realtime_temperature
+                    self.equipment.virtual_target_temperature = (
+                        max(27.0, worst.temperature_target) - 0.5
+                    )
+                    self.equipment.virtual_realtime_temperature = (
+                        worst.realtime_temperature
+                    )
 
-        return self.equipment.virtual_target_temperature, self.equipment.virtual_realtime_temperature
+        return (
+            self.equipment.virtual_target_temperature,
+            self.equipment.virtual_realtime_temperature,
+        )
 
     async def run(self) -> None:
         await self.build_virtual_temperature()
@@ -181,7 +225,6 @@ class VAVControllerV2(VAVController):
 
 
 class VAVControllerV3(VAVControllerV2):
-
     def __init__(self, vav_params: VAVBox, season: Season):
         super(VAVControllerV3, self).__init__(vav_params)
         self.season = season
@@ -200,8 +243,12 @@ class VAVControllerV3(VAVControllerV2):
         if not valid_spaces:
             virtual_realtime, virtual_target = np.NAN, np.NAN
         else:
-            sorted_spaces = sorted(valid_spaces, key=lambda x: x.vav_temporary_update_time)
-            if sorted_spaces[-1].vav_temporary_update_time > get_time_str(60 * 60 * 2, flag='ago'):
+            sorted_spaces = sorted(
+                valid_spaces, key=lambda x: x.vav_temporary_update_time
+            )
+            if sorted_spaces[-1].vav_temporary_update_time > get_time_str(
+                60 * 60 * 2, flag="ago"
+            ):
                 virtual_realtime = sorted_spaces[-1].realtime_temperature
                 virtual_target = sorted_spaces[-1].temperature_target
             else:
@@ -237,7 +284,7 @@ async def fetch_vav_control_params(project_id: str, equipment_id: str) -> Dict:
         space_objects = []
         realtime_supply_air_temperature_list = []
         for sp in served_spaces:
-            sp_id = sp.get('id')
+            sp_id = sp.get("id")
             transfer = SpaceInfoService(client, project_id, sp_id)
             current_target = await transfer.get_current_temperature_target()
             realtime_temperature = await platform.get_realtime_temperature(sp_id)
@@ -245,37 +292,41 @@ async def fetch_vav_control_params(project_id: str, equipment_id: str) -> Dict:
             related_equipment = await transfer.get_equipment()
             equipment_objects = []
             for eq in related_equipment:
-                if eq.get('category') == 'ACATFC':
-                    speed = await platform.get_fan_speed(eq.get('id'))
-                    temp_fcu_params = {'id': eq.get('id'), 'air_valve_speed': speed}
+                if eq.get("category") == "ACATFC":
+                    speed = await platform.get_fan_speed(eq.get("id"))
+                    temp_fcu_params = {"id": eq.get("id"), "air_valve_speed": speed}
                     fcu = FCU(**temp_fcu_params)
                     equipment_objects.append(fcu)
-                elif eq.get('category') == 'ACATAH':
+                elif eq.get("category") == "ACATAH":
                     realtime_supply_air_temperature_list.append(
-                        await platform.get_realtime_supply_air_temperature(eq.get('id'))
+                        await platform.get_realtime_supply_air_temperature(eq.get("id"))
                     )
             temp_space_params = {
-                'id': sp_id,
-                'realtime_temperature': realtime_temperature,
-                'equipment': equipment_objects,
-                'temperature_target': current_target,
-                'diff': current_target - realtime_temperature
+                "id": sp_id,
+                "realtime_temperature": realtime_temperature,
+                "equipment": equipment_objects,
+                "temperature_target": current_target,
+                "diff": current_target - realtime_temperature,
             }
             space = Space(**temp_space_params)
             space_objects.append(space)
 
-        realtime_supply_air_temperature = np.array(realtime_supply_air_temperature_list).mean()
-        realtime_supply_air_flow = await platform.get_realtime_supply_air_flow(equipment_id)
+        realtime_supply_air_temperature = np.array(
+            realtime_supply_air_temperature_list
+        ).mean()
+        realtime_supply_air_flow = await platform.get_realtime_supply_air_flow(
+            equipment_id
+        )
         lower_limit, upper_limit = await platform.get_air_flow_limit(equipment_id)
 
         vav_params = {
-            'id': equipment_id,
-            'spaces': space_objects,
-            'supply_air_temperature': realtime_supply_air_temperature,
-            'supply_air_flow': realtime_supply_air_flow,
-            'supply_air_flow_lower_limit': lower_limit,
-            'supply_air_flow_upper_limit': upper_limit,
-            'season': season
+            "id": equipment_id,
+            "spaces": space_objects,
+            "supply_air_temperature": realtime_supply_air_temperature,
+            "supply_air_flow": realtime_supply_air_flow,
+            "supply_air_flow_lower_limit": lower_limit,
+            "supply_air_flow_upper_limit": upper_limit,
+            "season": season,
         }
 
         return vav_params
@@ -299,7 +350,9 @@ async def get_vav_control_v2(db: Session, project_id: str, equipment_id: str) ->
     vav = VAVBox(**vav_params)
     weights = get_weights_by_vav(db, equipment_id)
 
-    vav_controller = VAVControllerV2(vav, [SpaceWeight.from_orm(weight) for weight in weights], vav_params['season'])
+    vav_controller = VAVControllerV2(
+        vav, [SpaceWeight.from_orm(weight) for weight in weights], vav_params["season"]
+    )
     await vav_controller.run()
     regulated_vav = vav_controller.get_results()
 
@@ -307,7 +360,9 @@ async def get_vav_control_v2(db: Session, project_id: str, equipment_id: str) ->
 
 
 @logger.catch()
-async def build_acatva_instructions(params: ACATVAInstructionsRequest) -> ACATVAInstructions:
+async def build_acatva_instructions(
+    params: ACATVAInstructionsRequest,
+) -> ACATVAInstructions:
     space_params = []
     for sp in params.spaces:
         temp_sp = Space(**sp.dict())
@@ -327,7 +382,7 @@ async def build_acatva_instructions(params: ACATVAInstructionsRequest) -> ACATVA
         supply_air_temperature=supply_air_temperature,
         supply_air_flow=params.supply_air_flow,
         supply_air_flow_lower_limit=params.supply_air_flow_lower_limit,
-        supply_air_flow_upper_limit=params.supply_air_flow_upper_limit
+        supply_air_flow_upper_limit=params.supply_air_flow_upper_limit,
     )
 
     controller = VAVControllerV3(vav_params=vav_params, season=Season(params.season))
@@ -337,7 +392,7 @@ async def build_acatva_instructions(params: ACATVAInstructionsRequest) -> ACATVA
     instructions = ACATVAInstructions(
         supply_air_flow_set=regulated_vav.supply_air_flow_set,
         virtual_realtime_temperature=regulated_vav.virtual_realtime_temperature,
-        virtual_temperature_target_set=regulated_vav.virtual_target_temperature
+        virtual_temperature_target_set=regulated_vav.virtual_target_temperature,
     )
 
     return instructions

+ 7 - 6
app/controllers/equipment/ventilation_fan/switch.py

@@ -8,7 +8,6 @@ from app.schemas.equipment import VentilationFan
 
 
 class VentilationFanSwitch(Switch):
-
     def __init__(self, equipment: VentilationFan):
         super(VentilationFanSwitch, self).__init__(equipment)
 
@@ -16,11 +15,13 @@ class VentilationFanSwitch(Switch):
 @logger.catch()
 async def ventilation_fan_switch_control(project_id: str, equipment_id: str) -> None:
     equip_params, day_type = await fetch_data(project_id, equipment_id)
-    is_workday = True if day_type.get('day_type') == 'WeekDay' else False
-    action = await VentilationFanSwitch(VentilationFan(**equip_params)).build_next_action(is_workday)
+    is_workday = True if day_type.get("day_type") == "WeekDay" else False
+    action = await VentilationFanSwitch(
+        VentilationFan(**equip_params)
+    ).build_next_action(is_workday)
     if not is_workday:
-        action = 'off'
-    logger.debug(f'VTSF-{equipment_id}: {action}')
+        action = "off"
+    logger.debug(f"VTSF-{equipment_id}: {action}")
     await send_switch_command(project_id, equipment_id, action)
 
 
@@ -34,6 +35,6 @@ async def build_acvtsf_switch_set(params: ACVTSFSwitchSetRequest) -> str:
     )
     action = await VentilationFanSwitch(vrf).build_next_action(params.is_workday)
     if not params.is_workday:
-        action = 'off'
+        action = "off"
 
     return action

+ 8 - 4
app/controllers/events.py

@@ -10,7 +10,11 @@ ahu_supply_air_temp_set_dict = {}
 
 async def load_q_learning_model():
     base_path = settings.PROJECT_DIR
-    summer_model_path = f'{base_path}/app/resources/ml_models/equipment/fcu/q_learning/net_1_summer.mat'
-    winter_model_path = f'{base_path}/app/resources/ml_models/equipment/fcu/q_learning/net_1_winter.mat'
-    q_learning_models.update({'summer': sio.loadmat(summer_model_path)['net'][0, 0][0]})
-    q_learning_models.update({'winter': sio.loadmat(winter_model_path)['net'][0, 0][0]})
+    summer_model_path = (
+        f"{base_path}/app/resources/ml_models/equipment/fcu/q_learning/net_1_summer.mat"
+    )
+    winter_model_path = (
+        f"{base_path}/app/resources/ml_models/equipment/fcu/q_learning/net_1_winter.mat"
+    )
+    q_learning_models.update({"summer": sio.loadmat(summer_model_path)["net"][0, 0][0]})
+    q_learning_models.update({"winter": sio.loadmat(winter_model_path)["net"][0, 0][0]})

+ 16 - 11
app/controllers/location/ble/space.py

@@ -9,20 +9,23 @@ 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
+    ):
         super(SpacePositioningController, self).__init__()
         self.realtime_ibeacon_list = realtime_ibeacon_list
         self.ibeacon_space_dict = ibeacon_space_dict
 
     def run(self) -> str:
-        ibeacon_list = sorted(self.realtime_ibeacon_list, key=attrgetter('rssi'), reverse=True)
-        strongest_id = ''
+        ibeacon_list = sorted(
+            self.realtime_ibeacon_list, key=attrgetter("rssi"), reverse=True
+        )
+        strongest_id = ""
         for ibeacon in ibeacon_list:
             if ibeacon.rssi != 0:
                 strongest = ibeacon
                 logger.debug(strongest)
-                strongest_id = str(strongest.major) + '-' + str(strongest.minor)
+                strongest_id = str(strongest.major) + "-" + str(strongest.minor)
                 break
 
         logger.debug(strongest_id)
@@ -30,19 +33,21 @@ 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')
+        spaces = await platform.get_items_by_category("Sp")
 
     ibeacon_space_dict = dict()
     for sp in spaces:
         try:
-            major = str(sp['infos']['ctm-iBeacon-Major'])
-            minor = str(sp['infos']['ctm-iBeacon-Minor'])
+            major = str(sp["infos"]["ctm-iBeacon-Major"])
+            minor = str(sp["infos"]["ctm-iBeacon-Minor"])
             if len(major) > 0 and len(minor) > 0:
-                k = major + '-' + minor
-                v = sp['id']
+                k = major + "-" + minor
+                v = sp["id"]
                 ibeacon_space_dict.update({k: v})
         except KeyError:
             pass

+ 28 - 18
app/controllers/nlp/meeting.py

@@ -8,38 +8,46 @@ from app.services.tencent_nlp import TencentNLP
 
 
 class MeetingInfoCatcher:
-
     def __init__(self, nlp_service: TencentNLP, duckling: Duckling):
         super(MeetingInfoCatcher, self).__init__()
         self.nlp_service = nlp_service
         self.duckling = duckling
 
     async def extract_time(self, sentence: str) -> Tuple[str, str, int]:
-        start_time, end_time, duration = '', '', -1
+        start_time, end_time, duration = "", "", -1
         parsed = await self.duckling.parse(sentence)
         for dim in parsed:
-            if dim['dim'] == 'time':
-                start_time = dim['value']['from']['value']
-                end_time = dim['value']['to']['value']
-            if dim['dim'] == 'duration':
-                duration = dim['value']['normalized']['value']
+            if dim["dim"] == "time":
+                start_time = dim["value"]["from"]["value"]
+                end_time = dim["value"]["to"]["value"]
+            if dim["dim"] == "duration":
+                duration = dim["value"]["normalized"]["value"]
 
         return start_time, end_time, duration
 
     async def extract_room_size(self, sentence: str) -> str:
         dp_tokens = await self.nlp_service.get_dependency(sentence)
-        size = ''
+        size = ""
         for token in dp_tokens:
-            if await self.nlp_service.get_word_similarity(token.Word, '会议室') > 0.8:
+            if await self.nlp_service.get_word_similarity(token.Word, "会议室") > 0.8:
                 index = token.Id
                 for item in dp_tokens:
                     if item.HeadId == index:
-                        if 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:
-                            size = 'medium'
-                        if await self.nlp_service.get_word_similarity(item.Word, '大') > 0.9:
-                            size = 'large'
+                        if (
+                            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
+                        ):
+                            size = "medium"
+                        if (
+                            await self.nlp_service.get_word_similarity(item.Word, "大")
+                            > 0.9
+                        ):
+                            size = "large"
                 break
 
         return size
@@ -54,15 +62,17 @@ class MeetingInfoCatcher:
         name_list = []
         if ner_tokens:
             for token in ner_tokens:
-                if token.Type == 'PER':
+                if token.Type == "PER":
                     name_list.append(token.Word)
 
         return name_list
 
     async def run(self, sentence: str) -> Tuple:
-        similarity = await self.nlp_service.get_text_similarity_result('我要开会', [sentence])
+        similarity = await self.nlp_service.get_text_similarity_result(
+            "我要开会", [sentence]
+        )
         if similarity[-1].Score < 0.5:
-            return '', '', -1, '', '', []
+            return "", "", -1, "", "", []
         else:
             start_time, end_time, interval = await self.extract_time(sentence)
             topic = await self.extract_topic(sentence)

+ 218 - 126
app/controllers/targets/temperature.py

@@ -29,15 +29,19 @@ class StepSizeCalculator:
         self.weight = weight
 
     def run(
-            self,
-            realtime_temperature: float,
-            comfortable_temperature: float,
-            feedback: FeedbackValue
+        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))
+            base_step_size = 1.8 / (
+                1 + np.exp((realtime_temperature - comfortable_temperature) / 2)
+            )
         return self.weight.get(feedback.value) * base_step_size
 
 
@@ -71,7 +75,9 @@ class NewTemperatureTargetBuilder(NewTargetBuilder):
     Calculate a new temperature target value.
     """
 
-    def __init__(self, realtime_temperature: float, actual_target: float, step_size: float):
+    def __init__(
+        self, realtime_temperature: float, actual_target: float, step_size: float
+    ):
         self.realtime_temperature = realtime_temperature
         self.actual_target = actual_target
         self.step_size = step_size
@@ -98,13 +104,16 @@ class TemporaryTargetInit:
         self.default_target = default_target
 
     def build(
-            self,
-            extent: float,
-            season: Season,
-            realtime_temperature: 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, self.default_target - 1.0
+            upper_bound, lower_bound = (
+                self.default_target + 1.0,
+                self.default_target - 1.0,
+            )
         else:
             actual_target = np.NAN
             if season == Season.cooling:
@@ -114,7 +123,9 @@ class TemporaryTargetInit:
 
             clipper = Clipper()
             actual_target = clipper.cut(actual_target)
-            upper_bound, lower_bound = actual_target + (extent / 2), actual_target - (extent / 2)
+            upper_bound, lower_bound = actual_target + (extent / 2), actual_target - (
+                extent / 2
+            )
 
         return lower_bound, upper_bound
 
@@ -140,8 +151,17 @@ class SimpleGlobalTemperatureTargetBuilder(GlobalTargetBaseBuilder):
     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
 
@@ -151,30 +171,46 @@ class ExpSmoothingTemperatureTargetBuilder(GlobalTargetBaseBuilder):
     Exponential smooth previous changes and set them as new global target.
     """
 
-    def __init__(self, current_global_target: TemperatureTarget, previous_changes: pd.DataFrame):
+    def __init__(
+        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:
-        now_time = arrow.get(get_time_str(), TIME_FMT).time().strftime('%H%M%S')
+        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([
-            pd.DataFrame({'timestamp': [now_time], 'value': [new_actual_target]}),
-            self.previous_changes,
-        ])
+        previous_changes = pd.concat(
+            [
+                pd.DataFrame({"timestamp": [now_time], "value": [new_actual_target]}),
+                self.previous_changes,
+            ]
+        )
         previous_changes.reset_index(inplace=True)
-        previous_changes['weight1'] = previous_changes['index'].apply(lambda x: (1 / (x + 1)) ** 3)
+        previous_changes["weight1"] = previous_changes["index"].apply(
+            lambda x: (1 / (x + 1)) ** 3
+        )
         new_targets = {}
-        time_index = self.current_global_target.target_schedule['temperatureMin'].keys()
+        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["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"]
+            )
+            temp_target = (
+                previous_changes["value"] * previous_changes["weight"]
+            ).sum() / previous_changes["weight"].sum()
+            new_targets.update(
+                {item: [temp_target - half_extent, temp_target + half_extent]}
             )
-            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())
-            new_targets.update({item: [temp_target - half_extent, temp_target + half_extent]})
 
         return new_targets
 
@@ -190,8 +226,15 @@ class TemporaryTargetBuilder:
 
     def build(self) -> Dict:
         now_str = get_time_str()
-        time_index = arrow.get(arrow.get(now_str, TIME_FMT).shift(minutes=15).timestamp()
-                               // (15 * 60) * (15 * 60)).time().strftime('%H%M%S')
+        time_index = (
+            arrow.get(
+                arrow.get(now_str, TIME_FMT).shift(minutes=15).timestamp()
+                // (15 * 60)
+                * (15 * 60)
+            )
+            .time()
+            .strftime("%H%M%S")
+        )
         return {time_index: [self.lower_target, self.upper_target]}
 
 
@@ -218,7 +261,8 @@ class Packer(metaclass=ABCMeta):
 
 class AdjustmentController(metaclass=ABCMeta):
     """
-    Fetch some data, assemble target adjustment related functions and classes, send the new target to transfer server,
+    Fetch some data, assemble target adjustment related functions and classes, 
+    send the new target to transfer server,
     and return a flag which denote whether transfer server need to request room/control.
     """
 
@@ -243,21 +287,23 @@ class TemperatureTargetCarrier(Carrier):
             duoduo = Duoduo(client, self.project_id)
             platform = DataPlatformService(client, self.project_id)
 
-            realtime_temperature = await platform.get_realtime_temperature(self.object_id)
+            realtime_temperature = await platform.get_realtime_temperature(
+                self.object_id
+            )
             targets = await transfer.get_custom_target()
-            all_day_targets = targets.get('normal_targets')
+            all_day_targets = targets.get("normal_targets")
             current_target = await transfer.get_current_temperature_target()
             is_customized = await transfer.is_customized()
             is_temporary = await transfer.is_temporary()
             season = await duoduo.get_season()
 
         self.result = {
-            'realtime_temperature': realtime_temperature,
-            'all_day_targets': all_day_targets,
-            'current_target': current_target,
-            'is_customized': is_customized,
-            'is_temporary': is_temporary,
-            'season': season
+            "realtime_temperature": realtime_temperature,
+            "all_day_targets": all_day_targets,
+            "current_target": current_target,
+            "is_customized": is_customized,
+            "is_temporary": is_temporary,
+            "season": season,
         }
 
     async def get_result(self) -> Dict:
@@ -275,7 +321,7 @@ class TemperatureTargetV2Carrier(TemperatureTargetCarrier):
             transfer = SpaceInfoService(client, self.project_id, self.object_id)
             previous_changes = await transfer.env_database_get()
 
-        self.result.update({'previous_changes': previous_changes['temperature']})
+        self.result.update({"previous_changes": previous_changes["temperature"]})
 
     async def get_result(self) -> Dict:
         await self.fetch_all()
@@ -292,21 +338,26 @@ class TemperatureTargetPacker:
         self.result = data
 
     def get_temperature_target(self):
-        all_day_targets = self.result['all_day_targets']
+        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]
-            temperature_all_day_targets = all_day_targets[['temperatureMin', 'temperatureMax']].copy().to_dict()
+            extent = (
+                all_day_targets["temperatureMax"].iloc[0]
+                - all_day_targets["temperatureMin"].iloc[0]
+            )
+            temperature_all_day_targets = (
+                all_day_targets[["temperatureMin", "temperatureMax"]].copy().to_dict()
+            )
         else:
             extent = 2.0
             temperature_all_day_targets = {}
         target_params = {
-            'is_customized': self.result['is_customized'],
-            'is_temporary': self.result['is_temporary'],
-            'target_schedule': temperature_all_day_targets,
-            'extent': extent
+            "is_customized": self.result["is_customized"],
+            "is_temporary": self.result["is_temporary"],
+            "target_schedule": temperature_all_day_targets,
+            "extent": extent,
         }
         target = TemperatureTarget(**target_params)
-        self.result.update({'target': target})
+        self.result.update({"target": target})
 
     def get_result(self) -> Dict:
         self.get_temperature_target()
@@ -325,19 +376,29 @@ class TargetDeliver:
     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']:
+            if controlled_result["need_switch_off"]:
                 await transfer.set_temporary_custom()
-            if controlled_result['new_temporary_target']:
-                await transfer.set_custom_target('temperature', controlled_result['new_temporary_target'], '0')
-            if controlled_result['new_global_target']:
-                await transfer.set_custom_target('temperature', controlled_result['new_global_target'], '1')
-            if controlled_result['new_actual_target'] > 0 and controlled_result['need_run_room_control']:
-                await transfer.env_database_set('temperature', controlled_result['new_actual_target'])
+            if controlled_result["new_temporary_target"]:
+                await transfer.set_custom_target(
+                    "temperature", controlled_result["new_temporary_target"], "0"
+                )
+            if controlled_result["new_global_target"]:
+                await transfer.set_custom_target(
+                    "temperature", controlled_result["new_global_target"], "1"
+                )
+            if (
+                controlled_result["new_actual_target"] > 0
+                and controlled_result["need_run_room_control"]
+            ):
+                await transfer.env_database_set(
+                    "temperature", controlled_result["new_actual_target"]
+                )
 
 
 class WeightFlagDeliver:
     """
-    Change a space temporary weight when the space receives a feedback about temperature.
+    Change a space temporary weight when the space receives a feedback about 
+    temperature.
     """
 
     def __init__(self, db: Session, feedback: FeedbackValue):
@@ -345,10 +406,12 @@ class WeightFlagDeliver:
         self.feedback = feedback
 
     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):
+        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
+        ):
             flag = True
         else:
             flag = False
@@ -382,40 +445,46 @@ class TemperatureTargetController:
             need_run_room_control = True
         elif feedback == FeedbackValue.switch_on:
             need_run_room_control = True
-            if not self.data['is_customized']:
+            if not self.data["is_customized"]:
                 new_lower, new_upper = TemporaryTargetInit(1, 24).build(
-                    self.data['extent'],
-                    self.data['season'],
-                    self.data['realtime_temperature']
+                    self.data["extent"],
+                    self.data["season"],
+                    self.data["realtime_temperature"],
                 )
-                new_temporary_target = TemporaryTargetBuilder(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):
+                new_temporary_target = TemporaryTargetBuilder(
+                    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
+        ):
             step_size = StepSizeCalculator(TEMPERATURE_TARGET_WEIGHT).run(
-                self.data['realtime_temperature'],
-                25.0,
-                feedback
+                self.data["realtime_temperature"], 25.0, feedback
             )
             new_actual_target = NewTemperatureTargetBuilder(
-                self.data['realtime_temperature'],
-                self.data['current_target'],
-                step_size
+                self.data["realtime_temperature"],
+                self.data["current_target"],
+                step_size,
             ).build()
             need_run_room_control = True
-            if new_actual_target != self.data['current_target']:
-                new_global_target = SimpleGlobalTemperatureTargetBuilder(self.data['target']).build(new_actual_target)
+            if new_actual_target != self.data["current_target"]:
+                new_global_target = SimpleGlobalTemperatureTargetBuilder(
+                    self.data["target"]
+                ).build(new_actual_target)
         else:
             need_run_room_control = False
 
-        self.result.update({
-            'need_switch_off': need_switch_off,
-            'new_temporary_target': new_temporary_target,
-            'new_global_target': new_global_target,
-            'new_actual_target': new_actual_target,
-            'need_run_room_control': need_run_room_control
-        })
+        self.result.update(
+            {
+                "need_switch_off": need_switch_off,
+                "new_temporary_target": new_temporary_target,
+                "new_global_target": new_global_target,
+                "new_actual_target": new_actual_target,
+                "need_run_room_control": need_run_room_control,
+            }
+        )
 
     def get_result(self) -> Dict:
         return self.result
@@ -440,52 +509,61 @@ class TemperatureTargetControllerV2:
             need_run_room_control = True
         elif feedback == FeedbackValue.switch_on:
             need_run_room_control = True
-            if not self.data['target'].is_customized:
+            if not self.data["target"].is_customized:
                 new_lower, new_upper = TemporaryTargetInit(1, 24).build(
-                    self.data['target'].extent,
-                    self.data['season'],
-                    self.data['realtime_temperature']
+                    self.data["target"].extent,
+                    self.data["season"],
+                    self.data["realtime_temperature"],
                 )
-                new_temporary_target = TemporaryTargetBuilder(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):
+                new_temporary_target = TemporaryTargetBuilder(
+                    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
+        ):
             step_size = StepSizeCalculator(TEMPERATURE_TARGET_WEIGHT).run(
-                self.data['realtime_temperature'],
-                25.0,
-                feedback
+                self.data["realtime_temperature"], 25.0, feedback
             )
             new_actual_target = NewTemperatureTargetBuilder(
-                self.data['realtime_temperature'],
-                self.data['current_target'],
-                step_size
+                self.data["realtime_temperature"],
+                self.data["current_target"],
+                step_size,
             ).build()
             need_run_room_control = True
-            if new_actual_target != self.data['current_target']:
+            if new_actual_target != self.data["current_target"]:
                 new_global_target = ExpSmoothingTemperatureTargetBuilder(
-                    self.data['target'],
-                    self.data['previous_changes']
+                    self.data["target"], self.data["previous_changes"]
                 ).build(new_actual_target)
         else:
             need_run_room_control = False
 
-        self.result.update({
-            'need_switch_off': need_switch_off,
-            'new_temporary_target': new_temporary_target,
-            'new_global_target': new_global_target,
-            'new_actual_target': new_actual_target,
-            'need_run_room_control': need_run_room_control
-        })
+        self.result.update(
+            {
+                "need_switch_off": need_switch_off,
+                "new_temporary_target": new_temporary_target,
+                "new_global_target": new_global_target,
+                "new_actual_target": new_actual_target,
+                "need_run_room_control": need_run_room_control,
+            }
+        )
 
     def get_result(self) -> Dict:
         return self.result
 
 
 @logger.catch()
-async def temperature_target_control_v1(project_id: str, space_id: str, feedback: FeedbackValue, db: Session) -> bool:
-    temperature_target_raw_data = await TemperatureTargetCarrier(project_id, space_id).get_result()
-    temperature_target_data = TemperatureTargetPacker(temperature_target_raw_data).get_result()
+async def temperature_target_control_v1(
+    project_id: str, space_id: str, feedback: FeedbackValue, db: Session
+) -> bool:
+    temperature_target_raw_data = await TemperatureTargetCarrier(
+        project_id, space_id
+    ).get_result()
+    temperature_target_data = TemperatureTargetPacker(
+        temperature_target_raw_data
+    ).get_result()
     controller = TemperatureTargetController(temperature_target_data)
     controller.run(feedback)
     controlled_result = controller.get_result()
@@ -493,33 +571,47 @@ async def temperature_target_control_v1(project_id: str, space_id: str, feedback
 
     WeightFlagDeliver(db, feedback).save(space_id)
 
-    return controlled_result['need_run_room_control']
+    return controlled_result["need_run_room_control"]
 
 
 @logger.catch()
-async def temperature_target_control_v2(project_id: str, space_id: str, feedback: FeedbackValue) -> bool:
-    temperature_target_raw_data = await TemperatureTargetV2Carrier(project_id, space_id).get_result()
-    temperature_target_data = TemperatureTargetPacker(temperature_target_raw_data).get_result()
+async def temperature_target_control_v2(
+    project_id: str, space_id: str, feedback: FeedbackValue
+) -> bool:
+    temperature_target_raw_data = await TemperatureTargetV2Carrier(
+        project_id, space_id
+    ).get_result()
+    temperature_target_data = TemperatureTargetPacker(
+        temperature_target_raw_data
+    ).get_result()
     controller = TemperatureTargetControllerV2(temperature_target_data)
     controller.run(feedback)
     controlled_result = controller.get_result()
     await TargetDeliver(project_id, space_id).send(controlled_result)
 
-    return controlled_result['need_run_room_control']
+    return controlled_result["need_run_room_control"]
 
 
 @logger.catch()
-async def get_target_after_feedback(project_id: str, space_id: str, feedback: FeedbackValue) -> float:
-    if project_id == 'Pj1101050030':
-        temperature_target_raw_data = await TemperatureTargetCarrier(project_id, space_id).get_result()
+async def get_target_after_feedback(
+    project_id: str, space_id: str, feedback: FeedbackValue
+) -> float:
+    if project_id == "Pj1101050030":
+        temperature_target_raw_data = await TemperatureTargetCarrier(
+            project_id, space_id
+        ).get_result()
     else:
-        temperature_target_raw_data = await TemperatureTargetV2Carrier(project_id, space_id).get_result()
-    temperature_target_data = TemperatureTargetPacker(temperature_target_raw_data).get_result()
-    if project_id == 'Pj1101050030':
+        temperature_target_raw_data = await TemperatureTargetV2Carrier(
+            project_id, space_id
+        ).get_result()
+    temperature_target_data = TemperatureTargetPacker(
+        temperature_target_raw_data
+    ).get_result()
+    if project_id == "Pj1101050030":
         controller = TemperatureTargetController(temperature_target_data)
     else:
         controller = TemperatureTargetControllerV2(temperature_target_data)
     controller.run(feedback)
     controlled_result = controller.get_result()
 
-    return controlled_result.get('new_actual_target')
+    return controlled_result.get("new_actual_target")

+ 15 - 8
app/core/config.py

@@ -2,7 +2,14 @@
 
 from typing import Any, Dict, Optional
 
-from pydantic import AnyHttpUrl, BaseSettings, DirectoryPath, PostgresDsn, SecretStr, validator
+from pydantic import (
+    AnyHttpUrl,
+    BaseSettings,
+    DirectoryPath,
+    PostgresDsn,
+    SecretStr,
+    validator,
+)
 
 
 class Settings(BaseSettings):
@@ -35,21 +42,21 @@ class Settings(BaseSettings):
     POSTGRES_DB: str
     SQLALCHEMY_DATABASE_URL: Optional[PostgresDsn] = None
 
-    @validator('SQLALCHEMY_DATABASE_URL', pre=True)
+    @validator("SQLALCHEMY_DATABASE_URL", pre=True)
     def assemble_db_connection(cls, v: Optional[str], values: Dict[str, Any]) -> Any:
         if isinstance(v, str):
             return v
         return PostgresDsn.build(
-            scheme='postgresql',
-            user=values.get('POSTGRES_USER'),
-            password=values.get('POSTGRES_PASSWORD'),
-            host=values.get('POSTGRES_SERVER'),
-            path=f'/{values.get("POSTGRES_DB") or ""}'
+            scheme="postgresql",
+            user=values.get("POSTGRES_USER"),
+            password=values.get("POSTGRES_PASSWORD"),
+            host=values.get("POSTGRES_SERVER"),
+            path=f'/{values.get("POSTGRES_DB") or ""}',
         )
 
     class Config:
         case_sensitive = True
-        env_file = '.env'
+        env_file = ".env"
 
 
 settings = Settings()

+ 6 - 6
app/crud/base.py

@@ -27,7 +27,7 @@ class CRUDBase(Generic[ModelType, CreateSchemaType, UpdateSchemaType]):
         return db.query(self.model).filter(self.model.id == id).first()
 
     def get_multi(
-            self, db: Session, *, skip: int = 0, limit: int = 100
+        self, db: Session, *, skip: int = 0, limit: int = 100
     ) -> List[ModelType]:
         return db.query(self.model).offset(skip).limit(limit).all()
 
@@ -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: Union[UpdateSchemaType, Dict[str, Any]]
     ) -> ModelType:
         obj_data = jsonable_encoder(db_obj)
         if isinstance(obj_in, dict):

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

@@ -23,7 +23,7 @@ def create_weight(db: Session, weight: SpaceWeightCreate) -> VAVRoomWeight:
         default_weight=weight.default_weight,
         project_id=weight.project_id,
         space_id=weight.space_id,
-        vav_box_id=weight.vav_box_id
+        vav_box_id=weight.vav_box_id,
     )
     db.add(db_weight)
     db.commit()
@@ -31,13 +31,15 @@ def create_weight(db: Session, weight: SpaceWeightCreate) -> VAVRoomWeight:
     return db_weight
 
 
-def update_weight(db: Session, db_weight: VAVRoomWeight, weight_in: SpaceWeightUpdate) -> VAVRoomWeight:
+def update_weight(
+    db: Session, db_weight: VAVRoomWeight, weight_in: SpaceWeightUpdate
+) -> VAVRoomWeight:
     weight_data = jsonable_encoder(db_weight)
     update_data = weight_in.dict(exclude_unset=True)
     for field in weight_data:
         if field in update_data:
             setattr(db_weight, field, update_data[field])
-            if field == 'temporary_weight':
+            if field == "temporary_weight":
                 db_weight.temporary_weight_update_time = get_time_str()
     db.add(db_weight)
     db.commit()

+ 6 - 1
app/db/session.py

@@ -4,7 +4,12 @@ from sqlalchemy.orm import sessionmaker
 
 from app.core.config import settings
 
-engine = create_engine(settings.SQLALCHEMY_DATABASE_URL, pool_pre_ping=True, pool_size=1000, max_overflow=2000)
+engine = create_engine(
+    settings.SQLALCHEMY_DATABASE_URL,
+    pool_pre_ping=True,
+    pool_size=1000,
+    max_overflow=2000,
+)
 SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
 
 Base = declarative_base()

+ 0 - 2
app/main.py

@@ -10,7 +10,6 @@ from loguru import logger
 from app.api.routers import (
     algorithms,
     targets,
-    equipment,
     space,
     bluetooth,
     devices,
@@ -45,7 +44,6 @@ def get_application() -> FastAPI:
     application.include_router(
         early_start.router, prefix="/model-path", tags=["Model Path"]
     )
-    application.include_router(equipment.router, prefix="/equip", tags=["Equipment"])
     application.include_router(nlp.router, prefix="/nlp-service", tags=["NLP"])
     application.include_router(
         positioning.router, prefix="/positioning-service", tags=["Positioning Service"]

+ 20 - 18
app/models/domain/devices.py

@@ -7,20 +7,20 @@ from app.models.domain.feedback import FeedbackValue
 
 
 class ThermalMode(str, Enum):
-    cooling = 'cooling'
-    heating = 'heating'
-    hold = 'hold'
+    cooling = "cooling"
+    heating = "heating"
+    hold = "hold"
 
 
 class DevicesInstructionsBaseResponse(BaseModel):
-    project_id: str = Field(None, alias='projectId')
-    device_id: str = Field(None, alias='equipId')
+    project_id: str = Field(None, alias="projectId")
+    device_id: str = Field(None, alias="equipId")
     output: Dict
 
 
 class DevicesEarlyStartTime(BaseModel):
-    project_id: str = Field(None, alias='projectId')
-    space_id: str = Field(None, alias='spaceId')
+    project_id: str = Field(None, alias="projectId")
+    space_id: str = Field(None, alias="spaceId")
     minutes: float
 
 
@@ -54,11 +54,11 @@ class ACATFCInstructionsRequest(BaseModel):
 
 
 class ACATFCInstructionsResponse(BaseModel):
-    switch_set: int = Field(None, alias='onOff')
-    speed_set: int = Field(None, alias='speed')
-    temperature_set: float = Field(None, alias='temperature')
-    mode_set: int = Field(None, alias='mode')
-    water_valve_switch_set: int = Field(None, alias='water')
+    switch_set: int = Field(None, alias="onOff")
+    speed_set: int = Field(None, alias="speed")
+    temperature_set: float = Field(None, alias="temperature")
+    mode_set: int = Field(None, alias="mode")
+    water_valve_switch_set: int = Field(None, alias="water")
 
 
 class ACATFCEarlyStartPredictionRequest(BaseModel):
@@ -92,9 +92,11 @@ class ACATVAInstructionsRequest(BaseModel):
 
 
 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')
+    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"
+    )
 
 
 class ACATAHFreqSetRequest(BaseModel):
@@ -111,9 +113,9 @@ class ACATAHFreqSetResponse(BaseModel):
 
 
 class SwitchSet(str, Enum):
-    on = 'on'
-    off = 'off'
-    hold = 'hold'
+    on = "on"
+    off = "off"
+    hold = "hold"
 
 
 class SwitchSetRequestBase(BaseModel):

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

@@ -8,7 +8,7 @@ from app.schemas.equipment import BaseEquipment
 
 
 class EquipmentControlResponse(BaseModel):
-    result: str = 'success'
+    result: str = "success"
     projectId: str
     equipId: str
     time: str

+ 13 - 13
app/models/domain/feedback.py

@@ -4,16 +4,16 @@ from enum import Enum
 
 
 class FeedbackValue(str, Enum):
-    null = 'null'
-    a_little_cold = '1'
-    so_cold = '2'
-    a_little_hot = '3'
-    so_hot = '4'
-    noisy_or_blowy = '5'
-    so_stuffy = '6'
-    more_sunshine = '7'
-    less_sunshine = '8'
-    send_a_repairman = '9'
-    switch_off = '10'
-    nice = '11'
-    switch_on = '12'
+    null = "null"
+    a_little_cold = "1"
+    so_cold = "2"
+    a_little_hot = "3"
+    so_hot = "4"
+    noisy_or_blowy = "5"
+    so_stuffy = "6"
+    more_sunshine = "7"
+    less_sunshine = "8"
+    send_a_repairman = "9"
+    switch_off = "10"
+    nice = "11"
+    switch_on = "12"

+ 4 - 4
app/models/domain/nlp.py

@@ -5,10 +5,10 @@ from pydantic import BaseModel
 
 
 class RoomSize(str, Enum):
-    small = 'small'
-    medium = 'medium'
-    large = 'large'
-    unknown = ''
+    small = "small"
+    medium = "medium"
+    large = "large"
+    unknown = ""
 
 
 class NLPResponseBase(BaseModel):

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

@@ -4,7 +4,7 @@ from pydantic import BaseModel
 
 
 class SpaceControlResponse(BaseModel):
-    result: str = 'success'
+    result: str = "success"
     projectId: str
     roomId: str
     flag: int

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

@@ -6,7 +6,7 @@ from pydantic import BaseModel
 
 
 class TargetReadjustResponse(BaseModel):
-    result: str = 'success'
+    result: str = "success"
     projectId: str
     roomId: str
     flag: int

+ 8 - 8
app/models/meetings/meeting_info.py

@@ -6,22 +6,22 @@ from app.db.session import Base
 
 
 class MeetingInfo(Base):
-    __tablename__ = 'meetings_info'
+    __tablename__ = "meetings_info"
 
     id = Column(String, primary_key=True, index=True)
-    initiator_id = Column(String, ForeignKey('tenantslink_users.id'))
-    room_id = Column(String, ForeignKey('meeting_rooms_info.id'))
+    initiator_id = Column(String, ForeignKey("tenantslink_users.id"))
+    room_id = Column(String, ForeignKey("meeting_rooms_info.id"))
     start_time = Column(TIMESTAMP)
     end_time = Column(TIMESTAMP)
     topic = Column(String)
     status = Column()
 
-    initiator = relationship('TenantslinkUser', back_populates='meetings_info')
-    room = relationship('MeetingRoom', back_populates='meetings_info')
+    initiator = relationship("TenantslinkUser", back_populates="meetings_info")
+    room = relationship("MeetingRoom", back_populates="meetings_info")
 
 
 class MeetingRoom(Base):
-    __tablename__ = 'meeting_rooms_info'
+    __tablename__ = "meeting_rooms_info"
 
     id = Column(String, primary_key=True, index=True)
     name = Column(String)
@@ -31,14 +31,14 @@ class MeetingRoom(Base):
 
 
 class MeetingAttendee(Base):
-    __tablename__ = 'meeting_attendees'
+    __tablename__ = "meeting_attendees"
 
     meeting_id = Column(String, index=True)
     user_id = Column(String, index=True)
 
 
 class TenantslinkUser(Base):
-    __tablename__ = 'tenantslink_users'
+    __tablename__ = "tenantslink_users"
 
     id = Column(String, primary_key=True, index=True)
     name = Column(String)

+ 1 - 1
app/models/ml_models_path/early_start.py

@@ -6,7 +6,7 @@ from app.db.session import Base
 
 
 class EarlyStartDTRModelPath(Base):
-    __tablename__ = 'early_start_DTR_models'
+    __tablename__ = "early_start_DTR_models"
 
     id = Column(Integer, primary_key=True, index=True)
     project_id = Column(String, nullable=False)

+ 2 - 2
app/models/space/weight.py

@@ -6,7 +6,7 @@ from app.db.session import Base
 
 
 class VAVRoomWeight(Base):
-    __tablename__ = 'vav_room_weights'
+    __tablename__ = "vav_room_weights"
 
     id = Column(Integer, primary_key=True, index=True)
     default_weight = Column(Float)
@@ -14,4 +14,4 @@ class VAVRoomWeight(Base):
     space_id = Column(String, index=True, nullable=False)
     vav_box_id = Column(String, index=True, nullable=False)
     temporary_weight = Column(Float, default=0.0)
-    temporary_weight_update_time = Column(String, default='20201111110400')
+    temporary_weight_update_time = Column(String, default="20201111110400")

+ 25 - 25
app/resources/params.py

@@ -1,44 +1,44 @@
 # -*- coding: utf-8 -*-
 
 TEMPERATURE_RELATED_FEEDBACK_WEIGHT = {
-    'a little cold': 1,
-    'so cold': 3,
-    'a little hot': -1,
-    'so hot': -2,
-    'switch on': 0.1,
+    "a little cold": 1,
+    "so cold": 3,
+    "a little hot": -1,
+    "so hot": -2,
+    "switch on": 0.1,
 }
 
 TEMPERATURE_TARGET_WEIGHT = {
-    '1': 1,
-    '2': 2,
-    '3': -1,
-    '4': -2,
+    "1": 1,
+    "2": 2,
+    "3": -1,
+    "4": -2,
 }
 
 CO2_RELATED_FEEDBACK_WEIGHT = {
-    'noisy or blowy': 100,
-    'so stuffy': -100,
+    "noisy or blowy": 100,
+    "so stuffy": -100,
 }
 
 SWITCH_RELATED_FEEDBACK = [
-    'a little cold',
-    'so cold',
-    'a little hot',
-    'so hot',
-    'so stuffy',
-    'switch on',
+    "a little cold",
+    "so cold",
+    "a little hot",
+    "so hot",
+    "so stuffy",
+    "switch on",
 ]
 
 TEMPERATURE_RELATED_FEEDBACK = [
-    'a little cold',
-    'so cold',
-    'a little hot',
-    'so hot',
-    'switch on'
+    "a little cold",
+    "so cold",
+    "a little hot",
+    "so hot",
+    "switch on",
 ]
 
 CO2_RELATED_FEEDBACK = [
-    'noisy or blowy',
-    'so stuffy',
-    'switch on',
+    "noisy or blowy",
+    "so stuffy",
+    "switch on",
 ]

+ 12 - 12
app/schemas/feedback.py

@@ -4,15 +4,15 @@ from enum import Enum
 
 
 class Feedback(str, Enum):
-    a_little_cold = 'a little cold'
-    so_cold = 'so cold'
-    a_little_hot = 'a little hot'
-    so_hot = 'so hot'
-    noisy_or_blowy = 'noisy or blowy'
-    so_stuffy = 'so stuffy'
-    more_sunshine = 'more sunshine'
-    less_sunshine = 'less sunshine'
-    send_a_repairman = 'send a repairman'
-    switch_off = 'switch off'
-    nice = 'nice'
-    switch_on = 'switch on'
+    a_little_cold = "a little cold"
+    so_cold = "so cold"
+    a_little_hot = "a little hot"
+    so_hot = "so hot"
+    noisy_or_blowy = "noisy or blowy"
+    so_stuffy = "so stuffy"
+    more_sunshine = "more sunshine"
+    less_sunshine = "less sunshine"
+    send_a_repairman = "send a repairman"
+    switch_off = "switch off"
+    nice = "nice"
+    switch_on = "switch on"

+ 0 - 1
app/schemas/space.py

@@ -15,4 +15,3 @@ class Space(BaseModel):
     vav_default_weight: Optional[float]
     vav_temporary_weight: Optional[float]
     vav_temporary_update_time: Optional[str]
-

+ 3 - 6
app/services/duckling.py

@@ -17,12 +17,9 @@ class Duckling:
         self._host = URL(server_settings.DUCKLING_HOST)
 
     @api_exception
-    async def parse(self, text: str, locale: str = 'zh_CN') -> Dict:
-        url = self._host.join('parse')
-        data = {
-            'locale': locale,
-            'text': text
-        }
+    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)
 
         return raw_response.json()

+ 118 - 127
app/services/platform.py

@@ -15,44 +15,38 @@ from app.utils.math import round_half_up
 
 
 class InfoCode(str, Enum):
-    temperature = 'Tdb'
-    co2 = 'CO2'
-    hcho = 'HCHO'
-    pm2d5 = 'PM2d5'
-    humidity = 'RH'
-    supply_air_flow = 'SupplyAirFlow'
-    supply_air_flow_set = 'SupplyAirFlowSet'
-    supply_air_temperature = 'SupplyAirTemp'
-    supply_air_temperature_set = 'SupplyAirTempSet'
-    fan_speed = 'FanGear'
-    fan_speed_set = 'FanGearSet'
-    fan_freq = 'FanFreq'
-    fan_freq_set = 'FanFreqSet'
-    supply_static_press = 'SupplyStaticPress'
-    supply_static_press_set = 'SupplyStaticPressSet'
-    running_status = 'RunStatus'
-    cloud_status = 'InCloudStatus'
-    equip_switch_set = 'EquipSwitchSet'
-    return_air_temperature = 'ReturnAirTemp'
-    chill_water_valve_opening_set = 'ChillWaterValveOpeningSet'
-    hot_water_valve_opening_set = 'HotWaterValveOpeningSet'
-    water_valve_switch_set = 'WaterValveSwitchSet'
-    in_cloud_set = 'InCloudSet'
-    work_mode_set = 'WorkModeSet'
-    supply_temperature = 'SupplyTemp'
-    water_out_temperature = 'WaterOutTemp'
-    water_in_temperature = 'WaterInTemp'
-    valve_opening = 'ValveOpening'
+    temperature = "Tdb"
+    co2 = "CO2"
+    hcho = "HCHO"
+    pm2d5 = "PM2d5"
+    humidity = "RH"
+    supply_air_flow = "SupplyAirFlow"
+    supply_air_flow_set = "SupplyAirFlowSet"
+    supply_air_temperature = "SupplyAirTemp"
+    supply_air_temperature_set = "SupplyAirTempSet"
+    fan_speed = "FanGear"
+    fan_speed_set = "FanGearSet"
+    fan_freq = "FanFreq"
+    fan_freq_set = "FanFreqSet"
+    supply_static_press = "SupplyStaticPress"
+    supply_static_press_set = "SupplyStaticPressSet"
+    running_status = "RunStatus"
+    cloud_status = "InCloudStatus"
+    equip_switch_set = "EquipSwitchSet"
+    return_air_temperature = "ReturnAirTemp"
+    chill_water_valve_opening_set = "ChillWaterValveOpeningSet"
+    hot_water_valve_opening_set = "HotWaterValveOpeningSet"
+    water_valve_switch_set = "WaterValveSwitchSet"
+    in_cloud_set = "InCloudSet"
+    work_mode_set = "WorkModeSet"
+    supply_temperature = "SupplyTemp"
+    water_out_temperature = "WaterOutTemp"
+    water_in_temperature = "WaterInTemp"
+    valve_opening = "ValveOpening"
 
 
 class DataPlatformService(Service):
-
-    def __init__(
-            self,
-            client: AsyncClient,
-            project_id: str,
-            server_settings=settings
-    ):
+    def __init__(self, client: AsyncClient, project_id: str, server_settings=settings):
         super(DataPlatformService, self).__init__(client)
         self._project_id = project_id
         self._base_url = URL(server_settings.PLATFORM_HOST)
@@ -60,63 +54,68 @@ class DataPlatformService(Service):
         self._secret = server_settings.PLATFORM_SECRET
 
     def _common_parameters(self) -> Dict:
-        return {'projectId': self._project_id, 'secret': self._secret}
+        return {"projectId": self._project_id, "secret": self._secret}
 
     async def get_realtime_data(self, code: InfoCode, object_id: str) -> float:
-        url = self._base_url.join('data-platform-3/hisdata/query_by_obj')
+        url = self._base_url.join("data-platform-3/hisdata/query_by_obj")
         params = self._common_parameters()
-        start_time = get_time_str(60 * 60, flag='ago')
+        start_time = get_time_str(60 * 60, flag="ago")
         payload = {
-            'criteria': {
-                'id': object_id,
-                'code': code.value,
-                'receivetime': {
-                    '$gte': start_time,
-                    '$lte': self._now_time,
-                }
+            "criteria": {
+                "id": object_id,
+                "code": code.value,
+                "receivetime": {
+                    "$gte": start_time,
+                    "$lte": self._now_time,
+                },
             }
         }
         raw_info = await self._post(url, params, payload)
 
         try:
-            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):
-                logger.info(f'delayed data - {object_id}: ({latest_time}, {latest_data})')
+            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
+            ):
+                logger.info(
+                    f"delayed data - {object_id}: ({latest_time}, {latest_data})"
+                )
             value = round_half_up(latest_data, 2)
         except (IndexError, KeyError, TypeError):
             value = np.NAN
 
         return value
 
-    async def get_duration(self, code: InfoCode, object_id: str, duration: int) -> List[Dict]:
-        url = self._base_url.join('data-platform-3/hisdata/query_by_obj')
+    async def get_duration(
+        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')
+        start_time = get_time_str(duration, flag="ago")
         payload = {
-            'criteria': {
-                'id': object_id,
-                'code': code.value,
-                'receivetime': {
-                    '$gte': start_time,
-                    '$lte': self._now_time,
-                }
+            "criteria": {
+                "id": object_id,
+                "code": code.value,
+                "receivetime": {
+                    "$gte": start_time,
+                    "$lte": self._now_time,
+                },
             }
         }
         raw_info = await self._post(url, params, payload)
 
         try:
-            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):
+            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
+            ):
                 result = []
-                logger.info(f'delayed data - {object_id}: ({latest_time})')
+                logger.info(f"delayed data - {object_id}: ({latest_time})")
             else:
                 result = [
-                    {
-                        'timestamp': item['receivetime'],
-                        'value': item['data']
-                    }
+                    {"timestamp": item["receivetime"], "value": item["data"]}
                     for item in content
                 ]
         except (KeyError, TypeError, IndexError):
@@ -124,7 +123,9 @@ class DataPlatformService(Service):
 
         return result
 
-    async def get_past_data(self, code: InfoCode, object_id: str, interval: int) -> float:
+    async def get_past_data(
+        self, code: InfoCode, object_id: str, interval: int
+    ) -> float:
         """
         Query past data from data platform.
         :param code: Info code
@@ -132,27 +133,31 @@ class DataPlatformService(Service):
         :param interval: time interval(seconds) from now to past
         :return: a past value
         """
-        url = self._base_url.join('data-platform-3/hisdata/query_by_obj')
+        url = self._base_url.join("data-platform-3/hisdata/query_by_obj")
         params = self._common_parameters()
-        start_time = get_time_str(60 * 60 + interval, flag='ago')
-        end_time = get_time_str(interval, flag='ago')
+        start_time = get_time_str(60 * 60 + interval, flag="ago")
+        end_time = get_time_str(interval, flag="ago")
         payload = {
-            'criteria': {
-                'id': object_id,
-                'code': code.value,
-                'receivetime': {
-                    '$gte': start_time,
-                    '$lte': end_time,
-                }
+            "criteria": {
+                "id": object_id,
+                "code": code.value,
+                "receivetime": {
+                    "$gte": start_time,
+                    "$lte": end_time,
+                },
             }
         }
         raw_info = await self._post(url, params, payload)
 
         try:
-            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):
-                logger.info(f'delayed data - {object_id}: ({latest_time}, {latest_data})')
+            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
+            ):
+                logger.info(
+                    f"delayed data - {object_id}: ({latest_time}, {latest_data})"
+                )
             value = round_half_up(latest_data, 2)
         except (KeyError, IndexError, TypeError):
             value = np.NAN
@@ -162,26 +167,24 @@ 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
+        self,
+        from_id: Optional[str] = None,
+        graph_id: Optional[str] = None,
+        relation_type: Optional[str] = None,
     ) -> List[Dict]:
-        url = self._base_url.join('data-platform-3/relation/query')
+        url = self._base_url.join("data-platform-3/relation/query")
         params = self._common_parameters()
         criteria = dict()
         if from_id:
-            criteria.update({'from_id': from_id})
+            criteria.update({"from_id": from_id})
         if graph_id:
-            criteria.update({'graph_id': graph_id})
+            criteria.update({"graph_id": graph_id})
         if relation_type:
-            criteria.update({'relation_type': relation_type})
-        payload = {
-            'criteria': criteria
-        }
+            criteria.update({"relation_type": relation_type})
+        payload = {"criteria": criteria}
         raw_info = await self._post(url, params, payload)
 
-        return raw_info.get('Content')
+        return raw_info.get("Content")
 
     async def get_realtime_temperature(self, space_id: str) -> float:
         return await self.get_realtime_data(InfoCode.temperature, space_id)
@@ -205,38 +208,35 @@ class DataPlatformService(Service):
         return await self.get_realtime_data(InfoCode.supply_air_flow, equipment_id)
 
     async def get_realtime_supply_air_temperature(self, equipment_id: str) -> float:
-        return await self.get_realtime_data(InfoCode.supply_air_temperature, equipment_id)
+        return await self.get_realtime_data(
+            InfoCode.supply_air_temperature, equipment_id
+        )
 
     async def get_realtime_supply_air_temperature_set(self, equipment_id: str) -> float:
-        return await self.get_realtime_data(InfoCode.supply_air_temperature_set, equipment_id)
+        return await self.get_realtime_data(
+            InfoCode.supply_air_temperature_set, equipment_id
+        )
 
     async def get_fan_speed(self, equipment_id: str) -> float:
         return await self.get_realtime_data(InfoCode.fan_speed, equipment_id)
 
     async def get_static_info(self, code: str, object_id: str):
-        url = self._base_url.join('data-platform-3/object/batch_query')
+        url = self._base_url.join("data-platform-3/object/batch_query")
         params = self._common_parameters()
-        payload = {
-            'customInfo': True,
-            'criterias': [
-                {
-                    'id': object_id
-                }
-            ]
-        }
+        payload = {"customInfo": True, "criterias": [{"id": object_id}]}
         raw_info = await self._post(url, params, payload)
 
         try:
-            info = raw_info['Content'][0]['infos'][code]
+            info = raw_info["Content"][0]["infos"][code]
         except (KeyError, IndexError, TypeError) as e:
-            logger.error(f'id: {object_id}, details: {e}')
+            logger.error(f"id: {object_id}, details: {e}")
             info = None
 
         return info
 
     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)
+        lower = await self.get_static_info("MinAirFlow", equipment_id)
+        upper = await self.get_static_info("MaxAirFlow", equipment_id)
         if lower is None:
             lower = 150.0
         if upper is None:
@@ -245,12 +245,12 @@ class DataPlatformService(Service):
         return lower, upper
 
     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)
+        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:
-            on_time = '080000'
+            on_time = "080000"
         if not off_time:
-            off_time = '190000'
+            off_time = "190000"
 
         return on_time, off_time
 
@@ -273,28 +273,19 @@ class DataPlatformService(Service):
         return await self.get_realtime_data(InfoCode.return_air_temperature, device_id)
 
     async def set_code_value(self, object_id: str, code: InfoCode, value: float):
-        url = self._base_url.join('data-platform-3/parameter/setting')
+        url = self._base_url.join("data-platform-3/parameter/setting")
         params = self._common_parameters()
-        payload = {
-            'id': object_id,
-            'code': code.value,
-            'value': value
-        }
+        payload = {"id": object_id, "code": code.value, "value": value}
 
         await self._post(url, params, payload)
 
     async def get_items_by_category(self, code) -> List:
-        url = self._base_url.join('data-platform-3/object/subset_query')
+        url = self._base_url.join("data-platform-3/object/subset_query")
         params = self._common_parameters()
-        payload = {
-            'customInfo': True,
-            'criteria': {
-                'type': [code]
-            }
-        }
+        payload = {"customInfo": True, "criteria": {"type": [code]}}
 
         raw_info = await self._post(url, params, payload)
-        items = raw_info.get('Content')
+        items = raw_info.get("Content")
         results = items if items else []
 
         return results

+ 13 - 21
app/services/rwd.py

@@ -11,15 +11,14 @@ from app.utils.date import get_time_str, TIME_FMT
 
 
 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: Optional[str] = None,
+        user_id: Optional[str] = None,
+        server_settings=settings,
     ):
         super(RealWorldService, self).__init__(client)
         self._group_code = group_code
@@ -30,26 +29,19 @@ class RealWorldService(Service):
         self._now_time = get_time_str()
 
     def _common_parameters(self) -> Dict:
-        return {
-            'groupCode': self._group_code,
-            'projectId': self._project_id
-        }
+        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: Optional[List] = None, class_code: Optional[str] = None
     ):
-        url = self._base_url.join('/rwd/instance/object/query')
+        url = self._base_url.join("/rwd/instance/object/query")
         params = self._common_parameters()
         criteria = dict()
         if object_id:
-            criteria.update({'id': object_id})
+            criteria.update({"id": object_id})
         if class_code:
-            criteria.update({'classCode': class_code})
-        payload = {
-            'criteria': criteria
-        }
+            criteria.update({"classCode": class_code})
+        payload = {"criteria": criteria}
         raw_info = await self._post(url, params, payload)
 
         return raw_info

+ 12 - 9
app/services/service.py

@@ -16,7 +16,7 @@ def api_exception(func):
         except Exception:
             raise HTTPException(
                 status_code=500,
-                detail='The server did not receive a correct response from the upstream server.'
+                detail=("The server did not receive a correct response fromtheupstream server."),
             )
         else:
             return r
@@ -25,12 +25,13 @@ def api_exception(func):
 
 
 class Service:
-
     def __init__(self, client: AsyncClient) -> None:
         self._client = client
 
     @api_exception
-    async def _get(self, url: URL, params: Optional[Dict] = None, headers: Optional[Dict] = None) -> Dict:
+    async def _get(
+        self, url: URL, params: Optional[Dict] = None, headers: Optional[Dict] = None
+    ) -> Dict:
         raw_response = await self._client.get(url, params=params, headers=headers)
         # logger.debug(f'{url} - elapsed: {raw_response.elapsed.total_seconds()}')
 
@@ -38,13 +39,15 @@ class Service:
 
     @api_exception
     async def _post(
-            self,
-            url: URL,
-            params: Optional[Dict] = None,
-            payload: Optional[Dict] = None,
-            headers: Optional[Dict] = None
+        self,
+        url: URL,
+        params: Optional[Dict] = None,
+        payload: Optional[Dict] = None,
+        headers: Optional[Dict] = None,
     ) -> Dict:
-        raw_response = await self._client.post(url, params=params, json=payload, headers=headers)
+        raw_response = await self._client.post(
+            url, params=params, json=payload, headers=headers
+        )
         # logger.debug(f'{url} - elapsed: {raw_response.elapsed.total_seconds()}')
 
         return raw_response.json()

+ 21 - 26
app/services/tencent_nlp.py

@@ -6,7 +6,9 @@ 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.exception.tencent_cloud_sdk_exception import (
+    TencentCloudSDKException,
+)
 from tencentcloud.nlp.v20190408 import models, nlp_client
 
 from app.core.config import settings
@@ -14,14 +16,16 @@ from app.core.config import settings
 
 def get_tencent_nlp_client() -> nlp_client.NlpClient:
     try:
-        cred = credential.Credential(settings.TENCENT_SECRET_ID_V1, settings.TENCENT_SECRET_KEY_V1)
+        cred = credential.Credential(
+            settings.TENCENT_SECRET_ID_V1, settings.TENCENT_SECRET_KEY_V1
+        )
         http_profile = HttpProfile()
-        http_profile.reqMethod = 'GET'
+        http_profile.reqMethod = "GET"
         http_profile.endpoint = settings.TENCENT_NLP_ENDPOINT
 
         client_profile = ClientProfile()
         client_profile.httpProfile = http_profile
-        client = nlp_client.NlpClient(cred, 'ap-guangzhou', client_profile)
+        client = nlp_client.NlpClient(cred, "ap-guangzhou", client_profile)
 
         return client
     except TencentCloudSDKException as e:
@@ -29,23 +33,22 @@ def get_tencent_nlp_client() -> nlp_client.NlpClient:
 
 
 class TencentNLP:
-
     def __init__(self):
-        cred = credential.Credential(settings.TENCENT_SECRET_ID_V1, settings.TENCENT_SECRET_KEY_V1)
+        cred = credential.Credential(
+            settings.TENCENT_SECRET_ID_V1, settings.TENCENT_SECRET_KEY_V1
+        )
         http_profile = HttpProfile()
-        http_profile.reqMethod = 'GET'
+        http_profile.reqMethod = "GET"
         http_profile.endpoint = settings.TENCENT_NLP_ENDPOINT
 
         client_profile = ClientProfile()
         client_profile.httpProfile = http_profile
-        client = nlp_client.NlpClient(cred, 'ap-guangzhou', client_profile)
+        client = nlp_client.NlpClient(cred, "ap-guangzhou", client_profile)
         self.client = client
 
     async def get_lexical_analysis_result(self, text: str) -> Tuple[List, List]:
         req = models.LexicalAnalysisRequest()
-        params = {
-            'Text': text
-        }
+        params = {"Text": text}
         req.from_json_string(json.dumps(params))
         resp = self.client.LexicalAnalysis(req)
 
@@ -53,20 +56,17 @@ class TencentNLP:
 
     async def get_auto_summarization_result(self, text: str) -> str:
         req = models.AutoSummarizationRequest()
-        params = {
-            'Text': text
-        }
+        params = {"Text": text}
         req.from_json_string(json.dumps(params))
         resp = self.client.AutoSummarization(req)
 
         return resp.Summary
 
-    async def get_text_similarity_result(self, src_text: str, target_text: List[str]) -> List:
+    async def get_text_similarity_result(
+        self, src_text: str, target_text: List[str]
+    ) -> List:
         req = models.TextSimilarityRequest()
-        params = {
-            'SrcText': src_text,
-            'TargetText': target_text
-        }
+        params = {"SrcText": src_text, "TargetText": target_text}
         req.from_json_string(json.dumps(params))
         resp = self.client.TextSimilarity(req)
 
@@ -74,9 +74,7 @@ class TencentNLP:
 
     async def get_dependency(self, text: str) -> List:
         req = models.DependencyParsingRequest()
-        params = {
-            'Text': text
-        }
+        params = {"Text": text}
         req.from_json_string(json.dumps(params))
         resp = self.client.DependencyParsing(req)
 
@@ -85,10 +83,7 @@ class TencentNLP:
     async def get_word_similarity(self, src_word: str, target: str) -> float:
         try:
             req = models.WordSimilarityRequest()
-            params = {
-                'SrcWord': src_word,
-                'TargetWord': target
-            }
+            params = {"SrcWord": src_word, "TargetWord": target}
             req.from_json_string(json.dumps(params))
             resp = self.client.WordSimilarity(req)
         except TencentCloudSDKException:

+ 150 - 129
app/services/transfer.py

@@ -16,19 +16,18 @@ from app.utils.math import round_half_up
 
 
 class Season(str, Enum):
-    cooling = 'Cooling'
-    heating = 'Warm'
-    transition = 'Transition'
+    cooling = "Cooling"
+    heating = "Warm"
+    transition = "Transition"
 
 
 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,159 +36,182 @@ class SpaceInfoService(Service):
         self._now_time = get_time_str()
 
     def _common_parameters(self) -> Dict:
-        return {'projectId': self._project_id, 'spaceId': self._space_id}
+        return {"projectId": self._project_id, "spaceId": self._space_id}
 
     async def is_customized(self) -> bool:
-        url = self._base_url.join('duoduo-service/custom-service/custom/timetarget')
-        time_str = arrow.get(arrow.get(self._now_time, TIME_FMT).shift(minutes=15).timestamp()
-                             // 900 * 900).strftime('%Y%m%d%H%M%S')
+        url = self._base_url.join("duoduo-service/custom-service/custom/timetarget")
+        time_str = arrow.get(
+            arrow.get(self._now_time, TIME_FMT).shift(minutes=15).timestamp()
+            // 900
+            * 900
+        ).strftime("%Y%m%d%H%M%S")
         params = {
-            'projectId': self._project_id,
-            'objectId': self._space_id,
-            'timepoint': time_str,
+            "projectId": self._project_id,
+            "objectId": self._space_id,
+            "timepoint": time_str,
         }
         raw_info = await self._get(url, params)
 
         flag = False
-        if raw_info.get('data'):
+        if raw_info.get("data"):
             flag = True
 
         return flag
 
     async def is_temporary(self) -> bool:
-        url = self._base_url.join('duoduo-service/transfer/environment/temp/target')
+        url = self._base_url.join("duoduo-service/transfer/environment/temp/target")
         params = self._common_parameters()
-        params.update({'time': self._now_time})
+        params.update({"time": self._now_time})
         raw_info = await self._get(url, params)
         flag = False
-        if raw_info.get('flag') == 1:
+        if raw_info.get("flag") == 1:
             flag = True
 
         return flag
 
     async def get_feedback(self, wechat_time: str) -> Dict:
-        url = self._base_url.join('duoduo-service/transfer/environment/feedbackCount')
+        url = self._base_url.join("duoduo-service/transfer/environment/feedbackCount")
         params = self._common_parameters()
-        params.update({'time': wechat_time})
+        params.update({"time": wechat_time})
         raw_info = await self._get(url, params)
 
         meaning_dict = {
-            'Id1': 'a little cold',
-            'Id2': 'so cold',
-            'Id3': 'a little hot',
-            'Id4': 'so hot',
-            'Id5': 'noisy or blowy',
-            'Id6': 'so stuffy',
-            'Id7': 'more sunshine',
-            'Id8': 'less sunshine',
-            'Id9': 'send a repairman',
-            'Id10': 'switch off',
-            'Id11': 'nice',
-            'Id12': 'switch on',
+            "Id1": "a little cold",
+            "Id2": "so cold",
+            "Id3": "a little hot",
+            "Id4": "so hot",
+            "Id5": "noisy or blowy",
+            "Id6": "so stuffy",
+            "Id7": "more sunshine",
+            "Id8": "less sunshine",
+            "Id9": "send a repairman",
+            "Id10": "switch off",
+            "Id11": "nice",
+            "Id12": "switch on",
         }
 
-        feedback_dic = {meaning_dict.get(k): v for k, v in raw_info.items() if k != 'result'}
+        feedback_dic = {
+            meaning_dict.get(k): v for k, v in raw_info.items() if k != "result"
+        }
 
         return feedback_dic
 
     async def get_custom_target(self) -> Dict[str, pd.DataFrame]:
-        url = self._base_url.join('duoduo-service/transfer/environment/normalAndPreDayTarget')
+        url = self._base_url.join(
+            "duoduo-service/transfer/environment/normalAndPreDayTarget"
+        )
         params = self._common_parameters()
-        params.update({'date': arrow.get(self._now_time, TIME_FMT).date().strftime('%Y%m%d')})
+        params.update(
+            {"date": arrow.get(self._now_time, TIME_FMT).date().strftime("%Y%m%d")}
+        )
         raw_info = await self._get(url, params)
 
         try:
-            pre_target_df = pd.DataFrame(raw_info.get('preTargets'))
-            pre_target_df.set_index('time', inplace=True)
+            pre_target_df = pd.DataFrame(raw_info.get("preTargets"))
+            pre_target_df.set_index("time", inplace=True)
         except (KeyError, TypeError):
             pre_target_df = pd.DataFrame()
 
         try:
-            normal_target_df = pd.DataFrame(raw_info.get('normalTargets'))
-            normal_target_df.set_index('time', inplace=True)
+            normal_target_df = pd.DataFrame(raw_info.get("normalTargets"))
+            normal_target_df.set_index("time", inplace=True)
         except (KeyError, TypeError):
             normal_target_df = pd.DataFrame()
 
-        return {
-            'pre_targets': pre_target_df,
-            'normal_targets': normal_target_df
-        }
+        return {"pre_targets": pre_target_df, "normal_targets": normal_target_df}
 
     async def get_current_temperature_target(self) -> float:
         targets = await self.get_custom_target()
-        if len(targets.get('pre_targets')) > 0:
-            current_targets = targets.get('pre_targets').append(targets.get('normal_targets'))
+        if len(targets.get("pre_targets")) > 0:
+            current_targets = targets.get("pre_targets").append(
+                targets.get("normal_targets")
+            )
         else:
-            current_targets = targets.get('normal_targets')
-        temp = 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')
+            current_targets = targets.get("normal_targets")
+        temp = (
+            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:
-            current_lower_target = current_targets['temperatureMin'].loc[next_quarter_minutes]
-            current_upper_target = current_targets['temperatureMax'].loc[next_quarter_minutes]
+            current_lower_target = current_targets["temperatureMin"].loc[
+                next_quarter_minutes
+            ]
+            current_upper_target = current_targets["temperatureMax"].loc[
+                next_quarter_minutes
+            ]
         except KeyError:
             current_lower_target, current_upper_target = np.NAN, np.NAN
 
         return round_half_up((current_lower_target + current_upper_target) / 2, 2)
 
     async def env_database_set(self, form: str, value: float) -> None:
-        url = self._base_url.join('duoduo-service/transfer/environment/hispoint/set')
+        url = self._base_url.join("duoduo-service/transfer/environment/hispoint/set")
         params = self._common_parameters()
-        time_str = arrow.get(arrow.get(self._now_time, TIME_FMT).timestamp() // 900 * 900).strftime('%Y%m%d%H%M%S')
-        params.update({'time': time_str, 'type': form, 'value': value})
+        time_str = arrow.get(
+            arrow.get(self._now_time, TIME_FMT).timestamp() // 900 * 900
+        ).strftime("%Y%m%d%H%M%S")
+        params.update({"time": time_str, "type": form, "value": value})
         await self._get(url, params)
 
     async def env_database_get(self) -> Dict[str, pd.DataFrame]:
-        url = self._base_url.join('duoduo-service/transfer/environment/hispoint/get')
+        url = self._base_url.join("duoduo-service/transfer/environment/hispoint/get")
         params = self._common_parameters()
-        params.update({'date': arrow.get(self._now_time, TIME_FMT).date().strftime('%Y%m%d')})
+        params.update(
+            {"date": arrow.get(self._now_time, TIME_FMT).date().strftime("%Y%m%d")}
+        )
         raw_info = await self._get(url, params)
 
         result = {}
-        if raw_info.get('result') == 'success':
+        if raw_info.get("result") == "success":
             for k, v in raw_info.items():
-                if k != 'result':
+                if k != "result":
                     if len(v) > 0:
                         temp = {}
                         data = np.array(v)
-                        temp.update({'timestamp': data[:, 0]})
-                        temp.update({'value': data[:, 1].astype(np.float)})
+                        temp.update({"timestamp": data[:, 0]})
+                        temp.update({"value": data[:, 1].astype(np.float)})
                         result.update({k: pd.DataFrame(temp)})
                     else:
                         result.update({k: pd.DataFrame()})
 
         return result
 
-    async def set_custom_target(self, form: str, target_value: Dict[str, List[float]], flag: str = '1') -> None:
-        url = self._base_url.join('duoduo-service/transfer/environment/target/setting')
+    async def set_custom_target(
+        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 = {
-            'projectId': self._project_id,
-            'spaceId': self._space_id,
-            'timepoint': self._now_time,
-            'type': form,
-            'flag': flag
+            "projectId": self._project_id,
+            "spaceId": self._space_id,
+            "timepoint": self._now_time,
+            "type": form,
+            "flag": flag,
         }
         await self._post(url, params=params, payload=target_value)
 
     async def set_temporary_custom(self) -> None:
-        url = self._base_url.join('duoduo-service/transfer/environment/setServiceFlag')
+        url = self._base_url.join("duoduo-service/transfer/environment/setServiceFlag")
         params = self._common_parameters()
-        params.update({'time': self._now_time})
+        params.update({"time": self._now_time})
         await self._get(url, params)
 
     async def get_equipment(self) -> List[dict]:
-        url = self._base_url.join('duoduo-service/object-service/object/equipment/findForServe')
+        url = self._base_url.join(
+            "duoduo-service/object-service/object/equipment/findForServe"
+        )
         params = self._common_parameters()
         raw_info = await self._post(url, params)
 
         result = []
-        for eq in raw_info.get('data'):
-            result.append({'id': eq.get('id'), 'category': eq.get('equipmentCategory')})
+        for eq in raw_info.get("data"):
+            result.append({"id": eq.get("id"), "category": eq.get("equipmentCategory")})
 
         return result
 
 
 class Duoduo(Service):
-
     def __init__(self, client: AsyncClient, project_id: str, server_settings=settings):
         super(Duoduo, self).__init__(client)
         self._project_id = project_id
@@ -197,101 +219,98 @@ class Duoduo(Service):
         self._now_time = get_time_str()
 
     async def get_season(self) -> Season:
-        url = self._base_url.join('duoduo-service/transfer/environment/getSeasonType')
+        url = self._base_url.join("duoduo-service/transfer/environment/getSeasonType")
         params = {
-            'projectId': self._project_id,
-            'date': self._now_time,
+            "projectId": self._project_id,
+            "date": self._now_time,
         }
         raw_info = await self._get(url, params)
 
-        return Season(raw_info.get('data'))
+        return Season(raw_info.get("data"))
 
     async def get_fill_count(self) -> Dict:
-        url = self._base_url.join('duoduo-service/review-service/space/report/quarter/query')
+        url = self._base_url.join(
+            "duoduo-service/review-service/space/report/quarter/query"
+        )
         payload = {
-            'criteria': {
-                'projectId': self._project_id,
-                'date': arrow.get(self._now_time, TIME_FMT).date().strftime('%Y%m%d')
+            "criteria": {
+                "projectId": self._project_id,
+                "date": arrow.get(self._now_time, TIME_FMT).date().strftime("%Y%m%d"),
             },
-            'orders': [
-                {
-                    'column': 'time',
-                    'asc': False
-                }
-            ],
-            'page': 1,
-            'size': 1
+            "orders": [{"column": "time", "asc": False}],
+            "page": 1,
+            "size": 1,
         }
 
         raw_info = await self._post(url, payload=payload)
 
         try:
-            result = raw_info.get('content')[-1]
+            result = raw_info.get("content")[-1]
         except (IndexError, TypeError):
             result = {}
 
         return result
 
     async def get_space_by_equipment(self, equipment_id: str) -> List[dict]:
-        url = self._base_url.join('duoduo-service/object-service/object/space/findForServe')
-        params = {
-            'projectId': self._project_id,
-            'objectId': equipment_id
-        }
+        url = self._base_url.join(
+            "duoduo-service/object-service/object/space/findForServe"
+        )
+        params = {"projectId": self._project_id, "objectId": equipment_id}
         raw_info = await self._post(url, params)
 
         result = []
-        for sp in raw_info.get('data'):
-            if sp.get('isControlled'):
-                result.append({'id': sp.get('id')})
+        for sp in raw_info.get("data"):
+            if sp.get("isControlled"):
+                result.append({"id": sp.get("id")})
 
         return result
 
     async def get_system_by_equipment(self, equipment_id: str) -> List:
-        url = self._base_url.join('duoduo-service/object-service/object/system/findForCompose')
-        params = {
-            'projectId': self._project_id,
-            'equipmentId': equipment_id
-        }
+        url = self._base_url.join(
+            "duoduo-service/object-service/object/system/findForCompose"
+        )
+        params = {"projectId": self._project_id, "equipmentId": equipment_id}
         raw_info = await self._post(url, params)
 
         system_list = []
-        for sy in raw_info.get('data'):
-            system_list.append({'id': sy.get('id')})
+        for sy in raw_info.get("data"):
+            system_list.append({"id": sy.get("id")})
 
         return system_list
 
     async def get_day_type(self) -> Dict:
-        url = self._base_url.join('duoduo-service/custom-service/custom/getDateInfo')
+        url = self._base_url.join("duoduo-service/custom-service/custom/getDateInfo")
         params = {
-            'projectId': self._project_id,
-            'date': arrow.get(self._now_time, TIME_FMT).date().strftime('%Y%m%d')
+            "projectId": self._project_id,
+            "date": arrow.get(self._now_time, TIME_FMT).date().strftime("%Y%m%d"),
         }
         raw_info = await self._get(url, params)
 
         result = {
-            'day_type': raw_info.get('dayType'),
-            'season': raw_info.get('seasonType')
+            "day_type": raw_info.get("dayType"),
+            "season": raw_info.get("seasonType"),
         }
 
         return result
 
     async def query_device_virtual_data(self, device_id: str, info_code: str) -> float:
-        url = self._base_url.join('duoduo-service/review-service/equipment/order/query')
+        url = self._base_url.join("duoduo-service/review-service/equipment/order/query")
         payload = {
-            'criteria': {
-                'projectId': self._project_id,
-                'objectId': device_id,
-                'date': arrow.get(self._now_time, TIME_FMT).date().strftime('%Y%m%d'),
-                'funcId': info_code
+            "criteria": {
+                "projectId": self._project_id,
+                "objectId": device_id,
+                "date": arrow.get(self._now_time, TIME_FMT).date().strftime("%Y%m%d"),
+                "funcId": info_code,
             }
         }
         raw_info = await self._post(url, payload=payload)
 
         try:
-            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):
+            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
+            ):
                 value = np.NAN
             else:
                 value = latest_data
@@ -301,22 +320,24 @@ class Duoduo(Service):
         return value
 
     async def query_fill_rate_by_device(self, device_id: str) -> [float, float]:
-        url = self._base_url.join('duoduo-service/review-service/space/quarter/getQueryByCategory')
+        url = self._base_url.join(
+            "duoduo-service/review-service/space/quarter/getQueryByCategory"
+        )
         payload = {
-            'criteria': {
-                'projectId': self._project_id,
-                'date': arrow.get(self._now_time, TIME_FMT).date().strftime('%Y%m%d'),
-                'eqId': device_id
+            "criteria": {
+                "projectId": self._project_id,
+                "date": arrow.get(self._now_time, TIME_FMT).date().strftime("%Y%m%d"),
+                "eqId": device_id,
             }
         }
 
         raw_info = await self._post(url, payload=payload)
 
         try:
-            value_info = raw_info['content'][-1]
-            hot_count = value_info['hotSpaceNum']
-            cold_count = value_info['coldSpaceNum']
-            total = value_info['spaceNum']
+            value_info = raw_info["content"][-1]
+            hot_count = value_info["hotSpaceNum"]
+            cold_count = value_info["coldSpaceNum"]
+            total = value_info["spaceNum"]
 
             hot_rate = hot_count / total
             cold_rate = cold_count / total

+ 15 - 10
app/services/weather.py

@@ -11,27 +11,32 @@ from app.utils.date import get_time_str
 
 
 class WeatherService(Service):
-
     def __init__(self, client: AsyncClient, server_settings=settings):
         super(WeatherService, self).__init__(client)
         self._base_url = URL(server_settings.WEATHER_HOST)
-        self._now_time = get_time_str(fmt='YYYY-MM-DD HH:mm:ss')
+        self._now_time = get_time_str(fmt="YYYY-MM-DD HH:mm:ss")
 
     async def get_realtime_weather(self, project_id: str) -> Dict:
-        url = self._base_url.join('EMS_Weather/Spring/MVC/entrance/unifier/HourHistoryData')
+        url = self._base_url.join(
+            "EMS_Weather/Spring/MVC/entrance/unifier/HourHistoryData"
+        )
         headers = {
-            'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
-            'Connection': 'close'
+            "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8",
+            "Connection": "close",
         }
         params = {
-            'projectId': project_id,
-            'startTime': get_time_str(60 * 60 * 2, flag='ago', fmt='YYYY-MM-DD HH:mm:ss'),
-            'endTime': self._now_time,
+            "projectId": project_id,
+            "startTime": get_time_str(
+                60 * 60 * 2, flag="ago", fmt="YYYY-MM-DD HH:mm:ss"
+            ),
+            "endTime": self._now_time,
         }
 
-        raw_info = await self._post(url, params={'jsonString': json.dumps(params)}, headers=headers)
+        raw_info = await self._post(
+            url, params={"jsonString": json.dumps(params)}, headers=headers
+        )
         try:
-            result = raw_info.get('content')[-1]
+            result = raw_info.get("content")[-1]
         except (KeyError, TypeError, IndexError):
             result = {}
 

+ 8 - 6
app/utils/date.py

@@ -4,10 +4,12 @@ from typing import Optional
 
 import arrow
 
-TIME_FMT = 'YYYYMMDDHHmmss'
+TIME_FMT = "YYYYMMDDHHmmss"
 
 
-def get_time_str(delta: int = 0, flag: str = 'now', fmt: Optional[str] = TIME_FMT) -> str:
+def get_time_str(
+    delta: int = 0, flag: str = "now", fmt: Optional[str] = TIME_FMT
+) -> str:
     """
     Return a Beijing time strings.
     :param delta: time delta(seconds)
@@ -16,11 +18,11 @@ def get_time_str(delta: int = 0, flag: str = 'now', fmt: Optional[str] = TIME_FM
     :return: a '%Y%m%d%H%M%S' format strings
     """
     utc = arrow.utcnow()
-    local = utc.to('Asia/Shanghai')
-    if flag == 'ago':
+    local = utc.to("Asia/Shanghai")
+    if flag == "ago":
         delta = -delta
         t = local.shift(seconds=delta)
-    elif flag == 'later':
+    elif flag == "later":
         t = local.shift(seconds=delta)
     else:
         t = local
@@ -32,4 +34,4 @@ def get_time_str(delta: int = 0, flag: str = 'now', fmt: Optional[str] = TIME_FM
 
 def get_quarter_minutes(time_str: str) -> str:
     temp = arrow.get(time_str, TIME_FMT).timestamp() // (15 * 60) * (15 * 60)
-    return arrow.get(temp).time().strftime('%H%M%S')
+    return arrow.get(temp).time().strftime("%H%M%S")

+ 8 - 8
tests/test.py

@@ -8,7 +8,7 @@ import requests
 
 
 async def request(client):
-    await client.get('http://172.16.47.29:8000/users')
+    await client.get("http://172.16.47.29:8000/users")
 
 
 async def main():
@@ -22,28 +22,28 @@ async def main():
             task_list.append(task)
         await asyncio.gather(*task_list)
         end = time.process_time()
-    print(f'Sent {epochs} requests in method 1,elapsed:{end - start}')
+    print(f"Sent {epochs} requests in method 1,elapsed:{end - start}")
 
     start = time.process_time()
     for _ in range(epochs):
         async with httpx.AsyncClient() as client:
             await request(client)
     end = time.process_time()
-    print(f'Sent {epochs} requests in method 2,elapsed:{end - start}')
+    print(f"Sent {epochs} requests in method 2,elapsed:{end - start}")
 
     start = time.process_time()
     for _ in range(epochs):
         with httpx.Client() as client:
-            client.get('http://172.16.47.29:8000/users')
+            client.get("http://172.16.47.29:8000/users")
     end = time.process_time()
-    print(f'Sent {epochs} requests in method 3, elapsed: {end - start}')
+    print(f"Sent {epochs} requests in method 3, elapsed: {end - start}")
 
     start = time.process_time()
     for _ in range(epochs):
-        requests.get('http://172.16.47.29:8000/users')
+        requests.get("http://172.16.47.29:8000/users")
     end = time.process_time()
-    print(f'Sent {epochs} requests by requests, elapsed: {end - start}')
+    print(f"Sent {epochs} requests by requests, elapsed: {end - start}")
 
 
-if __name__ == '__main__':
+if __name__ == "__main__":
     asyncio.run(main())