瀏覽代碼

merged from origin dev

highing666 2 年之前
父節點
當前提交
b8a4b888ae

+ 9 - 14
app/api/errors/iot.py

@@ -1,20 +1,15 @@
-from functools import wraps
+from fastapi import FastAPI, Request
+from fastapi.responses import JSONResponse
 
 
-from fastapi import HTTPException
+app = FastAPI()
 
 
 
 
 class MissingIOTDataError(Exception):
 class MissingIOTDataError(Exception):
-    def __init__(self):
-        super().__init__(f"Missing IOT data error.")
+    pass
 
 
 
 
-def missing_iot_data_handler(func):
-    @wraps(func)
-    async def inner_function(*args, **kwargs):
-        try:
-            results = await func(*args, **kwargs)
-        except MissingIOTDataError:
-            raise HTTPException(status_code=400, detail="Missing data.")
-        return results
-
-    return inner_function
+async def missing_data_exception_handler(request: Request, exc: MissingIOTDataError):
+    return JSONResponse(
+        status_code=400,
+        content={"message": "Missing data"}
+    )

+ 2 - 2
app/api/routers/devices.py

@@ -28,7 +28,7 @@ from app.controllers.equipment.pau.supply_air_temperature_set import (
 from app.controllers.equipment.pau.switch import build_acatfu_switch_set, build_co2_acatfu_switch
 from app.controllers.equipment.pau.switch import build_acatfu_switch_set, build_co2_acatfu_switch
 from app.controllers.equipment.vav import (
 from app.controllers.equipment.vav import (
     build_acatva_instructions,
     build_acatva_instructions,
-    build_acatva_instructions_for_JM,
+    build_acatva_instructions_for_jm,
 )
 )
 from app.controllers.equipment.ventilation_fan.switch import build_acvtsf_switch_set
 from app.controllers.equipment.ventilation_fan.switch import build_acvtsf_switch_set
 from app.controllers.equipment.vrf.basic import build_acatvi_instructions
 from app.controllers.equipment.vrf.basic import build_acatvi_instructions
@@ -324,7 +324,7 @@ 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,
 ):
 ):
-    instructions = await build_acatva_instructions_for_JM(params)
+    instructions = await build_acatva_instructions_for_jm(params)
 
 
     logger.info(params)
     logger.info(params)
     logger.info(f"{params.device_id} - {instructions}")
     logger.info(f"{params.device_id} - {instructions}")

+ 0 - 119
app/api/routers/equipment.py

@@ -1,119 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from enum import Enum
-
-import numpy as np
-from fastapi import APIRouter, Depends, Query
-from loguru import logger
-from sqlalchemy.orm import Session
-
-from app.api.dependencies.db import get_db
-from app.controllers.equipment.fcu.basic import get_fcu_control_result
-from app.controllers.equipment.vav import get_vav_control_v2
-from app.models.domain.equipment import (
-    EquipmentControlResponse,
-    EquipmentControlRequest,
-)
-from app.schemas.equipment import PAU
-from app.utils.date import get_time_str
-
-
-class EquipmentName(str, Enum):
-    FCU = "ACATFC"
-    VAV = "ACATVA"
-
-
-router = APIRouter()
-
-
-@router.get("/control", response_model=EquipmentControlResponse)
-async def get_equipment_command_test(
-    project_id: str = Query(..., max_length=50, regex="^Pj", alias="projectId"),
-    equip_id: str = Query(..., max_length=50, regex="^Eq", alias="equipId"),
-    equip_type: EquipmentName = Query(..., alias="equipType"),
-    db: Session = Depends(get_db),
-):
-    if equip_type.value == EquipmentName.FCU:
-        output = await get_fcu_control_result(project_id, equip_id)
-    elif equip_type.value == EquipmentName.VAV:
-        vav = await get_vav_control_v2(db, project_id, equip_id)
-        output = {
-            "SupplyAirFlowSet": vav.supply_air_flow_set,
-            "VirtualRealtimeTemperature": vav.virtual_realtime_temperature
-            if not np.isnan(vav.virtual_realtime_temperature)
-            else None,
-            "TargetTemperatureSet": vav.virtual_target_temperature
-            if not np.isnan(vav.virtual_target_temperature)
-            else None,
-        }
-    else:
-        output = {}
-
-    response = {
-        "projectId": project_id,
-        "equipId": equip_id,
-        "time": get_time_str(),
-        "output": output,
-    }
-    return response
-
-
-@router.post("/control", response_model=EquipmentControlResponse)
-async def get_equipment_command(
-    equipment_control_info: EquipmentControlRequest, db: Session = Depends(get_db)
-):
-    if equipment_control_info.equipType == EquipmentName.FCU:
-        output = await get_fcu_control_result(
-            equipment_control_info.projectId, equipment_control_info.equipId
-        )
-    elif equipment_control_info.equipType == EquipmentName.VAV:
-        vav = await get_vav_control_v2(
-            db, equipment_control_info.projectId, equipment_control_info.equipId
-        )
-        output = {
-            "SupplyAirFlowSet": vav.supply_air_flow_set,
-            "VirtualRealtimeTemperature": vav.virtual_realtime_temperature
-            if not np.isnan(vav.virtual_realtime_temperature)
-            else None,
-            "TargetTemperatureSet": vav.virtual_target_temperature
-            if not np.isnan(vav.virtual_target_temperature)
-            else None,
-        }
-    else:
-        output = {}
-
-    response = {
-        "projectId": equipment_control_info.projectId,
-        "equipId": equipment_control_info.equipId,
-        "time": get_time_str(),
-        "output": output,
-    }
-    logger.info(response)
-    return response
-
-
-@router.post("/control/atva/v2", response_model=EquipmentControlResponse)
-async def get_fcu_command(
-    equipment_control_info: EquipmentControlRequest, db: Session = Depends(get_db)
-):
-    vav = await get_vav_control_v2(
-        db, equipment_control_info.projectId, equipment_control_info.equipId
-    )
-    output = {
-        "SupplyAirFlowSet": vav.supply_air_flow_set,
-        "VirtualRealtimeTemperature": vav.virtual_realtime_temperature
-        if not np.isnan(vav.virtual_realtime_temperature)
-        else None,
-        "TargetTemperatureSet": vav.virtual_target_temperature
-        if not np.isnan(vav.virtual_target_temperature)
-        else None,
-    }
-
-    response = {
-        "projectId": equipment_control_info.projectId,
-        "equipId": equipment_control_info.equipId,
-        "time": get_time_str(),
-        "output": output,
-    }
-    logger.info(response)
-    return response

+ 8 - 18
app/api/routers/space.py

@@ -6,7 +6,6 @@ from fastapi import APIRouter, Depends, HTTPException, Query
 from sqlalchemy.orm import Session
 from sqlalchemy.orm import Session
 
 
 from app.api.dependencies.db import get_db
 from app.api.dependencies.db import get_db
-from app.controllers.equipment.fcu.q_learning import QLearningCommandBuilder
 from app.crud.space.weight import (
 from app.crud.space.weight import (
     get_weights_by_space,
     get_weights_by_space,
     get_weights_by_vav,
     get_weights_by_vav,
@@ -15,17 +14,16 @@ from app.crud.space.weight import (
 )
 )
 from app.models.domain.space import SpaceControlResponse
 from app.models.domain.space import SpaceControlResponse
 from app.schemas.sapce_weight import SpaceWeight, SpaceWeightCreate, SpaceWeightUpdate
 from app.schemas.sapce_weight import SpaceWeight, SpaceWeightCreate, SpaceWeightUpdate
-from app.services.transfer import Season
 
 
 router = APIRouter()
 router = APIRouter()
 
 
 
 
 @router.get("/control", response_model=SpaceControlResponse)
 @router.get("/control", response_model=SpaceControlResponse)
 async def get_space_command(
 async def get_space_command(
-    project_id: str = Query(..., max_length=50, regex="^Pj", alias="projectId"),
-    space_id: str = Query(..., max_length=50, regex="^Sp", alias="roomId"),
-    timestamp: str = Query(None, min_length=14, max_length=14, alias="time"),
-    method: int = Query(3),
+        project_id: str = Query(..., max_length=50, regex="^Pj", alias="projectId"),
+        space_id: str = Query(..., max_length=50, regex="^Sp", alias="roomId"),
+        timestamp: str = Query(None, min_length=14, max_length=14, alias="time"),
+        method: int = Query(3),
 ):
 ):
     response = {
     response = {
         "projectId": project_id,
         "projectId": project_id,
@@ -37,14 +35,6 @@ async def get_space_command(
     return response
     return response
 
 
 
 
-@router.get("/test")
-async def get_test_result(current: float, pre: float, target: float):
-    builder = QLearningCommandBuilder(Season("Cooling"))
-    command = await builder.get_command(current, pre, target)
-
-    return command
-
-
 @router.post("/weight", response_model=SpaceWeight)
 @router.post("/weight", response_model=SpaceWeight)
 async def create_space_weight(weight: SpaceWeightCreate, db: Session = Depends(get_db)):
 async def create_space_weight(weight: SpaceWeightCreate, db: Session = Depends(get_db)):
     return create_weight(db=db, weight=weight)
     return create_weight(db=db, weight=weight)
@@ -64,10 +54,10 @@ async def read_weight_by_vav(vav_id: str, db: Session = Depends(get_db)):
 
 
 @router.put("/weight/{space_id}/{vav_id}", response_model=SpaceWeight)
 @router.put("/weight/{space_id}/{vav_id}", response_model=SpaceWeight)
 async def update_weight_by_space(
 async def update_weight_by_space(
-    space_id: str,
-    vav_id: str,
-    weight_in: SpaceWeightUpdate,
-    db: Session = Depends(get_db),
+        space_id: str,
+        vav_id: str,
+        weight_in: SpaceWeightUpdate,
+        db: Session = Depends(get_db),
 ):
 ):
     weights = get_weights_by_space(db, space_id=space_id)
     weights = get_weights_by_space(db, space_id=space_id)
     new_weight = None
     new_weight = None

+ 6 - 65
app/controllers/equipment/ahu/basic.py

@@ -3,14 +3,10 @@
 from typing import List, Optional
 from typing import List, Optional
 
 
 import numpy as np
 import numpy as np
-from httpx import AsyncClient
-from loguru import logger
 
 
 from app.models.domain.devices import ACATAHFreqSetRequest
 from app.models.domain.devices import ACATAHFreqSetRequest
 from app.schemas.equipment import AHU
 from app.schemas.equipment import AHU
 from app.schemas.system import ACAT
 from app.schemas.system import ACAT
-from app.services.platform import DataPlatformService, InfoCode
-from app.services.transfer import Duoduo
 
 
 
 
 class AHUController:
 class AHUController:
@@ -19,28 +15,20 @@ class AHUController:
         self._equipment = equipment
         self._equipment = equipment
         self._system = system
         self._system = system
 
 
-    async def build_freq_set(
-            self, supply_air_temperature_set_duration: List, hot_rate: float
-    ) -> float:
+    async def build_freq_set(self, supply_air_temperature_set_duration: List, hot_rate: float) -> float:
         extent = 5
         extent = 5
         if (
         if (
-                np.isnan(self._equipment.freq_set)
-                or np.isnan(self._system.supply_static_press)
-                or np.isnan(self._system.supply_static_press_set)
+                self._equipment.freq_set is None
+                or self._system.supply_static_press is None
+                or self._system.supply_static_press_set is None
         ):
         ):
             temp_freq_set = 80.0
             temp_freq_set = 80.0
         else:
         else:
             pre_fan_freq_set = self._equipment.freq_set
             pre_fan_freq_set = self._equipment.freq_set
 
 
-            if (
-                    self._system.supply_static_press
-                    < self._system.supply_static_press_set - extent
-            ):
+            if self._system.supply_static_press < self._system.supply_static_press_set - extent:
                 temp_freq_set = pre_fan_freq_set + 2
                 temp_freq_set = pre_fan_freq_set + 2
-            elif (
-                    self._system.supply_static_press
-                    > self._system.supply_static_press_set + extent
-            ):
+            elif self._system.supply_static_press > self._system.supply_static_press_set + extent:
                 temp_freq_set = pre_fan_freq_set - 2
                 temp_freq_set = pre_fan_freq_set - 2
             else:
             else:
                 temp_freq_set = pre_fan_freq_set
                 temp_freq_set = pre_fan_freq_set
@@ -61,53 +49,6 @@ class AHUController:
         return freq_set
         return freq_set
 
 
 
 
-@logger.catch()
-async def get_freq_controlled(project_id: str, equipment_id: str) -> None:
-    async with AsyncClient() as client:
-        platform = DataPlatformService(client, project_id)
-        review_service = Duoduo(client, project_id)
-
-        fan_freq_set = await platform.get_realtime_fan_freq_set(equipment_id)
-        # system = await equip_service.get_system_by_equipment(equipment_id)
-        system = ["Sy1101050030eab54ad66b084a1cb1b919950b263280"]
-        press = await platform.get_realtime_supply_static_press(system[0])
-        press_set = await platform.get_realtime_supply_static_press_set(system[0])
-        count = await review_service.get_fill_count()
-        try:
-            hot_rate = count.get("hotNum") / (
-                    count.get("hotNum") + count.get("coldNum") + count.get("normalNum")
-            )
-        except (ZeroDivisionError, KeyError):
-            hot_rate = 0.0
-        raw_supply_air_temperature_set = await platform.get_duration(
-            InfoCode.supply_air_temperature_set, equipment_id, 30 * 60
-        )
-        supply_air_temperature_set = [
-            item["value"] for item in raw_supply_air_temperature_set
-        ]
-
-    equip_params = {"id": equipment_id, "freq_set": fan_freq_set}
-    ahu = AHU(**equip_params)
-
-    system_params = {
-        "id": system[0],
-        "supply_static_press": press,
-        "supply_static_press_set": press_set,
-    }
-    acat_system = ACAT(**system_params)
-
-    ahu_controller = AHUController(ahu, acat_system)
-    new_freq_set = await ahu_controller.build_freq_set(
-        supply_air_temperature_set, hot_rate
-    )
-    logger.debug(f"{equipment_id} freq set: {new_freq_set}")
-
-    async with AsyncClient() as client:
-        platform = DataPlatformService(client, project_id)
-        await platform.set_code_value(equipment_id, InfoCode.fan_freq_set, new_freq_set)
-
-
-@logger.catch()
 async def build_acatah_freq_set(params: ACATAHFreqSetRequest) -> float:
 async def build_acatah_freq_set(params: ACATAHFreqSetRequest) -> float:
     acat_system = ACAT(
     acat_system = ACAT(
         supply_static_press=params.system_supply_static_press,
         supply_static_press=params.system_supply_static_press,

+ 18 - 14
app/controllers/equipment/ahu/common.py

@@ -6,6 +6,7 @@ from typing import List, Tuple
 import numpy as np
 import numpy as np
 from loguru import logger
 from loguru import logger
 
 
+from app.api.errors.iot import MissingIOTDataError
 from app.models.domain.devices import ACATAHInstructionsRequest
 from app.models.domain.devices import ACATAHInstructionsRequest
 from app.schemas.equipment import AHU
 from app.schemas.equipment import AHU
 from app.schemas.season import Season
 from app.schemas.season import Season
@@ -22,7 +23,7 @@ class ATAHController:
     def get_switch_set(self) -> str:
     def get_switch_set(self) -> str:
         switch_set = "off"
         switch_set = "off"
         for sp in self._spaces:
         for sp in self._spaces:
-            if not np.isnan(sp.temperature_target):
+            if sp.temperature_target:
                 switch_set = "on"
                 switch_set = "on"
 
 
         return switch_set
         return switch_set
@@ -105,7 +106,7 @@ class ATAHController:
     def get_valid_spaces(self) -> List:
     def get_valid_spaces(self) -> List:
         valid_spaces = list()
         valid_spaces = list()
         for sp in self._spaces:
         for sp in self._spaces:
-            if not np.isnan(sp.realtime_temperature) and not np.isnan(sp.temperature_target):
+            if sp.realtime_temperature and sp.temperature_target:
                 valid_spaces.append(sp)
                 valid_spaces.append(sp)
 
 
         return valid_spaces
         return valid_spaces
@@ -143,26 +144,29 @@ class ATAHController:
         return virtual_realtime, virtual_target
         return virtual_realtime, virtual_target
 
 
     def run(self) -> Tuple[str, float, float, float]:
     def run(self) -> Tuple[str, float, float, float]:
-        virtual_realtime, virtual_target = self.build_virtual_temperature()
-        new_switch_set = self.get_switch_set()
-        if np.isnan(self._ahu.return_air_temperature_set):
-            new_freq_set = self.get_freq_set(new_switch_set, virtual_target)
-            new_return_air_temp_set = np.NAN
-        else:
-            new_return_air_temp_set = self.get_return_air_temp_set(virtual_target)
-            new_freq_set = np.NAN
-        new_supply_air_temp_set = self.get_supply_air_temp_set(new_switch_set, virtual_realtime)
+        try:
+            virtual_realtime, virtual_target = self.build_virtual_temperature()
+            new_switch_set = self.get_switch_set()
+            if not self._ahu.return_air_temperature_set:
+                new_freq_set = self.get_freq_set(new_switch_set, virtual_target)
+                new_return_air_temp_set = np.NAN
+            else:
+                new_return_air_temp_set = self.get_return_air_temp_set(virtual_target)
+                new_freq_set = np.NAN
+            new_supply_air_temp_set = self.get_supply_air_temp_set(new_switch_set, virtual_realtime)
+        except TypeError:
+            raise MissingIOTDataError
 
 
         return new_switch_set, new_return_air_temp_set, new_freq_set, new_supply_air_temp_set
         return new_switch_set, new_return_air_temp_set, new_freq_set, new_supply_air_temp_set
 
 
 
 
-@logger.catch()
 async def build_acatah_instructions(params: ACATAHInstructionsRequest):
 async def build_acatah_instructions(params: ACATAHInstructionsRequest):
     space_params = []
     space_params = []
     for sp in params.spaces:
     for sp in params.spaces:
         temp_sp = SpaceATAH(**sp.dict())
         temp_sp = SpaceATAH(**sp.dict())
-        temp_sp.diff = temp_sp.temperature_target - temp_sp.realtime_temperature
-        space_params.append(temp_sp)
+        if temp_sp.temperature_target and temp_sp.realtime_temperature:
+            temp_sp.diff = temp_sp.temperature_target - temp_sp.realtime_temperature
+            space_params.append(temp_sp)
 
 
     ahu = AHU(**params.dict())
     ahu = AHU(**params.dict())
     ahu_controller = ATAHController(ahu, space_params, params.season)
     ahu_controller = ATAHController(ahu, space_params, params.season)

+ 25 - 106
app/controllers/equipment/ahu/supply_air_temperature_set.py

@@ -2,15 +2,13 @@ from typing import List
 
 
 import arrow
 import arrow
 import numpy as np
 import numpy as np
-from httpx import AsyncClient
 from loguru import logger
 from loguru import logger
 
 
-from app.controllers.equipment.ahu.thermal_mode import count_vav_box_weight, fetch_status_params
+from app.api.errors.iot import MissingIOTDataError
+from app.controllers.equipment.ahu.thermal_mode import count_vav_box_weight
 from app.models.domain.devices import ThermalMode, ACATAHSupplyAirTempSetRequest
 from app.models.domain.devices import ThermalMode, ACATAHSupplyAirTempSetRequest
 from app.schemas.equipment import VAVBox
 from app.schemas.equipment import VAVBox
-from app.services.platform import DataPlatformService, InfoCode
-from app.services.transfer import Duoduo, Season
-from app.services.weather import WeatherService
+from app.services.transfer import Season
 from app.utils.date import get_time_str, TIME_FMT
 from app.utils.date import get_time_str, TIME_FMT
 
 
 
 
@@ -108,25 +106,28 @@ class ACATAHSupplyAirTemperatureController:
         return ratio
         return ratio
 
 
     def build(self) -> float:
     def build(self) -> float:
-        if not self.is_off_to_on:
-            normal_ratio = self.get_normal_ratio()
-            if normal_ratio < 0.9:
-                cold_ratio = self.get_cold_ratio()
-                temperature = self.calculate_by_cold_vav(cold_ratio)
+        try:
+            if not self.is_off_to_on:
+                normal_ratio = self.get_normal_ratio()
+                if normal_ratio < 0.9:
+                    cold_ratio = self.get_cold_ratio()
+                    temperature = self.calculate_by_cold_vav(cold_ratio)
+                else:
+                    temperature = self.current_set
             else:
             else:
-                temperature = self.current_set
-        else:
+                if self.season == Season.heating:
+                    temperature = 27.0
+                elif self.season == Season.cooling:
+                    temperature = 20.0
+                else:
+                    temperature = 25.0
+
             if self.season == Season.heating:
             if self.season == Season.heating:
-                temperature = 27.0
-            elif self.season == Season.cooling:
-                temperature = 20.0
+                temperature = max(20.0, min(30.0, temperature))
             else:
             else:
-                temperature = 25.0
-
-        if self.season == Season.heating:
-            temperature = max(20.0, min(30.0, temperature))
-        else:
-            temperature = max(18.0, min(25.0, temperature))
+                temperature = max(18.0, min(25.0, temperature))
+        except TypeError:
+            raise MissingIOTDataError
 
 
         return temperature
         return temperature
 
 
@@ -159,96 +160,14 @@ class ACATAHSupplyAirTemperatureDefaultController:
         return temperature
         return temperature
 
 
 
 
-async def get_planned(project_id: str, device_id: str) -> float:
-    vav_boxes_params = await fetch_status_params(project_id, device_id)
-    vav_boxes_lit = vav_boxes_params["vav_boxes_list"]
-    async with AsyncClient() as client:
-        platform = DataPlatformService(client, project_id)
-        duoduo = Duoduo(client, project_id)
-
-        current_supply_air_temperature = await platform.get_realtime_supply_air_temperature(device_id)
-        return_air_temperature = await platform.query_realtime_return_air_temperature(device_id)
-
-        hot_water_valve_opening_set_duration = await platform.get_duration(
-            InfoCode.hot_water_valve_opening_set, device_id, 15 * 60
-        )
-        chill_water_valve_opening_set_duration = await platform.get_duration(
-            InfoCode.chill_water_valve_opening_set, device_id, 15 * 60
-        )
-        on_off_set_duration = await platform.get_duration(InfoCode.equip_switch_set, device_id, 20 * 60)
-
-        season = await duoduo.get_season()
-
-        if chill_water_valve_opening_set_duration[-1]["value"] == 0.0:
-            thermal_mode = ThermalMode.heating
-        else:
-            thermal_mode = ThermalMode.cooling
-
-        is_off_to_on = False
-        if on_off_set_duration[-1]["value"] == 1.0:
-            for item in on_off_set_duration[::-1]:
-                if item["value"] == 0.0:
-                    is_off_to_on = True
-                    break
-
-        is_thermal_mode_switched = False
-        if len(set([item["value"] for item in hot_water_valve_opening_set_duration])) > 1:
-            is_thermal_mode_switched = True
-        if len(set([item["value"] for item in chill_water_valve_opening_set_duration])) > 1:
-            is_thermal_mode_switched = True
-
-    controller = ACATAHSupplyAirTemperatureController(
-        vav_boxes_lit,
-        current_supply_air_temperature,
-        return_air_temperature,
-        thermal_mode,
-        is_off_to_on,
-        is_thermal_mode_switched,
-        season,
-    )
-    next_supply_air_temperature_set = controller.build()
-
-    return next_supply_air_temperature_set
-
-
-async def get_default(project_id: str) -> float:
-    async with AsyncClient() as client:
-        weather_service = WeatherService(client)
-        realtime_weather = await weather_service.get_realtime_weather(project_id)
-
-        if realtime_weather.get("text") == "晴":
-            is_clear_day = True
-        else:
-            is_clear_day = False
-
-    controller = ACATAHSupplyAirTemperatureDefaultController(is_clear_day)
-    next_supply_air_temperature_set = controller.build()
-
-    return next_supply_air_temperature_set
-
-
-@logger.catch
-async def get_next_supply_air_temperature_set(project_id: str, device_id: str) -> float:
-    try:
-        new = await get_planned(project_id, device_id)
-    except KeyError and IndexError:
-        new = await get_default(project_id)
-
-    logger.debug(f"next supply air temperature set: {device_id} - {new}")
-
-    return new
-
-
-@logger.catch
-def build_acatah_supply_air_temperature_set(
-        params: ACATAHSupplyAirTempSetRequest,
-) -> float:
+def build_acatah_supply_air_temperature_set(params: ACATAHSupplyAirTempSetRequest) -> float:
     try:
     try:
         vav_list = list()
         vav_list = list()
         for raw_vav in params.vav_list:
         for raw_vav in params.vav_list:
             vav = VAVBox(**raw_vav.dict())
             vav = VAVBox(**raw_vav.dict())
             vav.virtual_target_temperature = raw_vav.virtual_temperature_target
             vav.virtual_target_temperature = raw_vav.virtual_temperature_target
-            vav_list.append(vav)
+            if vav.virtual_target_temperature and vav.virtual_realtime_temperature:
+                vav_list.append(vav)
 
 
         if params.chill_water_valve_opening_set_list[-1] == 0.0:
         if params.chill_water_valve_opening_set_list[-1] == 0.0:
             thermal_mode = ThermalMode.heating
             thermal_mode = ThermalMode.heating

+ 19 - 22
app/controllers/equipment/ahu/switch.py

@@ -1,14 +1,9 @@
 # -*- coding: utf-8 -*-
 # -*- coding: utf-8 -*-
 
 
-from typing import Tuple
-
-from httpx import AsyncClient
-from loguru import logger
-
+from app.api.errors.iot import MissingIOTDataError
 from app.controllers.equipment.switch import Switch, SwitchSet
 from app.controllers.equipment.switch import Switch, SwitchSet
 from app.models.domain.devices import ACATAHSwitchSetRequest
 from app.models.domain.devices import ACATAHSwitchSetRequest
 from app.schemas.equipment import AHU
 from app.schemas.equipment import AHU
-from app.services.platform import DataPlatformService
 
 
 
 
 class AHUSwitch(Switch):
 class AHUSwitch(Switch):
@@ -16,32 +11,34 @@ class AHUSwitch(Switch):
         super(AHUSwitch, self).__init__(equipment)
         super(AHUSwitch, self).__init__(equipment)
 
 
     def break_time_action(self, begin: str, end: str, is_workday: bool) -> SwitchSet:
     def break_time_action(self, begin: str, end: str, is_workday: bool) -> SwitchSet:
-        if self._equip.in_cloud_status:
-            if is_workday:
-                if begin and end:
-                    switch_flag = True
-                    if begin <= end:
-                        if begin <= self._now_time <= end:
-                            switch_flag = False
-                    else:
-                        if not end <= self._now_time <= begin:
-                            switch_flag = False
-
-                    if not switch_flag:
-                        action = SwitchSet.off
+        try:
+            if self._equip.in_cloud_status:
+                if is_workday:
+                    if begin and end:
+                        switch_flag = True
+                        if begin <= end:
+                            if begin <= self._now_time <= end:
+                                switch_flag = False
+                        else:
+                            if not end <= self._now_time <= begin:
+                                switch_flag = False
+
+                        if not switch_flag:
+                            action = SwitchSet.off
+                        else:
+                            action = SwitchSet.hold
                     else:
                     else:
                         action = SwitchSet.hold
                         action = SwitchSet.hold
                 else:
                 else:
                     action = SwitchSet.hold
                     action = SwitchSet.hold
             else:
             else:
                 action = SwitchSet.hold
                 action = SwitchSet.hold
-        else:
-            action = SwitchSet.hold
+        except TypeError:
+            raise MissingIOTDataError
 
 
         return action
         return action
 
 
 
 
-@logger.catch()
 async def build_acatah_switch_set(params: ACATAHSwitchSetRequest) -> SwitchSet:
 async def build_acatah_switch_set(params: ACATAHSwitchSetRequest) -> SwitchSet:
     ahu = AHU(
     ahu = AHU(
         running_status=params.running_status,
         running_status=params.running_status,

+ 25 - 79
app/controllers/equipment/ahu/thermal_mode.py

@@ -1,13 +1,9 @@
-from typing import Dict, List
-
-from httpx import AsyncClient
-from loguru import logger
+from typing import List
 
 
+from app.api.errors.iot import MissingIOTDataError
 from app.models.domain.devices import ACATAHThermalModeSetRequest
 from app.models.domain.devices import ACATAHThermalModeSetRequest
-from app.models.domain.devices import ThermalMode
 from app.schemas.equipment import VAVBox
 from app.schemas.equipment import VAVBox
-from app.services.platform import DataPlatformService, InfoCode
-from app.services.transfer import Duoduo, Season
+from app.services.transfer import Season
 
 
 
 
 def count_vav_box_weight(
 def count_vav_box_weight(
@@ -63,15 +59,18 @@ class ACATAHThermalModeController:
     def build(self) -> str:
     def build(self) -> str:
         weight = 0.0
         weight = 0.0
         for box in self.vav_boxes_list:
         for box in self.vav_boxes_list:
-            weight += count_vav_box_weight(
-                box.virtual_realtime_temperature,
-                box.virtual_target_temperature,
-                box.supply_air_flow_upper_limit,
-                box.supply_air_flow_lower_limit,
-                box.supply_air_flow_set,
-                box.valve_opening,
-                box.supply_air_temperature
-            )
+            try:
+                weight += count_vav_box_weight(
+                    box.virtual_realtime_temperature,
+                    box.virtual_target_temperature,
+                    box.supply_air_flow_upper_limit,
+                    box.supply_air_flow_lower_limit,
+                    box.supply_air_flow_set,
+                    box.valve_opening,
+                    box.supply_air_temperature
+                )
+            except TypeError:
+                raise MissingIOTDataError
 
 
         if weight > 0:
         if weight > 0:
             mode = "cooling"
             mode = "cooling"
@@ -83,72 +82,19 @@ class ACATAHThermalModeController:
         return mode
         return mode
 
 
 
 
-async def fetch_status_params(project_id: str, device_id: str) -> Dict:
-    async with AsyncClient() as client:
-        platform = DataPlatformService(client, project_id)
-        duoduo = Duoduo(client, project_id)
-
-        season = duoduo.get_season()
-        relations = await platform.query_relations(
-            from_id=device_id, graph_id="GtControlEquipNetwork001"
-        )
-        vav_id_list = [item.get("to_id") for item in relations]
-        vav_boxes_list = []
-        for vav_id in vav_id_list:
-            virtual_realtime_temperature = await duoduo.query_device_virtual_data(
-                vav_id, "VirtualRealtimeTemperature"
-            )
-            virtual_temperature_target = await duoduo.query_device_virtual_data(
-                vav_id, "TargetTemperatureSet"
-            )
-            lower_limit_flow, upper_limit_flow = await platform.get_air_flow_limit(
-                vav_id
-            )
-            current_flow_set = await platform.get_realtime_data(
-                InfoCode.supply_air_flow_set, vav_id
-            )
-            valve_opening = await platform.get_realtime_data(
-                InfoCode.valve_opening, vav_id
-            )
-            vav_params = {
-                "id": vav_id,
-                "virtual_realtime_temperature": virtual_realtime_temperature,
-                "virtual_target_temperature": virtual_temperature_target,
-                "supply_air_flow_lower_limit": lower_limit_flow,
-                "supply_air_flow_upper_limit": upper_limit_flow,
-                "supply_air_flow_set": current_flow_set,
-                "valve_opening": valve_opening,
-            }
-            vav = VAVBox(**vav_params)
-            vav_boxes_list.append(vav)
-
-        return {"vav_boxes_list": vav_boxes_list, "season": season}
-
-
-@logger.catch()
-async def get_thermal_mode(project_id: str, device_id: str) -> ThermalMode:
-    prams = await fetch_status_params(project_id, device_id)
-    controller = ACATAHThermalModeController(
-        prams.get("vav_boxes_list"), prams.get("season")
-    )
-    mode = controller.build()
-
-    return ThermalMode(mode)
-
-
-@logger.catch()
 def build_acatah_thermal_mode_set(params: ACATAHThermalModeSetRequest) -> str:
 def build_acatah_thermal_mode_set(params: ACATAHThermalModeSetRequest) -> str:
     vav_list = list()
     vav_list = list()
     for raw_vav in params.vav_list:
     for raw_vav in params.vav_list:
-        vav = VAVBox(
-            virtual_realtime_temperature=raw_vav.virtual_realtime_temperature,
-            virtual_target_temperature=raw_vav.virtual_temperature_target,
-            supply_air_flow_lower_limit=raw_vav.supply_air_flow_lower_limit,
-            supply_air_flow_upper_limit=raw_vav.supply_air_flow_upper_limit,
-            supply_air_flow_set=raw_vav.supply_air_flow_set,
-            valve_opening=raw_vav.valve_opening,
-        )
-        vav_list.append(vav)
+        if raw_vav.virtual_realtime_temperature and raw_vav.virtual_temperature_target:
+            vav = VAVBox(
+                virtual_realtime_temperature=raw_vav.virtual_realtime_temperature,
+                virtual_target_temperature=raw_vav.virtual_temperature_target,
+                supply_air_flow_lower_limit=raw_vav.supply_air_flow_lower_limit,
+                supply_air_flow_upper_limit=raw_vav.supply_air_flow_upper_limit,
+                supply_air_flow_set=raw_vav.supply_air_flow_set,
+                valve_opening=raw_vav.valve_opening,
+            )
+            vav_list.append(vav)
 
 
     controller = ACATAHThermalModeController(vav_list, Season(params.season))
     controller = ACATAHThermalModeController(vav_list, Season(params.season))
     mode = controller.build()
     mode = controller.build()

+ 58 - 154
app/controllers/equipment/fcu/basic.py

@@ -1,23 +1,15 @@
 # -*- coding: utf-8 -*-
 # -*- 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.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.models.domain.feedback import FeedbackValue
 from app.schemas.equipment import AirValveSpeed, FCU
 from app.schemas.equipment import AirValveSpeed, FCU
 from app.schemas.instructions import ACATFCInstructions
 from app.schemas.instructions import ACATFCInstructions
 from app.schemas.space import Space
 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
 from app.utils.math import round_half_up
 
 
 
 
@@ -29,7 +21,7 @@ class FCUController(EquipmentController):
 
 
     async def get_temperature_target(self) -> float:
     async def get_temperature_target(self) -> float:
         target = self._equipment.space.temperature_target
         target = self._equipment.space.temperature_target
-        if not np.isnan(target):
+        if target:
             setting_target = target
             setting_target = target
         else:
         else:
             setting_target = 25.0
             setting_target = 25.0
@@ -41,10 +33,7 @@ class FCUController(EquipmentController):
         temperature_target = self._equipment.space.temperature_target
         temperature_target = self._equipment.space.temperature_target
         if self.season == Season.heating:
         if self.season == Season.heating:
             mode = 2
             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:
                 if temperature_target < self._equipment.space.realtime_temperature:
                     mode = 1
                     mode = 1
         elif self.season == Season.cooling:
         elif self.season == Season.cooling:
@@ -57,11 +46,9 @@ class FCUController(EquipmentController):
 
 
     async def get_air_valve_speed(self):
     async def get_air_valve_speed(self):
         temperature_target = self._equipment.space.temperature_target
         temperature_target = self._equipment.space.temperature_target
-        if temperature_target > 0:
+        if temperature_target:
             if self.season == Season.heating:
             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:
                 if diff >= 1.5:
                     self._equipment.air_valve_speed = AirValveSpeed.high
                     self._equipment.air_valve_speed = AirValveSpeed.high
                 elif diff >= 1.0:
                 elif diff >= 1.0:
@@ -90,10 +77,13 @@ class FCUController(EquipmentController):
             self._equipment.running_status = True
             self._equipment.running_status = True
 
 
     async def run(self):
     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):
     def get_results(self):
         return self._equipment
         return self._equipment
@@ -108,19 +98,13 @@ class FCUControllerV2(EquipmentController):
         self.season = season
         self.season = season
 
 
     def get_mode(self) -> int:
     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
                 mode = 2
             else:
             else:
                 mode = 1
                 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
                 mode = 2
             else:
             else:
                 mode = 1
                 mode = 1
@@ -137,8 +121,8 @@ class FCUControllerV2(EquipmentController):
 
 
     def build_air_valve_speed(self):
     def build_air_valve_speed(self):
         target = self.equipment.space.temperature_target
         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()
                 mode = self.get_mode()
                 if mode == 2:
                 if mode == 2:
                     diff = target - self.equipment.space.realtime_temperature
                     diff = target - self.equipment.space.realtime_temperature
@@ -169,16 +153,19 @@ class FCUControllerV2(EquipmentController):
             self.equipment.running_status = True
             self.equipment.running_status = True
 
 
     def build_temperature_set(self):
     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
             self.equipment.setting_temperature = self.equipment.space.temperature_target
+        else:
+            self.equipment.setting_temperature = 0.0
 
 
     async def run(self):
     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):
     def get_results(self):
         return self.equipment
         return self.equipment
@@ -247,7 +234,7 @@ class ATFC2Controller:
 
 
     def build_speed_set(self) -> Speed:
     def build_speed_set(self) -> Speed:
         speed_controller = SpeedController(self.speed, self.running_status)
         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:
             if self.season == Season.cooling:
                 diff = self.space_realtime - self.space_target
                 diff = self.space_realtime - self.space_target
             elif self.season == Season.heating:
             elif self.season == Season.heating:
@@ -267,23 +254,17 @@ class ATFC2Controller:
                 speed = Speed.high
                 speed = Speed.high
         else:
         else:
             speed = Speed.hold
             speed = Speed.hold
-            if self.space_target < 0.0:
+            if not self.space_target:
                 speed = Speed.off
                 speed = Speed.off
             else:
             else:
                 if self.feedback == FeedbackValue.switch_on:
                 if self.feedback == FeedbackValue.switch_on:
                     speed = Speed.medium
                     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:
                     if self.season == Season.cooling:
                         speed = speed_controller.turn_up()
                         speed = speed_controller.turn_up()
                     elif self.season == Season.heating:
                     elif self.season == Season.heating:
                         speed = speed_controller.turn_down()
                         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:
                     if self.season == Season.cooling:
                         speed = speed_controller.turn_down()
                         speed = speed_controller.turn_down()
                     elif self.season == Season.heating:
                     elif self.season == Season.heating:
@@ -306,9 +287,12 @@ class ATFC2Controller:
         return new_switch_set
         return new_switch_set
 
 
     def run(self) -> dict:
     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 = {
         res = {
             "speed_set": speed,
             "speed_set": speed,
@@ -339,7 +323,7 @@ class ATFC4Controller(ATFC2Controller):
         speed = super().build_speed_set()
         speed = super().build_speed_set()
         if self.season == Season.heating:
         if self.season == Season.heating:
             speed_controller = SpeedController(self.speed, self.running_status)
             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)
                 diff = abs(self.space_realtime - self.space_target)
                 if diff < 0.2:
                 if diff < 0.2:
                     speed = Speed.hold
                     speed = Speed.hold
@@ -350,20 +334,14 @@ class ATFC4Controller(ATFC2Controller):
                 else:
                 else:
                     speed = Speed.high
                     speed = Speed.high
             else:
             else:
-                if self.space_target < 0.0:
+                if not self.space_target:
                     speed = Speed.off
                     speed = Speed.off
                 else:
                 else:
                     if self.feedback == FeedbackValue.switch_on:
                     if self.feedback == FeedbackValue.switch_on:
                         speed = Speed.medium
                         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()
                         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()
                         speed = speed_controller.turn_up()
 
 
         return speed
         return speed
@@ -374,7 +352,7 @@ class ATFC4Controller(ATFC2Controller):
             hot_water_valve_set = "off"
             hot_water_valve_set = "off"
         else:
         else:
             if self.season == Season.heating:
             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:
                     if self.space_realtime - self.space_target >= 0.2:
                         chill_water_valve_set = "on"
                         chill_water_valve_set = "on"
                         hot_water_valve_set = "off"
                         hot_water_valve_set = "off"
@@ -390,16 +368,10 @@ class ATFC4Controller(ATFC2Controller):
                     if self.feedback == FeedbackValue.switch_on:
                     if self.feedback == FeedbackValue.switch_on:
                         chill_water_valve_set = "off"
                         chill_water_valve_set = "off"
                         hot_water_valve_set = "on"
                         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"
                         chill_water_valve_set = "on"
                         hot_water_valve_set = "off"
                         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"
                         chill_water_valve_set = "off"
                         hot_water_valve_set = "on"
                         hot_water_valve_set = "on"
             else:
             else:
@@ -409,11 +381,12 @@ class ATFC4Controller(ATFC2Controller):
         return chill_water_valve_set, hot_water_valve_set
         return chill_water_valve_set, hot_water_valve_set
 
 
     def run(self) -> dict:
     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 = {
         res = {
             "speed_set": speed,
             "speed_set": speed,
@@ -425,65 +398,7 @@ class ATFC4Controller(ATFC2Controller):
         return res
         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(
     space = Space(
         temperature_target=params.space_temperature_target,
         temperature_target=params.space_temperature_target,
         realtime_temperature=params.space_realtime_temperature,
         realtime_temperature=params.space_realtime_temperature,
@@ -505,10 +420,7 @@ async def build_acatfc2_instructions(
     return instructions
     return instructions
 
 
 
 
-@logger.catch()
-async def build_acatfc4_instructions(
-        params: ACATFC4InstructionsRequest,
-) -> ACATFCInstructions:
+async def build_acatfc4_instructions(params: ACATFC4InstructionsRequest) -> ACATFCInstructions:
     space = Space(
     space = Space(
         temperature_target=params.space_temperature_target,
         temperature_target=params.space_temperature_target,
         realtime_temperature=params.space_realtime_temperature,
         realtime_temperature=params.space_realtime_temperature,
@@ -530,14 +442,10 @@ async def build_acatfc4_instructions(
     return instructions
     return instructions
 
 
 
 
-@logger.catch()
 async def build_acatfc2_instructions_v2(params: ACATFC2InstructionsRequest) -> dict:
 async def build_acatfc2_instructions_v2(params: ACATFC2InstructionsRequest) -> dict:
-    space_realtime = (
-        params.space_realtime_temperature if params.space_realtime_temperature else -1
-    )
     controller = ATFC2Controller(
     controller = ATFC2Controller(
         params.space_temperature_target,
         params.space_temperature_target,
-        space_realtime,
+        params.space_realtime_temperature,
         Season(params.season),
         Season(params.season),
         params.feedback,
         params.feedback,
         params.running_status,
         params.running_status,
@@ -548,14 +456,10 @@ async def build_acatfc2_instructions_v2(params: ACATFC2InstructionsRequest) -> d
     return instructions
     return instructions
 
 
 
 
-@logger.catch()
 async def build_acatfc4_instructions_v2(params: ACATFC4InstructionsRequest) -> dict:
 async def build_acatfc4_instructions_v2(params: ACATFC4InstructionsRequest) -> dict:
-    space_realtime = (
-        params.space_realtime_temperature if params.space_realtime_temperature else -1
-    )
     controller = ATFC4Controller(
     controller = ATFC4Controller(
         params.space_temperature_target,
         params.space_temperature_target,
-        space_realtime,
+        params.space_realtime_temperature,
         Season(params.season),
         Season(params.season),
         params.feedback,
         params.feedback,
         params.running_status,
         params.running_status,

+ 5 - 7
app/controllers/equipment/fcu/early_start.py

@@ -2,6 +2,7 @@ from joblib import load
 from loguru import logger
 from loguru import logger
 from sqlalchemy.orm import Session
 from sqlalchemy.orm import Session
 
 
+from app.api.errors.iot import MissingIOTDataError
 from app.core.config import settings
 from app.core.config import settings
 from app.crud.model_path.early_start import model_path_early_start_dtr
 from app.crud.model_path.early_start import model_path_early_start_dtr
 from app.models.domain.devices import ACATFCEarlyStartPredictionRequest
 from app.models.domain.devices import ACATFCEarlyStartPredictionRequest
@@ -41,19 +42,16 @@ class EarlyStartTimeDTRBuilder:
         except (ValueError, IndexError) as e:
         except (ValueError, IndexError) as e:
             logger.debug(e)
             logger.debug(e)
             pre_time = 0
             pre_time = 0
+        except TypeError:
+            raise MissingIOTDataError
 
 
         return pre_time
         return pre_time
 
 
 
 
-@logger.catch()
-async def build_acatfc_early_start_prediction(
-    params: ACATFCEarlyStartPredictionRequest, db: Session
-) -> float:
+async def build_acatfc_early_start_prediction(params: ACATFCEarlyStartPredictionRequest, db: Session) -> float:
     model_path = model_path_early_start_dtr.get_path_by_device(db, params.device_id)
     model_path = model_path_early_start_dtr.get_path_by_device(db, params.device_id)
 
 
     builder = EarlyStartTimeDTRBuilder(model_path, params.season)
     builder = EarlyStartTimeDTRBuilder(model_path, params.season)
-    hour = await builder.get_prediction(
-        params.space_realtime_temperature, params.outdoor_realtime_temperature
-    )
+    hour = await builder.get_prediction(params.space_realtime_temperature, params.outdoor_realtime_temperature)
 
 
     return hour * 60
     return hour * 60

+ 0 - 126
app/controllers/equipment/fcu/q_learning.py

@@ -1,126 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from typing import Dict, Optional
-
-import numpy as np
-from httpx import AsyncClient
-from loguru import logger
-
-from app.controllers.events import q_learning_models
-from app.services.platform import DataPlatformService
-from app.services.transfer import Duoduo, SpaceInfoService
-from app.services.transfer import Season
-
-
-class QLearningCommandBuilder:
-    """
-    Build FCU command by Q learning net.
-    """
-
-    def __init__(self, season: Season):
-        self.season = season
-        if season == Season.cooling:
-            self.model = q_learning_models.get('summer')
-        elif season == Season.heating:
-            self.model = q_learning_models.get('winter')
-        else:
-            self.model = None
-
-    def get_type(self, layer: int) -> str:
-        return self.model[0, layer][0, 0][0][0]
-
-    def get_weight(self, layer: int, idx: int) -> np.ndarray:
-        return self.model[0, layer][0, 0][1][0, idx]
-
-    @staticmethod
-    def linear(input_v: np.ndarray, weight: np.ndarray, bias: Optional[np.ndarray] = None) -> np.ndarray:
-        y = np.dot(weight, input_v)
-        if bias.size > 0:
-            y += bias
-
-        return y
-
-    @staticmethod
-    def relu(x: np.ndarray) -> np.ndarray:
-        return np.maximum(x, 0)
-
-    def predict_speed(self, input_v: np.ndarray) -> int:
-        result = [input_v]
-        for layer in range(self.model.shape[1]):
-            if self.get_type(layer) == 'mlp' or self.get_type(layer) == 'linear':
-                y = self.linear(result[layer], self.get_weight(layer, 0), self.get_weight(layer, 1))
-                result.append(y)
-            elif self.get_type(layer) == 'relu':
-                result.append(self.relu(result[layer]))
-
-        speed = np.argmax(result[-1])
-
-        return int(speed)
-
-    async def get_command(self, current_temperature: float, pre_temperature: float, actual_target: float) -> Dict:
-        input_value = np.array([
-            [(current_temperature - actual_target) / 5],
-            [(current_temperature - pre_temperature) / 5]
-        ])
-        speed = self.predict_speed(input_value)
-        if np.isnan(current_temperature) or np.isnan(pre_temperature):
-            speed = 2
-        if np.isnan(actual_target):
-            speed = 0
-
-        if speed == 0:
-            on_off = 0
-            water_on_off = 0
-        else:
-            on_off = 1
-            water_on_off = 1
-
-        if self.season == Season.cooling:
-            season = 1
-        elif self.season == Season.heating:
-            season = 2
-        else:
-            season = 0
-
-        command = {
-            'onOff': on_off,
-            'mode': season,
-            'speed': int(speed),
-            'temperature': actual_target if not np.isnan(actual_target) else None,
-            'water': water_on_off
-        }
-        return command
-
-
-@logger.catch()
-async def get_fcu_q_learning_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 not spaces:
-            logger.error(f'FCU {equipment_id} does not have space')
-            return {}
-        else:
-            if len(spaces) > 1:
-                logger.error(f'FCU {equipment_id} control more than one spaces!')
-            transfer = SpaceInfoService(client, project_id, spaces[0].get('id'))
-            season = await duo_duo.get_season()
-            current_target = await transfer.get_current_temperature_target()
-            realtime_temperature = await platform.get_realtime_temperature(spaces[0].get('id'))
-            past_temperature = await platform.get_past_temperature(spaces[0].get('id'), 15 * 60)
-
-    logger.debug(
-        f'{spaces[0]["id"]} - {equipment_id} - '
-        f'realtime Tdb: {realtime_temperature} - '
-        f'pre Tdb: {past_temperature} - '
-        f'target: {current_target}'
-    )
-    if season == Season.transition:
-        command = {}
-    else:
-        builder = QLearningCommandBuilder(season)
-        command = await builder.get_command(realtime_temperature, past_temperature, current_target)
-
-    return command

+ 7 - 48
app/controllers/equipment/pau/freq_set.py

@@ -2,8 +2,8 @@
 
 
 from typing import List, Tuple
 from typing import List, Tuple
 
 
-from loguru import logger
 import numpy as np
 import numpy as np
+from loguru import logger
 
 
 from app.models.domain.devices import ACATFUFreqSetRequest
 from app.models.domain.devices import ACATFUFreqSetRequest
 from app.schemas.season import Season
 from app.schemas.season import Season
@@ -13,49 +13,14 @@ from app.utils.helpers import is_off_to_on
 
 
 class ACATFUFanFreqController:
 class ACATFUFanFreqController:
     """
     """
-    Fan freq setting logic for zhonghai.
-    """
-
-    def __init__(self, current_freq: float, hot_rate: float, cold_rate: float):
-        self.current_freq = current_freq
-        self.hot_rate = hot_rate
-        self.cold_rate = cold_rate
-
-    def get_next_set(self) -> float:
-        try:
-            cold_hot_ratio = self.cold_rate / self.hot_rate
-        except ZeroDivisionError:
-            cold_hot_ratio = 99
-
-        if cold_hot_ratio < 0.5:
-            diff = 3
-        elif cold_hot_ratio < 0.9:
-            diff = 2
-        elif cold_hot_ratio < 1.1:
-            diff = 0
-        elif cold_hot_ratio < 1.5:
-            diff = -2
-        elif cold_hot_ratio >= 1.5:
-            diff = -3
-        else:  # If cold hot rate is NAN.
-            diff = 0
-
-        next_freq_set = self.current_freq + diff
-        next_freq_set = max(30.0, min(45.0, next_freq_set))
-
-        return next_freq_set
-
-
-class ACATFUFanFreqControllerV2:
-    """
     Logic writen by Wuxu.
     Logic writen by Wuxu.
     """
     """
 
 
     def __init__(
     def __init__(
-        self,
-        freq: float,
-        fresh_air_temperature: float,
-        season: Season,
+            self,
+            freq: float,
+            fresh_air_temperature: float,
+            season: Season,
     ) -> None:
     ) -> None:
         self._freq = freq
         self._freq = freq
         self._fresh_air_temperature = fresh_air_temperature
         self._fresh_air_temperature = fresh_air_temperature
@@ -72,9 +37,7 @@ class ACATFUFanFreqControllerV2:
 
 
         return next_freq_set
         return next_freq_set
 
 
-    def get_transition_logic(
-        self, spaces_params: List[SpaceATFU], on_flag: bool
-    ) -> float:
+    def get_transition_logic(self, spaces_params: List[SpaceATFU], on_flag: bool) -> float:
         temp_avg, co2_avg = self.get_avg(spaces_params)
         temp_avg, co2_avg = self.get_avg(spaces_params)
         if on_flag:
         if on_flag:
             if self._fresh_air_temperature <= 16.0:
             if self._fresh_air_temperature <= 16.0:
@@ -210,11 +173,7 @@ class ACATFUFanFreqControllerV2:
 
 
 @logger.catch()
 @logger.catch()
 async def build_acatfu_freq_set(params: ACATFUFreqSetRequest) -> float:
 async def build_acatfu_freq_set(params: ACATFUFreqSetRequest) -> float:
-    controller = ACATFUFanFreqControllerV2(
-        params.freq,
-        params.fresh_air_temperature,
-        params.season,
-    )
+    controller = ACATFUFanFreqController(params.freq, params.fresh_air_temperature, params.season)
     on_flag = is_off_to_on(params.running_status_list)
     on_flag = is_off_to_on(params.running_status_list)
     spaces = [SpaceATFU(**sp.dict()) for sp in params.spaces]
     spaces = [SpaceATFU(**sp.dict()) for sp in params.spaces]
     freq_set = controller.get_next_set(spaces, on_flag)
     freq_set = controller.get_next_set(spaces, on_flag)

+ 22 - 55
app/controllers/equipment/switch.py

@@ -1,15 +1,12 @@
 # -*- coding: utf-8 -*-
 # -*- coding: utf-8 -*-
 
 
 from enum import Enum
 from enum import Enum
-from typing import Dict, Tuple
 
 
 import arrow
 import arrow
-from httpx import AsyncClient
 
 
 from app.schemas.equipment import BaseEquipment
 from app.schemas.equipment import BaseEquipment
-from app.services.platform import DataPlatformService, InfoCode
-from app.services.transfer import Duoduo
 from app.utils.date import get_time_str, TIME_FMT
 from app.utils.date import get_time_str, TIME_FMT
+from app.api.errors.iot import MissingIOTDataError
 
 
 
 
 class SwitchSet(str, Enum):
 class SwitchSet(str, Enum):
@@ -25,61 +22,31 @@ class Switch:
         self._now_time = arrow.get(get_time_str(), TIME_FMT).time().strftime("%H%M%S")
         self._now_time = arrow.get(get_time_str(), TIME_FMT).time().strftime("%H%M%S")
 
 
     async def build_next_action(self, is_workday: bool) -> SwitchSet:
     async def build_next_action(self, is_workday: bool) -> SwitchSet:
-        if self._equip.in_cloud_status:
-            if is_workday:
-                if self._equip.on_time <= self._equip.off_time:
-                    if self._equip.on_time <= self._now_time <= self._equip.off_time:
-                        switch_flag = True
+        try:
+            if self._equip.in_cloud_status:
+                if is_workday:
+                    if self._equip.on_time <= self._equip.off_time:
+                        if self._equip.on_time <= self._now_time <= self._equip.off_time:
+                            switch_flag = True
+                        else:
+                            switch_flag = False
                     else:
                     else:
-                        switch_flag = False
-                else:
-                    if self._equip.off_time <= self._now_time <= self._equip.on_time:
-                        switch_flag = False
+                        if self._equip.off_time <= self._now_time <= self._equip.on_time:
+                            switch_flag = False
+                        else:
+                            switch_flag = True
+
+                    if switch_flag and not self._equip.running_status:
+                        action = SwitchSet.on
+                    elif not switch_flag and self._equip.running_status:
+                        action = SwitchSet.off
                     else:
                     else:
-                        switch_flag = True
-
-                if switch_flag and not self._equip.running_status:
-                    action = SwitchSet.on
-                elif not switch_flag and self._equip.running_status:
-                    action = SwitchSet.off
+                        action = SwitchSet.hold
                 else:
                 else:
                     action = SwitchSet.hold
                     action = SwitchSet.hold
             else:
             else:
-                action = SwitchSet.hold
-        else:
-            action = SwitchSet.off
+                action = SwitchSet.off
+        except TypeError:
+            raise MissingIOTDataError
 
 
         return action
         return action
-
-
-async def fetch_data(project_id: str, equipment_id: str) -> Tuple[Dict, Dict]:
-    async with AsyncClient() as client:
-        platform = DataPlatformService(client, project_id)
-        duo_duo = Duoduo(client, project_id)
-
-        day_type = await duo_duo.get_day_type()
-        running_status = await platform.get_realtime_running_status(equipment_id)
-        cloud_status = await platform.get_cloud_status(equipment_id)
-        on_time, off_time = await platform.get_schedule(equipment_id)
-
-    equip_params = {
-        "id": equipment_id,
-        "running_status": running_status,
-        "in_cloud_status": True if cloud_status == 1.0 else False,
-        "on_time": on_time,
-        "off_time": off_time,
-    }
-
-    return equip_params, day_type
-
-
-async def send_switch_command(project_id: str, equipment_id: str, action: str) -> None:
-    async with AsyncClient() as client:
-        platform = DataPlatformService(client, project_id)
-
-        if action == "on":
-            await platform.set_code_value(equipment_id, InfoCode.equip_switch_set, 1.0)
-        elif action == "off":
-            await platform.set_code_value(equipment_id, InfoCode.equip_switch_set, 0.0)
-        else:
-            pass

+ 1 - 1
app/controllers/equipment/vav.py

@@ -422,7 +422,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,
 ) -> dict:
 ) -> dict:
     # Control logic for Jiaming.
     # Control logic for Jiaming.

+ 4 - 8
app/controllers/equipment/vrf/basic.py

@@ -3,10 +3,9 @@ from typing import Dict, Tuple
 
 
 import arrow
 import arrow
 import numpy as np
 import numpy as np
-from loguru import logger
 from sqlalchemy.orm import Session
 from sqlalchemy.orm import Session
 
 
-from app.api.errors.iot import MissingIOTDataError, missing_iot_data_handler
+from app.api.errors.iot import MissingIOTDataError
 from app.controllers.equipment.controller import EquipmentController
 from app.controllers.equipment.controller import EquipmentController
 from app.crud.device.device import device
 from app.crud.device.device import device
 from app.crud.device.status_timestamp import blowy_feedback_time, high_speed_time
 from app.crud.device.status_timestamp import blowy_feedback_time, high_speed_time
@@ -143,7 +142,7 @@ class VRFController(EquipmentController):
         return new_temperature_set
         return new_temperature_set
 
 
     def get_speed_set(self) -> str:
     def get_speed_set(self) -> str:
-        if self.device.work_mode == 4.0 or self.device.work_mode == 8.0:
+        if self.device.work_mode == VRFMode.ventilation:
             if self.target is None:
             if self.target is None:
                 new_speed = "hold"
                 new_speed = "hold"
             else:
             else:
@@ -169,7 +168,7 @@ class VRFController(EquipmentController):
                             new_speed = "hold"
                             new_speed = "hold"
                 else:
                 else:
                     new_speed = "M"
                     new_speed = "M"
-        elif self.device.work_mode == 1.0 or self.device.work_mode == 6.0:
+        elif self.device.work_mode == VRFMode.cooling:
             new_speed = "hold"
             new_speed = "hold"
             if self.target is None:
             if self.target is None:
                 return new_speed
                 return new_speed
@@ -202,7 +201,7 @@ class VRFController(EquipmentController):
                     new_speed = "LL"
                     new_speed = "LL"
                 else:
                 else:
                     new_speed = "LL"
                     new_speed = "LL"
-        elif self.device.work_mode == 2.0 or self.device.work_mode == 7.0:
+        elif self.device.work_mode == VRFMode.heating:
             new_speed = "hold"
             new_speed = "hold"
             if self.target is None:
             if self.target is None:
                 return new_speed
                 return new_speed
@@ -276,7 +275,6 @@ class VRFController(EquipmentController):
             self.get_speed_set()
             self.get_speed_set()
             self.get_temperature_set()
             self.get_temperature_set()
         except TypeError:
         except TypeError:
-            logger.debug("missing data error")
             raise MissingIOTDataError
             raise MissingIOTDataError
 
 
     def get_results(self):
     def get_results(self):
@@ -312,8 +310,6 @@ async def query_status_time(db: Session, device_id: str) -> Tuple[datetime, date
     return feedback_time, high_time
     return feedback_time, high_time
 
 
 
 
-@logger.catch
-@missing_iot_data_handler
 async def build_acatvi_instructions(params: ACATVIInstructionsRequest) -> Dict:
 async def build_acatvi_instructions(params: ACATVIInstructionsRequest) -> Dict:
     vrf = VRF(
     vrf = VRF(
         return_air_temp=params.return_air_temperature,
         return_air_temp=params.return_air_temperature,

+ 4 - 4
app/core/config.py

@@ -42,10 +42,10 @@ class Settings(BaseSettings):
     REDIS_DB: int
     REDIS_DB: int
     REDIS_PASSWORD: str
     REDIS_PASSWORD: str
 
 
-    MILVUS_HOST: str
-    MILVUS_PORT: str
-    METRIC_TYPE: str
-    VECTOR_DIMENSION: int
+    MILVUS_HOST: Optional[str] = None
+    MILVUS_PORT: Optional[str] = None
+    METRIC_TYPE: Optional[str] = None
+    VECTOR_DIMENSION: Optional[int] = None
 
 
     POSTGRES_SERVER: str
     POSTGRES_SERVER: str
     POSTGRES_USER: str
     POSTGRES_USER: str

+ 5 - 14
app/main.py

@@ -1,12 +1,11 @@
 # -*- coding: utf-8 -*-
 # -*- coding: utf-8 -*-
 
 
 import logging
 import logging
-from pathlib import Path
 
 
 import uvicorn
 import uvicorn
 from fastapi import FastAPI
 from fastapi import FastAPI
-from loguru import logger
 
 
+from app.api.errors.iot import MissingIOTDataError, missing_data_exception_handler
 from app.api.routers import (
 from app.api.routers import (
     algorithms,
     algorithms,
     targets,
     targets,
@@ -25,12 +24,6 @@ from app.db.session import Base, engine
 Base.metadata.create_all(bind=engine)
 Base.metadata.create_all(bind=engine)
 
 
 logging.getLogger().handlers = [InterceptHandler()]
 logging.getLogger().handlers = [InterceptHandler()]
-# logger.add(
-#     Path(settings.LOGS_DIR, "env_fastapi.log"),
-#     level="INFO",
-#     rotation="00:00",
-#     encoding="utf-8",
-# )
 
 
 
 
 def get_application() -> FastAPI:
 def get_application() -> FastAPI:
@@ -41,16 +34,14 @@ def get_application() -> FastAPI:
     application.include_router(algorithms.router, prefix="/algo", tags=["Algorithms"])
     application.include_router(algorithms.router, prefix="/algo", tags=["Algorithms"])
     application.include_router(bluetooth.router, prefix="/bluetooth", tags=["BLE"])
     application.include_router(bluetooth.router, prefix="/bluetooth", tags=["BLE"])
     application.include_router(devices.router, prefix="/devices", tags=["Devices"])
     application.include_router(devices.router, prefix="/devices", tags=["Devices"])
-    application.include_router(
-        early_start.router, prefix="/model-path", tags=["Model Path"]
-    )
+    application.include_router(early_start.router, prefix="/model-path", tags=["Model Path"])
     application.include_router(nlp.router, prefix="/nlp-service", tags=["NLP"])
     application.include_router(nlp.router, prefix="/nlp-service", tags=["NLP"])
-    application.include_router(
-        positioning.router, prefix="/positioning-service", tags=["Positioning Service"]
-    )
+    application.include_router(positioning.router, prefix="/positioning-service", tags=["Positioning Service"])
     application.include_router(space.router, prefix="/room", tags=["Spaces"])
     application.include_router(space.router, prefix="/room", tags=["Spaces"])
     application.include_router(targets.router, prefix="/target", tags=["Targets"])
     application.include_router(targets.router, prefix="/target", tags=["Targets"])
 
 
+    application.add_exception_handler(MissingIOTDataError, missing_data_exception_handler)
+
     return application
     return application
 
 
 
 

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

@@ -23,23 +23,11 @@ class Speed(str, Enum):
     hold = "hold"
     hold = "hold"
 
 
 
 
-class DevicesInstructionsBaseResponse(BaseModel):
-    project_id: str = Field(None, alias="projectId")
-    device_id: str = Field(None, alias="equipId")
-    output: Dict
-
-
-class DevicesEarlyStartTime(BaseModel):
-    project_id: str = Field(None, alias="projectId")
-    space_id: str = Field(None, alias="spaceId")
-    minutes: float
-
-
 class ACATVIInstructionsRequest(BaseModel):
 class ACATVIInstructionsRequest(BaseModel):
     device_id: str
     device_id: str
     return_air_temperature: Optional[float]
     return_air_temperature: Optional[float]
     running_status: Optional[bool]
     running_status: Optional[bool]
-    work_mode: VRFMode
+    work_mode: Optional[VRFMode]
     current_speed: Optional[str]
     current_speed: Optional[str]
     current_temperature_set: Optional[float]
     current_temperature_set: Optional[float]
     space_temperature_target: Optional[float]
     space_temperature_target: Optional[float]
@@ -49,10 +37,6 @@ class ACATVIInstructionsRequest(BaseModel):
     off_time: Optional[str]
     off_time: Optional[str]
 
 
 
 
-class ACATVIInstructionsTemporaryResponse(BaseModel):
-    output: Dict
-
-
 class ACATVIInstructionsResponse(BaseModel):
 class ACATVIInstructionsResponse(BaseModel):
     switch_set: Optional[str]
     switch_set: Optional[str]
     speed_set: Optional[str]
     speed_set: Optional[str]

+ 14 - 14
app/schemas/equipment.py

@@ -25,11 +25,11 @@ class VRFMode(str, Enum):
 
 
 class BaseEquipment(BaseModel):
 class BaseEquipment(BaseModel):
     id: Optional[str]
     id: Optional[str]
-    running_status: Optional[bool] = False
+    running_status: Optional[bool]
     in_cloud_status: Optional[bool]
     in_cloud_status: Optional[bool]
     on_time: Optional[str]
     on_time: Optional[str]
     off_time: Optional[str]
     off_time: Optional[str]
-    equip_switch_set: Optional[bool] = False
+    equip_switch_set: Optional[bool]
 
 
 
 
 class FCU(BaseEquipment):
 class FCU(BaseEquipment):
@@ -38,10 +38,10 @@ class FCU(BaseEquipment):
     air_valve_speed_set: Optional[AirValveSpeed] = AirValveSpeed.off
     air_valve_speed_set: Optional[AirValveSpeed] = AirValveSpeed.off
     recommended_speed: Optional[AirValveSpeed] = AirValveSpeed.off
     recommended_speed: Optional[AirValveSpeed] = AirValveSpeed.off
     space: Optional[Space]
     space: Optional[Space]
-    setting_temperature: Optional[float] = 0.0
-    supply_air_temperature: Optional[float] = 0.0
-    water_out_temperature: Optional[float] = 0.0
-    water_in_temperature: Optional[float] = 0.0
+    setting_temperature: Optional[float]
+    supply_air_temperature: Optional[float]
+    water_out_temperature: Optional[float]
+    water_in_temperature: Optional[float]
     speed_limit: Optional[AirValveSpeed] = AirValveSpeed.high
     speed_limit: Optional[AirValveSpeed] = AirValveSpeed.high
 
 
 
 
@@ -60,14 +60,14 @@ class VAVBox(BaseEquipment):
 
 
 
 
 class AHU(BaseEquipment):
 class AHU(BaseEquipment):
-    supply_air_temperature: Optional[float] = np.NAN
-    supply_air_temperature_set: Optional[float] = np.NAN
-    return_air_temperature: Optional[float] = np.NAN
-    return_air_temperature_set: Optional[float] = np.NAN
-    freq: Optional[float] = np.NAN
-    freq_set: Optional[float] = np.NAN
-    fan_freq_upper_limit_set: Optional[float] = np.NAN
-    fan_freq_lower_limit_set: Optional[float] = np.NAN
+    supply_air_temperature: Optional[float]
+    supply_air_temperature_set: Optional[float]
+    return_air_temperature: Optional[float]
+    return_air_temperature_set: Optional[float]
+    freq: Optional[float]
+    freq_set: Optional[float]
+    fan_freq_upper_limit_set: Optional[float]
+    fan_freq_lower_limit_set: Optional[float]
 
 
 
 
 class VentilationFan(BaseEquipment):
 class VentilationFan(BaseEquipment):

+ 4 - 12
app/schemas/space.py

@@ -3,20 +3,12 @@
 from typing import List, Optional
 from typing import List, Optional
 
 
 import numpy as np
 import numpy as np
-from pydantic import BaseModel as PydanticBaseModel, validator
-
-
-class BaseModel(PydanticBaseModel):
-    @validator("*")
-    def change_to_nan(cls, v):
-        if v == -999.9:
-            v = np.NAN
-        return v
+from pydantic import BaseModel
 
 
 
 
 class SpaceBase(BaseModel):
 class SpaceBase(BaseModel):
     id: Optional[str]
     id: Optional[str]
-    realtime_temperature: float = np.NAN
+    realtime_temperature: Optional[float]
 
 
 
 
 class Space(SpaceBase):
 class Space(SpaceBase):
@@ -33,8 +25,8 @@ class SpaceATVA(Space):
 
 
 
 
 class SpaceATAH(Space):
 class SpaceATAH(Space):
-    ahu_default_weight: Optional[float] = np.NAN
-    ahu_temporary_weight: Optional[float] = np.NAN
+    ahu_default_weight: Optional[float]
+    ahu_temporary_weight: Optional[float]
     ahu_temporary_update_time: Optional[str] = ""
     ahu_temporary_update_time: Optional[str] = ""