ソースを参照

add new ATFC logic and add new params for Jiaming ATVA logic router

highing666 3 年 前
コミット
2c3c495e53

+ 30 - 4
app/api/routers/devices.py

@@ -14,6 +14,8 @@ from app.controllers.equipment.ahu.thermal_mode import build_acatah_thermal_mode
 from app.controllers.equipment.fcu.basic import (
 from app.controllers.equipment.fcu.basic import (
     build_acatfc2_instructions,
     build_acatfc2_instructions,
     build_acatfc4_instructions,
     build_acatfc4_instructions,
+    build_acatfc2_instructions_v2,
+    build_acatfc4_instructions_v2,
 )
 )
 from app.controllers.equipment.fcu.early_start import (
 from app.controllers.equipment.fcu.early_start import (
     build_acatfc_early_start_prediction,
     build_acatfc_early_start_prediction,
@@ -228,6 +230,31 @@ async def get_acatfc4_instructions(params: domain_devices.ACATFC4InstructionsReq
 
 
 
 
 @router.post(
 @router.post(
+    "/instructions/acatfc2/v2",
+    response_model=domain_devices.ACATFC2InstructionsResponse,
+)
+async def get_acatfc2_instruction_v2(params: domain_devices.ACATFC2InstructionsRequest):
+    instructions = await build_acatfc2_instructions_v2(params)
+
+    logger.info(params)
+    logger.info(f"{params.device_id} - {instructions}")
+
+    return instructions
+
+
+@router.post(
+    "/instrucions/acatfc4/v2", response_model=domain_devices.ACATFC4InstructionsResponse
+)
+async def get_acatfc4_instrutions_v2(params: domain_devices.ACATFC4InstructionsRequest):
+    instructions = await build_acatfc4_instructions_v2(params)
+
+    logger.info(params)
+    logger.info(f"{params.device_id} - {instructions}")
+
+    return instructions
+
+
+@router.post(
     "/instructions/acatva", response_model=domain_devices.ACATVAInstructionsResponse
     "/instructions/acatva", response_model=domain_devices.ACATVAInstructionsResponse
 )
 )
 async def get_acatva_instructions(params: domain_devices.ACATVAInstructionsRequest):
 async def get_acatva_instructions(params: domain_devices.ACATVAInstructionsRequest):
@@ -258,10 +285,9 @@ async def get_acatva_instructions(params: domain_devices.ACATVAInstructionsReque
 async def get_acatva_instructions_v2(
 async def get_acatva_instructions_v2(
     params: domain_devices.ACATVAInstructionsRequestV2,
     params: domain_devices.ACATVAInstructionsRequestV2,
 ):
 ):
-    temp_set = await build_acatva_instructions_for_JM(params)
+    instructions = await build_acatva_instructions_for_JM(params)
 
 
-    resp = {"temperature_target_set": temp_set}
     logger.info(params)
     logger.info(params)
-    logger.info(f"{params.device_id} - {resp}")
+    logger.info(f"{params.device_id} - {instructions}")
 
 
-    return resp
+    return instructions

+ 152 - 5
app/controllers/equipment/fcu/basic.py

@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 # -*- coding: utf-8 -*-
 
 
-from typing import Dict
+from typing import Dict, Tuple
 
 
 import numpy as np
 import numpy as np
 from httpx import AsyncClient
 from httpx import AsyncClient
@@ -38,10 +38,13 @@ class FCUController(EquipmentController):
     async def get_mode(self) -> int:
     async def get_mode(self) -> int:
         temperature_target = self._equipment.space.temperature_target
         temperature_target = self._equipment.space.temperature_target
         if self.season == Season.heating:
         if self.season == Season.heating:
-            if temperature_target >= self._equipment.space.realtime_temperature:
-                mode = 2
-            else:
-                mode = 1
+            mode = 2
+            if (
+                temperature_target > 0
+                and self._equipment.space.realtime_temperature > 0
+            ):
+                if temperature_target < self._equipment.space.realtime_temperature:
+                    mode = 1
         elif self.season == Season.cooling:
         elif self.season == Season.cooling:
             mode = 1
             mode = 1
         else:
         else:
@@ -179,6 +182,124 @@ class FCUControllerV2(EquipmentController):
         return self.equipment
         return self.equipment
 
 
 
 
+class ATFC2Controller:
+    """Two-wipe ATFC logic"""
+
+    def __init__(self, space_target: float, space_realtime: float, season: Season):
+        self.space_target = space_target
+        self.space_realtime = space_realtime
+        self.season = season
+
+    def build_speed_set(self) -> str:
+        if self.space_realtime > 0.0 and self.space_target > 0.0:
+            if self.season == Season.cooling:
+                diff = self.space_realtime - self.space_target
+            elif self.season == Season.heating:
+                diff = self.space_target - self.space_realtime
+            else:
+                diff = 0.0
+
+            if diff <= 0.0:
+                speed = "off"
+            elif diff < 0.5:
+                speed = "low"
+            elif diff < 1.5:
+                speed = "medium"
+            else:
+                speed = "high"
+        else:
+            speed = "hold"
+            if self.space_target < 0.0:
+                speed = "off"
+
+        return speed
+
+    def build_switch_set(self, new_speed_set: str) -> str:
+        if new_speed_set == "off":
+            switch_set = "off"
+        else:
+            switch_set = "on"
+
+        return switch_set
+
+    def build_water_valve_set(self, new_switch_set: str) -> str:
+        return new_switch_set
+
+    def run(self) -> dict:
+        speed = self.build_speed_set()
+        switch_set = self.build_switch_set(speed)
+        water_switch_set = self.build_water_valve_set(switch_set)
+
+        res = {
+            "speed_set": speed,
+            "switch_set": switch_set,
+            "water_valve_set": water_switch_set,
+        }
+
+        return res
+
+
+class ATFC4Controller(ATFC2Controller):
+    """Four-wipe ATFC logic"""
+
+    def __init__(self, space_target: float, space_realtime: float, season: Season):
+        super().__init__(space_target, space_realtime, season)
+
+    def build_speed_set(self) -> str:
+        speed = super().build_speed_set()
+        if self.season == Season.heating:
+            if self.space_target > 0.0 and self.space_realtime > 0.0:
+                diff = abs(self.space_realtime - self.space_target)
+                if diff < 0.2:
+                    speed = "off"
+                elif diff < 0.8:
+                    speed = "low"
+                elif diff < 1.5:
+                    speed = "medium"
+                else:
+                    speed = "high"
+
+        return speed
+
+    def build_water_valve_set(self, new_switch_set: str) -> Tuple[str, str]:
+        if new_switch_set == "off":
+            chill_water_valve_set = "off"
+            hot_water_valve_set = "off"
+        else:
+            if self.season == Season.heating:
+                if self.space_realtime > 0.0:
+                    if self.space_realtime > self.space_target:
+                        chill_water_valve_set = "on"
+                        hot_water_valve_set = "off"
+                    else:
+                        chill_water_valve_set = "off"
+                        hot_water_valve_set = "on"
+                else:
+                    chill_water_valve_set = "hold"
+                    hot_water_valve_set = "hold"
+            else:
+                chill_water_valve_set = "on"
+                hot_water_valve_set = "off"
+
+        return chill_water_valve_set, hot_water_valve_set
+
+    def run(self) -> dict:
+        speed = self.build_speed_set()
+        switch_set = self.build_switch_set(speed)
+        chill_water_valve_set, hot_water_valve_set = self.build_water_valve_set(
+            switch_set
+        )
+
+        res = {
+            "speed_set": speed,
+            "switch_set": switch_set,
+            "chill_water_valve_set": chill_water_valve_set,
+            "hot_water_valve_set": hot_water_valve_set,
+        }
+
+        return res
+
+
 @logger.catch()
 @logger.catch()
 async def get_fcu_control_result(project_id: str, equipment_id: str) -> Dict:
 async def get_fcu_control_result(project_id: str, equipment_id: str) -> Dict:
     async with AsyncClient() as client:
     async with AsyncClient() as client:
@@ -282,3 +403,29 @@ async def build_acatfc4_instructions(
     )
     )
 
 
     return instructions
     return instructions
+
+
+@logger.catch()
+async def build_acatfc2_instructions_v2(params: ACATFC2InstructionsRequest) -> dict:
+    space_realtime = (
+        params.space_realtime_temperature if params.space_realtime_temperature else -1
+    )
+    controller = ATFC2Controller(
+        params.space_temperature_target, space_realtime, Season(params.season)
+    )
+    instructions = controller.run()
+
+    return instructions
+
+
+@logger.catch()
+async def build_acatfc4_instructions_v2(params: ACATFC4InstructionsRequest) -> dict:
+    space_realtime = (
+        params.space_realtime_temperature if params.space_realtime_temperature else -1
+    )
+    controller = ATFC4Controller(
+        params.space_temperature_target, space_realtime, Season(params.season)
+    )
+    instructions = controller.run()
+
+    return instructions

+ 8 - 2
app/controllers/equipment/vav.py

@@ -437,7 +437,7 @@ async def build_acatva_instructions(
 @logger.catch()
 @logger.catch()
 async def build_acatva_instructions_for_JM(
 async def build_acatva_instructions_for_JM(
     params: ACATVAInstructionsRequestV2,
     params: ACATVAInstructionsRequestV2,
-) -> float:
+) -> dict:
     # Control logic for Jiaming.
     # Control logic for Jiaming.
 
 
     space_params = []
     space_params = []
@@ -468,5 +468,11 @@ async def build_acatva_instructions_for_JM(
             next_temp_set = -1.0
             next_temp_set = -1.0
     else:
     else:
         next_temp_set = -1.0
         next_temp_set = -1.0
+    
+    instructions = {
+        'temperature_target_set': next_temp_set,
+        'virtual_target_temperature': regulated_vav.virtual_target_temperature,
+        'virtual_realtime_temperature': regulated_vav.virtual_realtime_temperature
+    }
 
 
-    return next_temp_set
+    return instructions

+ 16 - 0
app/models/domain/devices.py

@@ -67,6 +67,20 @@ class ACATFC4InstructionsRequest(ACATFCInstructionsRequestBase):
     pass
     pass
 
 
 
 
+class ACATFCInstructionsResponseBase(BaseModel):
+    speed_set: str
+    switch_set: str
+
+
+class ACATFC2InstructionsResponse(ACATFCInstructionsResponseBase):
+    water_valve_set: str
+
+
+class ACATFC4InstructionsResponse(ACATFCInstructionsResponseBase):
+    chill_water_valve_set: str
+    hot_water_valve_set: str
+
+
 class ACATFCInstructionsResponse(BaseModel):
 class ACATFCInstructionsResponse(BaseModel):
     switch_set: int = Field(None, alias="onOff")
     switch_set: int = Field(None, alias="onOff")
     speed_set: int = Field(None, alias="speed")
     speed_set: int = Field(None, alias="speed")
@@ -125,6 +139,8 @@ class ACATVAInstructionsResponse(BaseModel):
 
 
 class ACATVAInstructionsResponseV2(BaseModel):
 class ACATVAInstructionsResponseV2(BaseModel):
     temperature_target_set: float
     temperature_target_set: float
+    virtual_target_temperature: float
+    virtual_realtime_temperature: float
 
 
 
 
 class ACATAHFreqSetRequest(BaseModel):
 class ACATAHFreqSetRequest(BaseModel):