浏览代码

add pump logic

highing666 2 年之前
父节点
当前提交
46af7b63d1

+ 23 - 1
app/api/routers/devices.py

@@ -27,6 +27,8 @@ from app.controllers.equipment.pau.supply_air_temperature_set import (
     build_acatfu_supply_air_temperature,
 )
 from app.controllers.equipment.pau.switch import build_acatfu_switch_set, build_co2_acatfu_switch
+from app.controllers.equipment.pump.basic import build_feed_water_pump_instructions, \
+    build_feed_water_pump_br_instructions
 from app.controllers.equipment.vav import (
     build_acatva_instructions,
     build_acatva_instructions_for_jm,
@@ -338,6 +340,26 @@ async def get_ashp_instructions(params: domain_devices.ASHPRequest):
     instructions = await build_ashp_instructions(params)
 
     logger.info(params)
-    logger.debug(instructions)
+    logger.info(instructions)
+
+    return instructions
+
+
+@router.post("/instructions/feed-water-pump", response_model=domain_devices.FeedWaterPumpResponse)
+async def get_feed_water_pump_instructions(params: domain_devices.FeedWaterPumpRequest):
+    instructions = await build_feed_water_pump_instructions(params)
+
+    logger.info(params)
+    logger.info(instructions)
+
+    return instructions
+
+
+@router.post("/instructions/feed-water-pump-BR", response_model=domain_devices.FeedWaterPumpResponse)
+async def get_feed_water_pump_instructions(params: domain_devices.FeedWaterPumpRequest):
+    instructions = await build_feed_water_pump_br_instructions(params)
+
+    logger.info(params)
+    logger.info(instructions)
 
     return instructions

+ 0 - 0
app/controllers/equipment/pump/__init__.py


+ 170 - 0
app/controllers/equipment/pump/basic.py

@@ -0,0 +1,170 @@
+from operator import attrgetter
+
+import numpy as np
+
+from app.api.errors.iot import MissingIOTDataError
+from app.controllers.equipment.ashp.basic import ASHPGroupController
+from app.models.domain.devices import FeedWaterPumpRequest
+from app.schemas.equipment import FeedWaterPump, ASHP
+from app.schemas.season import Season
+
+
+class FeedWaterPumpController:
+    def __init__(self, pump_list: list[FeedWaterPump]):
+        self._pump_list = pump_list
+
+    def get_switch_set(self, ashp_list: list[ASHP]):
+        ashp_on_count = 0
+        ashp_off_count = 0
+        for item in ashp_list:
+            if item.equip_switch_set:
+                ashp_on_count += 1
+            if not item.running_status:
+                ashp_off_count += 1
+
+        ashp_num = len(ashp_list)
+        pump_num = len(self._pump_list)
+        if ashp_off_count == ashp_num:
+            self.turn_off_all()
+        else:
+            if pump_num == 2:
+                if ashp_on_count < ashp_num / 2:
+                    pump_need_num = 1
+                else:
+                    pump_need_num = 2
+            elif pump_num == 3:
+                if ashp_on_count <= ashp_num // 3:
+                    pump_need_num = 1
+                elif ashp_on_count > 2 * ashp_num // 3:
+                    pump_need_num = 3
+                else:
+                    pump_need_num = 2
+            else:
+                pump_need_num = 1
+
+            self._pump_list = sorted(self._pump_list, key=attrgetter("acc_run_time"))
+            for device in self._pump_list:
+                if not device.running_status:
+                    device.equip_switch_set = True
+                    pump_need_num -= 1
+                    if pump_need_num == 0:
+                        break
+
+    def turn_off_all(self):
+        for device in self._pump_list:
+            device.equip_switch_set = False
+
+    def is_init(self):
+        on_flag = False
+        for device in self._pump_list:
+            if device.running_status:
+                on_flag = True
+
+        init_flag = False
+        if not on_flag:
+            for device in self._pump_list:
+                if device.equip_switch_set:
+                    init_flag = True
+
+        return init_flag
+
+    def get_freq_set(self, ashp_list: list[ASHP], season: Season, init: float = 30.0):
+        if self.is_init():
+            self.set_freq(0, init)
+        else:
+            in_temp_avg = np.mean([device.in_temp for device in ashp_list])
+            out_temp_avg = np.mean([device.out_temp for device in ashp_list])
+
+            if season == Season.cooling:
+                temp_diff = in_temp_avg - out_temp_avg
+            else:
+                temp_diff = out_temp_avg - in_temp_avg
+
+            if temp_diff > 6.0:
+                diff = 5.0
+            elif temp_diff < 4.0:
+                diff = -5.0
+            else:
+                diff = 0.0
+
+            self.set_freq(diff, 0)
+
+    def set_freq(self, diff: float, base: float):
+        for device in self._pump_list:
+            if device.equip_switch_set:
+                if base == 0:
+                    device.work_freq_set = device.work_freq_set + diff
+                else:
+                    device.work_freq_set = base + diff
+
+    def get_result(self):
+        return self._pump_list
+
+
+class FeedWaterPumpBRController(FeedWaterPumpController):
+    def __init__(self, pump_list: list[FeedWaterPump]):
+        super().__init__(pump_list)
+
+    def get_switch_set(self, ashp_list: list[ASHP]):
+        ashp_on_count = 0
+        ashp_off_count = 0
+        for item in ashp_list:
+            if item.equip_switch_set:
+                ashp_on_count += 1
+            if not item.running_status:
+                ashp_off_count += 1
+
+        ashp_num = len(ashp_list)
+        pump_num = len(self._pump_list)
+        if ashp_off_count == ashp_num:
+            self.turn_off_all()
+        else:
+            if pump_num == 2:
+                pump_need_num = 2
+            elif pump_num == 3:
+                if ashp_on_count <= ashp_num // 3:
+                    pump_need_num = 2
+                elif ashp_on_count > 2 * ashp_num // 3:
+                    pump_need_num = 3
+                else:
+                    pump_need_num = 2
+            else:
+                pump_need_num = 2
+
+            self._pump_list = sorted(self._pump_list, key=attrgetter("acc_run_time"))
+            for device in self._pump_list:
+                if not device.running_status:
+                    device.equip_switch_set = True
+                    pump_need_num -= 1
+                    if pump_need_num == 0:
+                        break
+
+
+async def build_feed_water_pump_instructions(params: FeedWaterPumpRequest):
+    ashp_controller = ASHPGroupController(params.ashp_list, params.outdoor_temp, params.season)
+    try:
+        ashp_controller.run()
+    except (TypeError, IndexError):
+        raise MissingIOTDataError
+    ashp_list, _, _ = ashp_controller.get_results()
+
+    pump_controller = FeedWaterPumpController(params.pump_list)
+    pump_controller.get_freq_set(params.ashp_list, params.season)
+    pump_controller.get_switch_set(params.ashp_list)
+
+    return pump_controller.get_result()
+
+
+async def build_feed_water_pump_br_instructions(params: FeedWaterPumpRequest):
+    ashp_controller = ASHPGroupController(params.ashp_list, params.outdoor_temp, params.season)
+    try:
+        ashp_controller.run()
+    except (TypeError, IndexError):
+        raise MissingIOTDataError
+    ashp_list, _, _ = ashp_controller.get_results()
+
+    pump_controller = FeedWaterPumpController(params.pump_list)
+    pump_controller.get_freq_set(params.ashp_list, params.season, 40.0)
+    pump_controller.get_switch_set(params.ashp_list)
+
+    return pump_controller.get_result()

+ 12 - 1
app/models/domain/devices.py

@@ -4,7 +4,7 @@ from pydantic import BaseModel, Field
 
 from app.controllers.equipment.switch import SwitchSet
 from app.models.domain.feedback import FeedbackValue
-from app.schemas.equipment import ASHP
+from app.schemas.equipment import ASHP, FeedWaterPump
 from app.schemas.equipment import VRFMode
 from app.schemas.season import Season
 
@@ -311,3 +311,14 @@ class ASHPResponse(BaseModel):
     device_list: list[ASHP]
     interval: float
     is_warning: bool
+
+
+class FeedWaterPumpRequest(BaseModel):
+    season: Season
+    outdoor_temp: list[float]
+    ashp_list: list[ASHP]
+    pump_list: list[FeedWaterPump]
+
+
+class FeedWaterPumpResponse(BaseModel):
+    device_list: list[FeedWaterPump]

+ 8 - 0
app/schemas/equipment.py

@@ -29,6 +29,7 @@ class BaseEquipment(BaseModel):
     on_time: str | None
     off_time: str | None
     equip_switch_set: bool | None
+    acc_run_time: float | None
 
 
 class FCU(BaseEquipment):
@@ -94,5 +95,12 @@ class ASHP(BaseEquipment):
     out_temp_30min: list[float]
     out_temp_set_30min: list[float]
     out_temp_set: float | None
+    out_temp: float | None
+    in_temp: float | None
     iplr_15min: list[float]
     iplr_30min: list[float]
+
+
+class FeedWaterPump(BaseEquipment):
+    work_freq: float | None
+    work_freq_set: float | None