Parcourir la source

add a api named equip/control/atva/v2

chenhaiyang il y a 4 ans
Parent
commit
d62e9b4884
2 fichiers modifiés avec 112 ajouts et 56 suppressions
  1. 30 8
      app/api/routers/equipment.py
  2. 82 48
      app/controllers/equipment/vav.py

+ 30 - 8
app/api/routers/equipment.py

@@ -2,6 +2,7 @@
 
 
 from enum import Enum
 from enum import Enum
 
 
+import numpy as np
 from fastapi import APIRouter, Depends, Query
 from fastapi import APIRouter, Depends, Query
 from loguru import logger
 from loguru import logger
 from sqlalchemy.orm import Session
 from sqlalchemy.orm import Session
@@ -9,7 +10,7 @@ from sqlalchemy.orm import Session
 from app.api.dependencies.db import get_db
 from app.api.dependencies.db import get_db
 from app.controllers.equipment.fcu.basic import get_fcu_control_result
 from app.controllers.equipment.fcu.basic import get_fcu_control_result
 from app.controllers.equipment.fcu.q_learning import get_fcu_q_learning_control_result
 from app.controllers.equipment.fcu.q_learning import get_fcu_q_learning_control_result
-from app.controllers.equipment.vav import get_vav_control_result
+from app.controllers.equipment.vav import get_vav_control_v1, get_vav_control_v2
 from app.models.domain.equipment import EquipmentControlResponse, EquipmentControlRequest
 from app.models.domain.equipment import EquipmentControlResponse, EquipmentControlRequest
 from app.utils.date import get_time_str
 from app.utils.date import get_time_str
 
 
@@ -26,8 +27,7 @@ router = APIRouter()
 async def get_equipment_command_test(
 async def get_equipment_command_test(
         project_id: str = Query(..., max_length=50, regex='^Pj', alias='projectId'),
         project_id: str = Query(..., max_length=50, regex='^Pj', alias='projectId'),
         equip_id: str = Query(..., max_length=50, regex='^Eq', alias='equipId'),
         equip_id: str = Query(..., max_length=50, regex='^Eq', alias='equipId'),
-        equip_type: EquipmentName = Query(..., alias='equipType'),
-        db: Session = Depends(get_db)
+        equip_type: EquipmentName = Query(..., alias='equipType')
 ):
 ):
     if equip_type.value == EquipmentName.FCU:
     if equip_type.value == EquipmentName.FCU:
         if project_id in ['Pj1101050030', 'Pj1101080259']:
         if project_id in ['Pj1101050030', 'Pj1101080259']:
@@ -35,7 +35,7 @@ async def get_equipment_command_test(
         else:
         else:
             output = await get_fcu_q_learning_control_result(project_id, equip_id)
             output = await get_fcu_q_learning_control_result(project_id, equip_id)
     elif equip_type.value == EquipmentName.VAV:
     elif equip_type.value == EquipmentName.VAV:
-        vav = await get_vav_control_result(db, project_id, equip_id)
+        vav = await get_vav_control_v1(project_id, equip_id)
         output = {
         output = {
             'SupplyAirFlowSet': vav.supply_air_flow_set,
             'SupplyAirFlowSet': vav.supply_air_flow_set,
             'VirtualRealtimeTemperature': vav.virtual_realtime_temperature,
             'VirtualRealtimeTemperature': vav.virtual_realtime_temperature,
@@ -54,7 +54,7 @@ async def get_equipment_command_test(
 
 
 
 
 @router.post('/control', response_model=EquipmentControlResponse)
 @router.post('/control', response_model=EquipmentControlResponse)
-async def get_equipment_command(equipment_control_info: EquipmentControlRequest, db: Session = Depends(get_db)):
+async def get_equipment_command(equipment_control_info: EquipmentControlRequest):
     if equipment_control_info.equipType == EquipmentName.FCU:
     if equipment_control_info.equipType == EquipmentName.FCU:
         if equipment_control_info.projectId in ['Pj1101050030', 'Pj1101080259']:
         if equipment_control_info.projectId in ['Pj1101050030', 'Pj1101080259']:
             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)
@@ -64,11 +64,13 @@ async def get_equipment_command(equipment_control_info: EquipmentControlRequest,
                 equipment_control_info.equipId
                 equipment_control_info.equipId
             )
             )
     elif equipment_control_info.equipType == EquipmentName.VAV:
     elif equipment_control_info.equipType == EquipmentName.VAV:
-        vav = await get_vav_control_result(db, equipment_control_info.projectId, equipment_control_info.equipId)
+        vav = await get_vav_control_v1(equipment_control_info.projectId, equipment_control_info.equipId)
         output = {
         output = {
             'SupplyAirFlowSet': vav.supply_air_flow_set,
             'SupplyAirFlowSet': vav.supply_air_flow_set,
-            'VirtualRealtimeTemperature': vav.virtual_realtime_temperature,
-            'TargetTemperatureSet': vav.virtual_target_temperature
+            '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:
     else:
         output = {}
         output = {}
@@ -81,3 +83,23 @@ async def get_equipment_command(equipment_control_info: EquipmentControlRequest,
     }
     }
     logger.info(response)
     logger.info(response)
     return 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)
+    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
+    }
+
+    response = {
+        'projectId': equipment_control_info.projectId,
+        'equipId': equipment_control_info.equipId,
+        'time': get_time_str(),
+        'output': output
+    }
+    logger.info(response)
+    return response

+ 82 - 48
app/controllers/equipment/vav.py

@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 # -*- coding: utf-8 -*-
 
 
-from typing import List, Tuple
+from typing import Dict, List, Tuple
 
 
 import numpy as np
 import numpy as np
 from fastapi import HTTPException
 from fastapi import HTTPException
@@ -20,15 +20,13 @@ from app.utils.date import get_time_str
 
 
 class VAVController(EquipmentController):
 class VAVController(EquipmentController):
 
 
-    def __init__(self, equipment: VAVBox, weights: List[SpaceWeight], season: Season):
+    def __init__(self, equipment: VAVBox):
         super(VAVController, self).__init__()
         super(VAVController, self).__init__()
-        self._equipment = equipment
-        self.weights = weights
-        self.season = season
+        self.equipment = equipment
 
 
     async def get_strategy(self):
     async def get_strategy(self):
         strategy = 'Plan A'
         strategy = 'Plan A'
-        for space in self._equipment.spaces:
+        for space in self.equipment.spaces:
             for eq in space.equipment:
             for eq in space.equipment:
                 if isinstance(eq, FCU):
                 if isinstance(eq, FCU):
                     strategy = 'Plan B'
                     strategy = 'Plan B'
@@ -36,11 +34,11 @@ class VAVController(EquipmentController):
 
 
         return strategy
         return strategy
 
 
-    async def build_virtual_temperature_v1(self) -> Tuple[float, float]:
+    async def build_virtual_temperature(self) -> Tuple[float, float]:
         target_list, realtime_list = [], []
         target_list, realtime_list = [], []
         buffer_list = []
         buffer_list = []
         strategy = await self.get_strategy()
         strategy = await self.get_strategy()
-        for space in self._equipment.spaces:
+        for space in self.equipment.spaces:
             if not np.isnan(space.temperature_target):
             if not np.isnan(space.temperature_target):
                 target_list.append(space.temperature_target)
                 target_list.append(space.temperature_target)
                 realtime_list.append(space.realtime_temperature)
                 realtime_list.append(space.realtime_temperature)
@@ -58,16 +56,50 @@ class VAVController(EquipmentController):
         if total_target and total_realtime:
         if total_target and total_realtime:
             target_result = np.array(total_target).sum() / len(target_list)
             target_result = np.array(total_target).sum() / len(target_list)
             realtime_result = np.array(total_realtime).sum() / len(realtime_list)
             realtime_result = np.array(total_realtime).sum() / len(realtime_list)
-            self._equipment.setting_temperature = target_result
+            self.equipment.setting_temperature = target_result
         else:
         else:
             target_result, realtime_result = np.NAN, np.NAN
             target_result, realtime_result = np.NAN, np.NAN
 
 
         return target_result, realtime_result
         return target_result, realtime_result
 
 
-    async def build_virtual_temperature_v2(self):
+    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:
+            temperature_supply = self.equipment.supply_air_temperature
+            if np.isnan(temperature_supply):
+                temperature_supply = 19.0
+            supply_air_flow_set = self.equipment.supply_air_flow * ((temperature_supply - temperature_realtime)
+                                                                    / (temperature_supply - temperature_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
+
+        return supply_air_flow_set
+
+    async def run(self):
+        temperature_set, temperature_realtime = await self.build_virtual_temperature()
+        await self.get_supply_air_flow_set(temperature_set, temperature_realtime)
+        self.equipment.running_status = True
+
+    def get_results(self):
+        return self.equipment
+
+
+class VAVControllerV2(VAVController):
+
+    def __init__(self, equipment: VAVBox, weights: List[SpaceWeight], season: Season):
+        super(VAVControllerV2, self).__init__(equipment)
+        # self.equipment = equipment
+        self.weights = weights
+        self.season = season
+
+    async def build_virtual_temperature(self):
         valid_spaces = []
         valid_spaces = []
         weights = []
         weights = []
-        for sp in self._equipment.spaces:
+        for sp in self.equipment.spaces:
             if sp.realtime_temperature > 0.0 and sp.temperature_target > 0.0:
             if sp.realtime_temperature > 0.0 and sp.temperature_target > 0.0:
                 valid_spaces.append(sp)
                 valid_spaces.append(sp)
                 for weight in self.weights:
                 for weight in self.weights:
@@ -95,58 +127,41 @@ class VAVController(EquipmentController):
                     virtual_target += sp.temperature_target * weight_dic.get(sp.id)
                     virtual_target += sp.temperature_target * weight_dic.get(sp.id)
                     virtual_realtime += sp.realtime_temperature * weight_dic.get(sp.id)
                     virtual_realtime += sp.realtime_temperature * weight_dic.get(sp.id)
             except KeyError:
             except KeyError:
-                logger.error(f'{self._equipment.id} has wrong vav-space 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')
                 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
+            self.equipment.virtual_target_temperature = virtual_target
+            self.equipment.virtual_realtime_temperature = virtual_realtime
         else:
         else:
-            self._equipment.virtual_target_temperature = np.NAN
-            self._equipment.virtual_realtime_temperature = np.NAN
+            self.equipment.virtual_target_temperature = np.NAN
+            self.equipment.virtual_realtime_temperature = np.NAN
 
 
     async def rectify(self) -> Tuple[float, float]:
     async def rectify(self) -> Tuple[float, float]:
-        for sp in self._equipment.spaces:
+        for sp in self.equipment.spaces:
             if sp.realtime_temperature < min(23.0, sp.temperature_target):
             if sp.realtime_temperature < min(23.0, sp.temperature_target):
                 if self.season == Season.heating:
                 if self.season == Season.heating:
-                    self._equipment.virtual_target_temperature = min(23.0, sp.temperature_target) + 0.5
-                    self._equipment.virtual_realtime_temperature = sp.realtime_temperature
+                    self.equipment.virtual_target_temperature = min(23.0, sp.temperature_target) + 0.5
+                    self.equipment.virtual_realtime_temperature = sp.realtime_temperature
                     break
                     break
             elif sp.realtime_temperature > max(27.0, sp.temperature_target):
             elif sp.realtime_temperature > max(27.0, sp.temperature_target):
                 if self.season == Season.cooling:
                 if self.season == Season.cooling:
-                    self._equipment.virtual_target_temperature = max(27.0, sp.temperature_target)
-                    self._equipment.virtual_realtime_temperature = sp.realtime_temperature
+                    self.equipment.virtual_target_temperature = max(27.0, sp.temperature_target)
+                    self.equipment.virtual_realtime_temperature = sp.realtime_temperature
                     break
                     break
 
 
-        return self._equipment.virtual_target_temperature, self._equipment.virtual_realtime_temperature
-
-    async def get_supply_air_flow_set(self) -> float:
-        # await self.build_virtual_temperature_v2()
-        # temperature_set, temperature_realtime = await self.rectify()
-        temperature_set, temperature_realtime = await self.build_virtual_temperature_v1()
-        if np.isnan(temperature_set) or np.isnan(temperature_realtime):
-            supply_air_flow_set = 0.0
-        else:
-            temperature_supply = self._equipment.supply_air_temperature
-            if np.isnan(temperature_supply):
-                temperature_supply = 19.0
-            supply_air_flow_set = self._equipment.supply_air_flow * ((temperature_supply - temperature_realtime)
-                                                                     / (temperature_supply - temperature_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
-
-        return supply_air_flow_set
+        return self.equipment.virtual_target_temperature, self.equipment.virtual_realtime_temperature
 
 
     async def run(self):
     async def run(self):
-        await self.get_supply_air_flow_set()
-        self._equipment.running_status = True
+        await self.build_virtual_temperature()
+        temperature_set, temperature_realtime = await self.rectify()
+        await self.get_supply_air_flow_set(temperature_set, temperature_realtime)
+        self.equipment.running_status = True
 
 
     def get_results(self):
     def get_results(self):
-        return self._equipment
+        return self.equipment
 
 
 
 
-@logger.catch()
-async def get_vav_control_result(db: Session, project_id: str, equipment_id: str) -> VAVBox:
+async def fetch_vav_control_params(project_id: str, equipment_id: str) -> Dict:
     async with AsyncClient() as client:
     async with AsyncClient() as client:
         duo_duo = Duoduo(client, project_id)
         duo_duo = Duoduo(client, project_id)
         platform = DataPlatformService(client, project_id)
         platform = DataPlatformService(client, project_id)
@@ -188,19 +203,38 @@ async def get_vav_control_result(db: Session, project_id: str, equipment_id: str
             space = Space(**temp_space_params)
             space = Space(**temp_space_params)
             space_objects.append(space)
             space_objects.append(space)
 
 
-        temp_vav_params = {
+        vav_params = {
             'id': equipment_id,
             'id': equipment_id,
             'spaces': space_objects,
             'spaces': space_objects,
             'supply_air_temperature': realtime_supply_air_temperature,
             'supply_air_temperature': realtime_supply_air_temperature,
             'supply_air_flow': realtime_supply_air_flow,
             'supply_air_flow': realtime_supply_air_flow,
             'supply_air_flow_lower_limit': lower_limit,
             'supply_air_flow_lower_limit': lower_limit,
             'supply_air_flow_upper_limit': upper_limit,
             'supply_air_flow_upper_limit': upper_limit,
+            'season': season
         }
         }
-        vav = VAVBox(**temp_vav_params)
 
 
+        return vav_params
+
+
+@logger.catch()
+async def get_vav_control_v1(project: str, equipment_id: str) -> VAVBox:
+    vav_params = await fetch_vav_control_params(project, equipment_id)
+    vav = VAVBox(**vav_params)
+
+    vav_controller = VAVController(vav)
+    await vav_controller.run()
+    regulated_vav = vav_controller.get_results()
+
+    return regulated_vav
+
+
+@logger.catch()
+async def get_vav_control_v2(db: Session, project_id: str, equipment_id: str) -> VAVBox:
+    vav_params = await fetch_vav_control_params(project_id, equipment_id)
+    vav = VAVBox(**vav_params)
     weights = get_weights_by_vav(db, equipment_id)
     weights = get_weights_by_vav(db, equipment_id)
 
 
-    vav_controller = VAVController(vav, [SpaceWeight.from_orm(weight) for weight in weights], season)
+    vav_controller = VAVControllerV2(vav, [SpaceWeight.from_orm(weight) for weight in weights], vav_params['season'])
     await vav_controller.run()
     await vav_controller.run()
     regulated_vav = vav_controller.get_results()
     regulated_vav = vav_controller.get_results()