|
@@ -1,23 +1,30 @@
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
|
-from typing import Tuple
|
|
|
+from typing import List, Tuple
|
|
|
|
|
|
import numpy as np
|
|
|
from httpx import AsyncClient
|
|
|
+from fastapi import HTTPException
|
|
|
from loguru import logger
|
|
|
+from sqlalchemy.orm import Session
|
|
|
|
|
|
from app.controllers.equipment.controller import EquipmentController
|
|
|
+from app.crud.space.weight import get_weights_by_vav
|
|
|
from app.schemas.equipment import VAVBox, FCU
|
|
|
from app.schemas.space import Space
|
|
|
+from app.schemas.sapce_weight import SpaceWeight
|
|
|
from app.services.platform import DataPlatformService
|
|
|
-from app.services.transfer import Duoduo, SpaceInfoService
|
|
|
+from app.services.transfer import Duoduo, SpaceInfoService, Season
|
|
|
+from app.utils.date import get_time_str
|
|
|
|
|
|
|
|
|
class VAVController(EquipmentController):
|
|
|
|
|
|
- def __init__(self, equipment: VAVBox):
|
|
|
+ def __init__(self, equipment: VAVBox, weights: List[SpaceWeight], season: Season):
|
|
|
super(VAVController, self).__init__()
|
|
|
self._equipment = equipment
|
|
|
+ self.weights = weights
|
|
|
+ self.season = season
|
|
|
|
|
|
async def get_strategy(self):
|
|
|
strategy = 'Plan A'
|
|
@@ -29,7 +36,7 @@ class VAVController(EquipmentController):
|
|
|
|
|
|
return strategy
|
|
|
|
|
|
- async def get_temperature(self) -> Tuple[float, float]:
|
|
|
+ async def build_virtual_temperature_v1(self) -> Tuple[float, float]:
|
|
|
target_list, realtime_list = [], []
|
|
|
buffer_list = []
|
|
|
strategy = await self.get_strategy()
|
|
@@ -57,8 +64,44 @@ class VAVController(EquipmentController):
|
|
|
|
|
|
return target_result, realtime_result
|
|
|
|
|
|
+ async def build_virtual_temperature_v2(self):
|
|
|
+ weights = sorted(self.weights, key=lambda weight: weight.temporary_weight_update_time)
|
|
|
+ if weights[-1].temporary_weight_update_time > get_time_str(60 * 60 * 2, flag='ago'):
|
|
|
+ weight_dic = {weight.id: 0.0 for weight in weights}
|
|
|
+ weight_dic.update({weights[-1].id: weights[-1].temporary_weight})
|
|
|
+ else:
|
|
|
+ weight_dic = {weight.id: weight.default_weight for weight in weights}
|
|
|
+
|
|
|
+ try:
|
|
|
+ virtual_target, virtual_realtime = 0.0, 0.0
|
|
|
+ for sp in self._equipment.spaces:
|
|
|
+ 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')
|
|
|
+
|
|
|
+ self._equipment.virtual_target_temperature = virtual_target
|
|
|
+ self._equipment.virtual_realtime_temperature = virtual_realtime
|
|
|
+
|
|
|
+ async def rectify(self) -> Tuple[float, float]:
|
|
|
+ for sp in self._equipment.spaces:
|
|
|
+ if sp.realtime_temperature < min(23.0, sp.temperature_target):
|
|
|
+ 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
|
|
|
+ break
|
|
|
+ elif sp.realtime_temperature > max(27.0, sp.temperature_target):
|
|
|
+ if self.season == Season.cooling:
|
|
|
+ self._equipment.virtual_target_temperature = max(27.0, sp.temperature_target)
|
|
|
+ self._equipment.virtual_realtime_temperature = sp.realtime_temperature
|
|
|
+ break
|
|
|
+
|
|
|
+ return self._equipment.virtual_target_temperature, self._equipment.virtual_realtime_temperature
|
|
|
+
|
|
|
async def get_supply_air_flow_set(self) -> float:
|
|
|
- temperature_set, temperature_realtime = await self.get_temperature()
|
|
|
+ await self.build_virtual_temperature_v2()
|
|
|
+ temperature_set, temperature_realtime = await self.rectify()
|
|
|
if np.isnan(temperature_set) or np.isnan(temperature_realtime):
|
|
|
supply_air_flow_set = 0.0
|
|
|
else:
|
|
@@ -86,7 +129,7 @@ class VAVController(EquipmentController):
|
|
|
|
|
|
|
|
|
@logger.catch()
|
|
|
-async def get_vav_control_result(project_id: str, equipment_id: str) -> VAVBox:
|
|
|
+async def get_vav_control_result(db: Session, project_id: str, equipment_id: str) -> VAVBox:
|
|
|
async with AsyncClient() as client:
|
|
|
duo_duo = Duoduo(client, project_id)
|
|
|
platform = DataPlatformService(client, project_id)
|
|
@@ -102,6 +145,7 @@ async def get_vav_control_result(project_id: str, equipment_id: str) -> VAVBox:
|
|
|
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)
|
|
|
|
|
|
+ season = await duo_duo.get_season()
|
|
|
served_spaces = await duo_duo.get_space_by_equipment(equipment_id)
|
|
|
space_objects = []
|
|
|
for sp in served_spaces:
|
|
@@ -137,7 +181,9 @@ async def get_vav_control_result(project_id: str, equipment_id: str) -> VAVBox:
|
|
|
}
|
|
|
vav = VAVBox(**temp_vav_params)
|
|
|
|
|
|
- vav_controller = VAVController(vav)
|
|
|
+ weights = get_weights_by_vav(db, equipment_id)
|
|
|
+
|
|
|
+ vav_controller = VAVController(vav, [SpaceWeight.from_orm(weight) for weight in weights], season)
|
|
|
await vav_controller.run()
|
|
|
regulated_vav = vav_controller.get_results()
|
|
|
|