thermal_mode.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. from typing import Dict, List
  2. from httpx import AsyncClient
  3. from loguru import logger
  4. from app.models.domain.devices import ThermalMode
  5. from app.schemas.equipment import VAVBox
  6. from app.services.platform import DataPlatformService, InfoCode
  7. from app.services.transfer import Duoduo, Season
  8. def count_vav_box_weight(
  9. realtime: float,
  10. target: float,
  11. upper_limit_flow: float,
  12. lower_limit_flow: float,
  13. current_flow_set: float,
  14. season: Season
  15. ) -> float:
  16. diff = realtime - target
  17. flag = False
  18. if current_flow_set < lower_limit_flow * 1.1:
  19. if season == Season.cooling:
  20. if diff < 0:
  21. flag = True
  22. if season == Season.heating:
  23. if diff > 0:
  24. flag = True
  25. elif current_flow_set > upper_limit_flow * 0.9:
  26. if season == Season.cooling:
  27. if diff > 0:
  28. flag = True
  29. if season == Season.heating:
  30. if diff < 0:
  31. flag = True
  32. if flag:
  33. weight = round(diff, 0)
  34. weight = max(-4.0, min(4.0, weight))
  35. else:
  36. weight = 0
  37. return weight
  38. class ACATAHThermalModeController:
  39. """
  40. Decide whether to use cooling or heating mode according to space condition controlled by VAV Box.
  41. Writen by WuXu
  42. """
  43. def __init__(self, vav_boxes_list: List[VAVBox], season: Season):
  44. super(ACATAHThermalModeController, self).__init__()
  45. self.vav_boxes_list = vav_boxes_list
  46. self.season = season
  47. def build(self) -> str:
  48. weight = 0.0
  49. for box in self.vav_boxes_list:
  50. weight += count_vav_box_weight(
  51. box.virtual_realtime_temperature,
  52. box.virtual_target_temperature,
  53. box.supply_air_flow_upper_limit,
  54. box.supply_air_flow_lower_limit,
  55. box.supply_air_flow_set,
  56. self.season
  57. )
  58. if weight > 0:
  59. mode = 'cooling'
  60. elif weight < 0:
  61. mode = 'heating'
  62. else:
  63. mode = 'hold'
  64. return mode
  65. async def fetch_status_params(project_id: str, device_id: str) -> Dict:
  66. async with AsyncClient() as client:
  67. platform = DataPlatformService(client, project_id)
  68. duoduo = Duoduo(client, project_id)
  69. season = duoduo.get_season()
  70. relations = await platform.query_relations(from_id=device_id, graph_id='GtControlEquipNetwork001')
  71. vav_id_list = [item.get('to_id') for item in relations]
  72. vav_boxes_list = []
  73. for vav_id in vav_id_list:
  74. virtual_realtime_temperature = await duoduo.query_device_virtual_data(
  75. vav_id,
  76. 'VirtualRealtimeTemperature'
  77. )
  78. virtual_temperature_target = await duoduo.query_device_virtual_data(vav_id, 'TargetTemperatureSet')
  79. lower_limit_flow, upper_limit_flow = await platform.get_air_flow_limit(vav_id)
  80. current_flow_set = await platform.get_realtime_data(InfoCode.supply_air_flow_set, vav_id)
  81. vav_params = {
  82. 'id': vav_id,
  83. 'virtual_realtime_temperature': virtual_realtime_temperature,
  84. 'virtual_target_temperature': virtual_temperature_target,
  85. 'supply_air_flow_lower_limit': lower_limit_flow,
  86. 'supply_air_flow_upper_limit': upper_limit_flow,
  87. 'supply_air_flow_set': current_flow_set
  88. }
  89. vav = VAVBox(**vav_params)
  90. vav_boxes_list.append(vav)
  91. return {'vav_boxes_list': vav_boxes_list, 'season': season}
  92. @logger.catch()
  93. async def get_thermal_mode(project_id: str, device_id: str) -> ThermalMode:
  94. prams = await fetch_status_params(project_id, device_id)
  95. controller = ACATAHThermalModeController(prams.get('vav_boxes_list'), prams.get('season'))
  96. mode = controller.build()
  97. return ThermalMode(mode)