|
@@ -1,23 +1,15 @@
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
|
-from typing import Dict, Tuple
|
|
|
-
|
|
|
-import numpy as np
|
|
|
-from httpx import AsyncClient
|
|
|
-from loguru import logger
|
|
|
+from typing import Tuple
|
|
|
|
|
|
+from app.api.errors.iot import MissingIOTDataError
|
|
|
from app.controllers.equipment.controller import EquipmentController
|
|
|
-from app.models.domain.devices import (
|
|
|
- ACATFC2InstructionsRequest,
|
|
|
- ACATFC4InstructionsRequest,
|
|
|
- Speed,
|
|
|
-)
|
|
|
+from app.models.domain.devices import ACATFC2InstructionsRequest, ACATFC4InstructionsRequest, Speed
|
|
|
from app.models.domain.feedback import FeedbackValue
|
|
|
from app.schemas.equipment import AirValveSpeed, FCU
|
|
|
from app.schemas.instructions import ACATFCInstructions
|
|
|
from app.schemas.space import Space
|
|
|
-from app.services.platform import DataPlatformService, InfoCode
|
|
|
-from app.services.transfer import SpaceInfoService, Duoduo, Season
|
|
|
+from app.services.transfer import Season
|
|
|
from app.utils.math import round_half_up
|
|
|
|
|
|
|
|
@@ -29,7 +21,7 @@ class FCUController(EquipmentController):
|
|
|
|
|
|
async def get_temperature_target(self) -> float:
|
|
|
target = self._equipment.space.temperature_target
|
|
|
- if not np.isnan(target):
|
|
|
+ if target:
|
|
|
setting_target = target
|
|
|
else:
|
|
|
setting_target = 25.0
|
|
@@ -41,10 +33,7 @@ class FCUController(EquipmentController):
|
|
|
temperature_target = self._equipment.space.temperature_target
|
|
|
if self.season == Season.heating:
|
|
|
mode = 2
|
|
|
- if (
|
|
|
- temperature_target > 0
|
|
|
- and self._equipment.space.realtime_temperature > 0
|
|
|
- ):
|
|
|
+ if temperature_target and self._equipment.space.realtime_temperature:
|
|
|
if temperature_target < self._equipment.space.realtime_temperature:
|
|
|
mode = 1
|
|
|
elif self.season == Season.cooling:
|
|
@@ -57,11 +46,9 @@ class FCUController(EquipmentController):
|
|
|
|
|
|
async def get_air_valve_speed(self):
|
|
|
temperature_target = self._equipment.space.temperature_target
|
|
|
- if temperature_target > 0:
|
|
|
+ if temperature_target:
|
|
|
if self.season == Season.heating:
|
|
|
- diff = abs(
|
|
|
- self._equipment.space.realtime_temperature - temperature_target
|
|
|
- )
|
|
|
+ diff = abs(self._equipment.space.realtime_temperature - temperature_target)
|
|
|
if diff >= 1.5:
|
|
|
self._equipment.air_valve_speed = AirValveSpeed.high
|
|
|
elif diff >= 1.0:
|
|
@@ -90,10 +77,13 @@ class FCUController(EquipmentController):
|
|
|
self._equipment.running_status = True
|
|
|
|
|
|
async def run(self):
|
|
|
- # await self.get_temperature_target()
|
|
|
- await self.get_air_valve_speed()
|
|
|
- await self.get_running_status()
|
|
|
- await self.get_mode()
|
|
|
+ try:
|
|
|
+ await self.get_air_valve_speed()
|
|
|
+ await self.get_running_status()
|
|
|
+ await self.get_mode()
|
|
|
+ await self.get_temperature_target()
|
|
|
+ except TypeError:
|
|
|
+ raise MissingIOTDataError
|
|
|
|
|
|
def get_results(self):
|
|
|
return self._equipment
|
|
@@ -108,19 +98,13 @@ class FCUControllerV2(EquipmentController):
|
|
|
self.season = season
|
|
|
|
|
|
def get_mode(self) -> int:
|
|
|
- if self.equipment.water_in_temperature > 0:
|
|
|
- if (
|
|
|
- self.equipment.water_in_temperature
|
|
|
- > self.equipment.space.temperature_target
|
|
|
- ):
|
|
|
+ if self.equipment.water_in_temperature and self.equipment.space.temperature_target:
|
|
|
+ if self.equipment.water_in_temperature > self.equipment.space.temperature_target:
|
|
|
mode = 2
|
|
|
else:
|
|
|
mode = 1
|
|
|
- elif self.equipment.supply_air_temperature > 0:
|
|
|
- if (
|
|
|
- self.equipment.supply_air_temperature
|
|
|
- > self.equipment.space.temperature_target
|
|
|
- ):
|
|
|
+ elif self.equipment.supply_air_temperature and self.equipment.space.temperature_target:
|
|
|
+ if self.equipment.supply_air_temperature > self.equipment.space.temperature_target:
|
|
|
mode = 2
|
|
|
else:
|
|
|
mode = 1
|
|
@@ -137,8 +121,8 @@ class FCUControllerV2(EquipmentController):
|
|
|
|
|
|
def build_air_valve_speed(self):
|
|
|
target = self.equipment.space.temperature_target
|
|
|
- if target > 0:
|
|
|
- if self.equipment.space.realtime_temperature > 0:
|
|
|
+ if target:
|
|
|
+ if self.equipment.space.realtime_temperature:
|
|
|
mode = self.get_mode()
|
|
|
if mode == 2:
|
|
|
diff = target - self.equipment.space.realtime_temperature
|
|
@@ -169,16 +153,19 @@ class FCUControllerV2(EquipmentController):
|
|
|
self.equipment.running_status = True
|
|
|
|
|
|
def build_temperature_set(self):
|
|
|
- if np.isnan(self.equipment.space.temperature_target):
|
|
|
- self.equipment.setting_temperature = 0.0
|
|
|
- else:
|
|
|
+ if self.equipment.space.temperature_target:
|
|
|
self.equipment.setting_temperature = self.equipment.space.temperature_target
|
|
|
+ else:
|
|
|
+ self.equipment.setting_temperature = 0.0
|
|
|
|
|
|
async def run(self):
|
|
|
- self.build_air_valve_speed()
|
|
|
- self.build_running_status()
|
|
|
- self.get_mode()
|
|
|
- self.build_temperature_set()
|
|
|
+ try:
|
|
|
+ self.build_air_valve_speed()
|
|
|
+ self.build_running_status()
|
|
|
+ self.get_mode()
|
|
|
+ self.build_temperature_set()
|
|
|
+ except TypeError:
|
|
|
+ raise MissingIOTDataError
|
|
|
|
|
|
def get_results(self):
|
|
|
return self.equipment
|
|
@@ -247,7 +234,7 @@ class ATFC2Controller:
|
|
|
|
|
|
def build_speed_set(self) -> Speed:
|
|
|
speed_controller = SpeedController(self.speed, self.running_status)
|
|
|
- if self.space_realtime > 0.0 and self.space_target > 0.0:
|
|
|
+ if self.space_realtime and self.space_target:
|
|
|
if self.season == Season.cooling:
|
|
|
diff = self.space_realtime - self.space_target
|
|
|
elif self.season == Season.heating:
|
|
@@ -267,23 +254,17 @@ class ATFC2Controller:
|
|
|
speed = Speed.high
|
|
|
else:
|
|
|
speed = Speed.hold
|
|
|
- if self.space_target < 0.0:
|
|
|
+ if not self.space_target:
|
|
|
speed = Speed.off
|
|
|
else:
|
|
|
if self.feedback == FeedbackValue.switch_on:
|
|
|
speed = Speed.medium
|
|
|
- elif (
|
|
|
- self.feedback == FeedbackValue.so_hot
|
|
|
- or self.feedback == FeedbackValue.a_little_hot
|
|
|
- ):
|
|
|
+ elif self.feedback == FeedbackValue.so_hot or self.feedback == FeedbackValue.a_little_hot:
|
|
|
if self.season == Season.cooling:
|
|
|
speed = speed_controller.turn_up()
|
|
|
elif self.season == Season.heating:
|
|
|
speed = speed_controller.turn_down()
|
|
|
- elif (
|
|
|
- self.feedback == FeedbackValue.so_cold
|
|
|
- or self.feedback == FeedbackValue.a_little_cold
|
|
|
- ):
|
|
|
+ elif self.feedback == FeedbackValue.so_cold or self.feedback == FeedbackValue.a_little_cold:
|
|
|
if self.season == Season.cooling:
|
|
|
speed = speed_controller.turn_down()
|
|
|
elif self.season == Season.heating:
|
|
@@ -306,9 +287,12 @@ class ATFC2Controller:
|
|
|
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)
|
|
|
+ try:
|
|
|
+ speed = self.build_speed_set()
|
|
|
+ switch_set = self.build_switch_set(speed)
|
|
|
+ water_switch_set = self.build_water_valve_set(switch_set)
|
|
|
+ except TypeError:
|
|
|
+ raise MissingIOTDataError
|
|
|
|
|
|
res = {
|
|
|
"speed_set": speed,
|
|
@@ -339,7 +323,7 @@ class ATFC4Controller(ATFC2Controller):
|
|
|
speed = super().build_speed_set()
|
|
|
if self.season == Season.heating:
|
|
|
speed_controller = SpeedController(self.speed, self.running_status)
|
|
|
- if self.space_target > 0.0 and self.space_realtime > 0.0:
|
|
|
+ if self.space_target and self.space_realtime:
|
|
|
diff = abs(self.space_realtime - self.space_target)
|
|
|
if diff < 0.2:
|
|
|
speed = Speed.hold
|
|
@@ -350,20 +334,14 @@ class ATFC4Controller(ATFC2Controller):
|
|
|
else:
|
|
|
speed = Speed.high
|
|
|
else:
|
|
|
- if self.space_target < 0.0:
|
|
|
+ if not self.space_target:
|
|
|
speed = Speed.off
|
|
|
else:
|
|
|
if self.feedback == FeedbackValue.switch_on:
|
|
|
speed = Speed.medium
|
|
|
- elif (
|
|
|
- self.feedback == FeedbackValue.so_hot
|
|
|
- or self.feedback == FeedbackValue.a_little_hot
|
|
|
- ):
|
|
|
+ elif self.feedback == FeedbackValue.so_hot or self.feedback == FeedbackValue.a_little_hot:
|
|
|
speed = speed_controller.turn_up()
|
|
|
- elif (
|
|
|
- self.feedback == FeedbackValue.so_cold
|
|
|
- or self.feedback == FeedbackValue.a_little_cold
|
|
|
- ):
|
|
|
+ elif self.feedback == FeedbackValue.so_cold or self.feedback == FeedbackValue.a_little_cold:
|
|
|
speed = speed_controller.turn_up()
|
|
|
|
|
|
return speed
|
|
@@ -374,7 +352,7 @@ class ATFC4Controller(ATFC2Controller):
|
|
|
hot_water_valve_set = "off"
|
|
|
else:
|
|
|
if self.season == Season.heating:
|
|
|
- if self.space_realtime > 0.0:
|
|
|
+ if self.space_realtime and self.space_target:
|
|
|
if self.space_realtime - self.space_target >= 0.2:
|
|
|
chill_water_valve_set = "on"
|
|
|
hot_water_valve_set = "off"
|
|
@@ -390,16 +368,10 @@ class ATFC4Controller(ATFC2Controller):
|
|
|
if self.feedback == FeedbackValue.switch_on:
|
|
|
chill_water_valve_set = "off"
|
|
|
hot_water_valve_set = "on"
|
|
|
- elif (
|
|
|
- self.feedback == FeedbackValue.so_hot
|
|
|
- or self.feedback == FeedbackValue.a_little_hot
|
|
|
- ):
|
|
|
+ elif self.feedback == FeedbackValue.so_hot or self.feedback == FeedbackValue.a_little_hot:
|
|
|
chill_water_valve_set = "on"
|
|
|
hot_water_valve_set = "off"
|
|
|
- elif (
|
|
|
- self.feedback == FeedbackValue.so_cold
|
|
|
- or self.feedback == FeedbackValue.a_little_cold
|
|
|
- ):
|
|
|
+ elif self.feedback == FeedbackValue.so_cold or self.feedback == FeedbackValue.a_little_cold:
|
|
|
chill_water_valve_set = "off"
|
|
|
hot_water_valve_set = "on"
|
|
|
else:
|
|
@@ -409,11 +381,12 @@ class ATFC4Controller(ATFC2Controller):
|
|
|
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
|
|
|
- )
|
|
|
+ try:
|
|
|
+ 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)
|
|
|
+ except TypeError:
|
|
|
+ raise MissingIOTDataError
|
|
|
|
|
|
res = {
|
|
|
"speed_set": speed,
|
|
@@ -425,65 +398,7 @@ class ATFC4Controller(ATFC2Controller):
|
|
|
return res
|
|
|
|
|
|
|
|
|
-@logger.catch()
|
|
|
-async def get_fcu_control_result(project_id: str, equipment_id: str) -> Dict:
|
|
|
- async with AsyncClient() as client:
|
|
|
- duo_duo = Duoduo(client, project_id)
|
|
|
- platform = DataPlatformService(client, project_id)
|
|
|
- spaces = await duo_duo.get_space_by_equipment(equipment_id)
|
|
|
- if project_id == "Pj1101150003":
|
|
|
- supply_air_temperature = await platform.get_realtime_data(
|
|
|
- InfoCode.supply_temperature, equipment_id
|
|
|
- )
|
|
|
- water_in_temperature = await platform.get_realtime_data(
|
|
|
- InfoCode.water_in_temperature, equipment_id
|
|
|
- )
|
|
|
- else:
|
|
|
- supply_air_temperature = np.NAN
|
|
|
- water_in_temperature = np.NAN
|
|
|
- for sp in spaces:
|
|
|
- transfer = SpaceInfoService(client, project_id, sp.get("id"))
|
|
|
- current_target = await transfer.get_current_temperature_target()
|
|
|
- realtime_temperature = await platform.get_realtime_temperature(sp.get("id"))
|
|
|
- season = await duo_duo.get_season()
|
|
|
- temp_space_params = {
|
|
|
- "id": sp.get("id"),
|
|
|
- "temperature_target": current_target,
|
|
|
- "realtime_temperature": realtime_temperature,
|
|
|
- }
|
|
|
- space = Space(**temp_space_params)
|
|
|
- break
|
|
|
-
|
|
|
- fcu_temp_params = {
|
|
|
- "id": equipment_id,
|
|
|
- "space": space,
|
|
|
- "supply_air_temperature": supply_air_temperature,
|
|
|
- "water_in_temperature": water_in_temperature,
|
|
|
- }
|
|
|
- fcu = FCU(**fcu_temp_params)
|
|
|
-
|
|
|
- if project_id == "Pj1101050030":
|
|
|
- fcu_controller = FCUController(fcu, season)
|
|
|
- else:
|
|
|
- fcu_controller = FCUControllerV2(fcu, season)
|
|
|
- await fcu_controller.run()
|
|
|
- regulated_fcu = fcu_controller.get_results()
|
|
|
-
|
|
|
- output = {
|
|
|
- "onOff": 1 if regulated_fcu.running_status else 0,
|
|
|
- "mode": regulated_fcu.work_mode,
|
|
|
- "speed": regulated_fcu.air_valve_speed.value,
|
|
|
- "temperature": float(round_half_up(regulated_fcu.setting_temperature, 1)),
|
|
|
- "water": 1 if regulated_fcu.running_status else 0,
|
|
|
- }
|
|
|
-
|
|
|
- return output
|
|
|
-
|
|
|
-
|
|
|
-@logger.catch()
|
|
|
-async def build_acatfc2_instructions(
|
|
|
- params: ACATFC2InstructionsRequest,
|
|
|
-) -> ACATFCInstructions:
|
|
|
+async def build_acatfc2_instructions(params: ACATFC2InstructionsRequest) -> ACATFCInstructions:
|
|
|
space = Space(
|
|
|
temperature_target=params.space_temperature_target,
|
|
|
realtime_temperature=params.space_realtime_temperature,
|
|
@@ -505,10 +420,7 @@ async def build_acatfc2_instructions(
|
|
|
return instructions
|
|
|
|
|
|
|
|
|
-@logger.catch()
|
|
|
-async def build_acatfc4_instructions(
|
|
|
- params: ACATFC4InstructionsRequest,
|
|
|
-) -> ACATFCInstructions:
|
|
|
+async def build_acatfc4_instructions(params: ACATFC4InstructionsRequest) -> ACATFCInstructions:
|
|
|
space = Space(
|
|
|
temperature_target=params.space_temperature_target,
|
|
|
realtime_temperature=params.space_realtime_temperature,
|
|
@@ -530,14 +442,10 @@ async def build_acatfc4_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,
|
|
|
+ params.space_realtime_temperature,
|
|
|
Season(params.season),
|
|
|
params.feedback,
|
|
|
params.running_status,
|
|
@@ -548,14 +456,10 @@ async def build_acatfc2_instructions_v2(params: ACATFC2InstructionsRequest) -> d
|
|
|
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,
|
|
|
+ params.space_realtime_temperature,
|
|
|
Season(params.season),
|
|
|
params.feedback,
|
|
|
params.running_status,
|