Browse Source

stand api response job

highing666 2 years ago
parent
commit
ecb286e77f

+ 0 - 0
app/api/errors/__init__.py


+ 20 - 0
app/api/errors/iot.py

@@ -0,0 +1,20 @@
+from functools import wraps
+
+from fastapi import HTTPException
+
+
+class MissingIOTDataError(Exception):
+    def __init__(self):
+        super().__init__(f"Missing IOT data error.")
+
+
+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

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

@@ -194,7 +194,7 @@ async def get_acatfc_early_start_prediction(
 async def get_acatvi_instructions(
         params: domain_devices.ACATVIInstructionsRequest, db: Session = Depends(get_db)
 ):
-    instructions = await build_acatvi_instructions(params, db)
+    instructions = await build_acatvi_instructions(params)
 
     logger.info(params)
     logger.info(f"{params.device_id} - {instructions}")
@@ -274,7 +274,7 @@ async def get_acatfc2_instruction_v2(params: domain_devices.ACATFC2InstructionsR
     "/instructions/acatfc4/v2",
     response_model=domain_devices.ACATFC4InstructionsResponse,
 )
-async def get_acatfc4_instrutions_v2(params: domain_devices.ACATFC4InstructionsRequest):
+async def get_acatfc4_instructions_v2(params: domain_devices.ACATFC4InstructionsRequest):
     instructions = await build_acatfc4_instructions_v2(params)
 
     logger.info(params)

+ 2 - 1
app/controllers/equipment/pau/freq_set.py

@@ -216,6 +216,7 @@ async def build_acatfu_freq_set(params: ACATFUFreqSetRequest) -> float:
         params.season,
     )
     on_flag = is_off_to_on(params.running_status_list)
-    freq_set = controller.get_next_set(params.spaces, on_flag)
+    spaces = [SpaceATFU(**sp.dict()) for sp in params.spaces]
+    freq_set = controller.get_next_set(spaces, on_flag)
 
     return freq_set

+ 84 - 301
app/controllers/equipment/vrf/basic.py

@@ -1,141 +1,37 @@
 from datetime import datetime
-from typing import Dict, Optional, Tuple
+from typing import Dict, Tuple
 
 import arrow
 import numpy as np
 from loguru import logger
 from sqlalchemy.orm import Session
-from sqlalchemy.exc import SQLAlchemyError
 
+from app.api.errors.iot import MissingIOTDataError, missing_iot_data_handler
 from app.controllers.equipment.controller import EquipmentController
 from app.crud.device.device import device
 from app.crud.device.status_timestamp import blowy_feedback_time, high_speed_time
 from app.models.domain.devices import ACATVIInstructionsRequest
 from app.models.domain.feedback import FeedbackValue
 from app.schemas.device.device import DeviceCreate
-from app.schemas.equipment import VRF
-from app.schemas.season import Season
-from app.schemas.device.status_timestamp import (
-    BlowyFeedbackTimeCreate,
-    BlowyFeedbackTimeUpdate,
-    HighSpeedTimeCreate,
-    HighSpeedTimeUpdate,
-)
+from app.schemas.device.status_timestamp import BlowyFeedbackTimeCreate, HighSpeedTimeCreate
+from app.schemas.equipment import VRF, VRFMode
 from app.utils.math import round_half_up
 
 
 class VRFController(EquipmentController):
-    def __init__(self, device: VRF, target: float, realtime: float):
+    def __init__(
+            self,
+            vrf: VRF,
+            target: float,
+            realtime: float,
+            feedback: FeedbackValue,
+            on_time: str,
+            off_time: str,
+    ):
         super(VRFController, self).__init__()
-        self.device = device
+        self.device = vrf
         self.target = target
         self.realtime = realtime
-
-    def get_switch_set(self) -> str:
-        if np.isnan(self.target):
-            if self.device.running_status:
-                switch_set = "off"
-            else:
-                switch_set = "hold"
-        else:
-            if self.device.running_status:
-                switch_set = "hold"
-            else:
-                switch_set = "on"
-
-        self.device.equip_switch_set = switch_set
-
-        return switch_set
-
-    def get_mode_set(self) -> str:
-        if self.target > self.realtime:
-            mode_set = "cooling"
-        else:
-            mode_set = "cooling"
-
-        self.device.mode_set = mode_set
-
-        return mode_set
-
-    def get_temperature_set(self) -> float:
-        if self.realtime >= 24.0:
-            diff = self.device.return_air_temp - self.realtime
-            if diff > 0:
-                new_temperature_set = self.target + diff
-            elif diff <= 0:
-                new_temperature_set = self.target
-            else:
-                if np.isnan(self.device.current_temperature_set):
-                    new_temperature_set = self.realtime
-                else:
-                    new_temperature_set = self.device.current_temperature_set
-        elif self.realtime <= 22.0:
-            new_temperature_set = 28.0
-        else:
-            if np.isnan(self.device.current_temperature_set):
-                new_temperature_set = 25.0
-            else:
-                new_temperature_set = self.device.current_temperature_set
-
-        new_temperature_set = round_half_up(new_temperature_set)
-        self.device.temperature_set = new_temperature_set
-
-        return self.device.temperature_set
-
-    def get_speed_set(self) -> str:
-        if self.realtime >= 24.0:
-            speed = "M"
-        elif self.realtime <= 22.0:
-            speed = "LL"
-        elif self.device.return_air_temp - self.target >= 3.0:
-            speed = "HH"
-        elif self.device.return_air_temp - self.target >= 1.0:
-            speed = "M"
-        else:
-            if self.device.speed == "missing":
-                speed = "M"
-            else:
-                speed = self.device.speed
-
-        self.device.speed_set = speed
-
-        return speed
-
-    async def run(self):
-        if self.get_switch_set() == "on":
-            self.get_speed_set()
-            self.get_mode_set()
-            self.get_temperature_set()
-
-            if self.device.temperature_set == self.device.current_temperature_set:
-                self.device.temperature_set = 0.0
-
-            if self.device.speed_set == self.device.speed:
-                self.device.speed_set = "hold"
-                self.device.equip_switch_set = "hold"
-
-            if not self.device.running_status:
-                self.device.equip_switch_set = "on"
-                self.get_speed_set()
-        else:
-            if not self.device.running_status:
-                self.device.equip_switch_set = "hold"
-
-    def get_results(self):
-        return self.device
-
-
-class VRFController1(VRFController):
-    def __init__(
-        self,
-        device: VRF,
-        target: float,
-        realtime: float,
-        feedback: FeedbackValue,
-        on_time: str,
-        off_time: str,
-    ):
-        super(VRFController1, self).__init__(device, target, realtime)
         self.feedback = feedback
         self.on_time = on_time
         self.off_time = off_time
@@ -175,105 +71,65 @@ class VRFController1(VRFController):
         return switch_set
 
     def get_temperature_set(self) -> float:
-        if self.device.work_mode == 4.0 or self.device.work_mode == 8.0:
-            # if self.season == Season.transition:
+        if self.device.work_mode == VRFMode.ventilation:
             new_temperature_set = np.NAN
-        elif self.device.work_mode == 1.0 or self.device.work_mode == 6.0:
-            # elif self.season == Season.cooling:
+        elif self.device.work_mode == VRFMode.cooling:
             new_temperature_set = np.NAN
-            if np.isnan(self.target):
+            if self.target is None:
                 return new_temperature_set
 
             # Default temperature set.
             if not self.device.running_status:
                 new_temperature_set = 26.0
 
-            # lower limit.
-            # if self.realtime <= 22.0:
-            #     new_temperature_set = 28.0
-
-            # recovery
-            # if self.device.temperature_set == 28.0 and self.realtime > 25.0:
-            #     new_temperature_set = self.target
-
             # feedback
             if self.feedback.value != "null" and self.device.current_temperature_set:
                 if (
-                    self.feedback == FeedbackValue.a_little_cold
-                    or self.feedback == FeedbackValue.so_cold
+                        self.feedback == FeedbackValue.a_little_cold
+                        or self.feedback == FeedbackValue.so_cold
                 ):
                     if self.feedback == FeedbackValue.so_cold:
+                        logger.debug("so_cold")
                         if self.device.speed == "LL":
-                            new_temperature_set = (
-                                self.device.current_temperature_set + 2.0
-                            )
+                            new_temperature_set = self.device.current_temperature_set + 2.0
                         else:
-                            new_temperature_set = (
-                                self.device.current_temperature_set + 1.0
-                            )
+                            new_temperature_set = self.device.current_temperature_set + 1.0
                     else:
                         new_temperature_set = self.device.current_temperature_set + 1.0
-                elif (
-                    self.feedback == FeedbackValue.a_little_hot
-                    or self.feedback == FeedbackValue.so_hot
-                ):
-                    if (
-                        self.feedback == FeedbackValue.so_hot
-                        and self.device.speed == "HH"
-                    ):
+                elif self.feedback == FeedbackValue.a_little_hot or self.feedback == FeedbackValue.so_hot:
+                    if self.feedback == FeedbackValue.so_hot and self.device.speed == "HH":
                         if self.device.speed == "HH":
-                            new_temperature_set = (
-                                self.device.current_temperature_set - 2.0
-                            )
+                            new_temperature_set = self.device.current_temperature_set - 2.0
                         else:
-                            new_temperature_set = (
-                                self.device.current_temperature_set - 1.0
-                            )
+                            new_temperature_set = self.device.current_temperature_set - 1.0
                     else:
                         new_temperature_set = self.device.current_temperature_set - 1.0
 
             if not np.isnan(new_temperature_set):
                 new_temperature_set = max(24.0, min(28.0, new_temperature_set))
-        elif self.device.work_mode == 2.0 or self.device.work_mode == 7.0:
+        elif self.device.work_mode == VRFMode.heating:
             new_temperature_set = np.NAN
-            if np.isnan(self.target):
+            if self.target is None:
                 return new_temperature_set
 
             if not self.device.running_status:
                 new_temperature_set = 24.0
 
-            # if self.realtime >= 27.0:
-            #     new_temperature_set = 18.0
-
             if self.feedback.value != "null" and self.device.current_temperature_set:
-                if (
-                    self.feedback == FeedbackValue.a_little_cold
-                    or self.feedback == FeedbackValue.so_cold
-                ):
+                if self.feedback == FeedbackValue.a_little_cold or self.feedback == FeedbackValue.so_cold:
                     if self.feedback == FeedbackValue.so_cold:
                         if self.device.speed == "M":
-                            new_temperature_set = (
-                                self.device.current_temperature_set + 1.0
-                            )
+                            new_temperature_set = self.device.current_temperature_set + 1.0
                         else:
-                            new_temperature_set = (
-                                self.device.current_temperature_set + 2.0
-                            )
+                            new_temperature_set = self.device.current_temperature_set + 2.0
                     else:
                         new_temperature_set = self.device.current_temperature_set + 1.0
-                elif (
-                    self.feedback == FeedbackValue.a_little_hot
-                    or self.feedback == FeedbackValue.so_hot
-                ):
+                elif self.feedback == FeedbackValue.a_little_hot or self.feedback == FeedbackValue.so_hot:
                     if self.feedback == FeedbackValue.so_hot:
                         if self.device.speed == "M":
-                            new_temperature_set = (
-                                self.device.current_temperature_set - 1.0
-                            )
+                            new_temperature_set = self.device.current_temperature_set - 1.0
                         else:
-                            new_temperature_set = (
-                                self.device.current_temperature_set - 2.0
-                            )
+                            new_temperature_set = self.device.current_temperature_set - 2.0
                     else:
                         new_temperature_set = self.device.current_temperature_set - 1.0
 
@@ -289,16 +145,15 @@ class VRFController1(VRFController):
 
     def get_speed_set(self) -> str:
         if self.device.work_mode == 4.0 or self.device.work_mode == 8.0:
-            # if self.season == Season.transition:
-            if np.isnan(self.target):
+            if self.target is None:
                 new_speed = "hold"
             else:
                 if self.device.running_status:
                     new_speed = "hold"
                     if (
-                        self.feedback == FeedbackValue.noisy_or_blowy
-                        or self.feedback == FeedbackValue.a_little_cold
-                        or self.feedback == FeedbackValue.so_cold
+                            self.feedback == FeedbackValue.noisy_or_blowy
+                            or self.feedback == FeedbackValue.a_little_cold
+                            or self.feedback == FeedbackValue.so_cold
                     ):
                         if self.device.speed == "HH":
                             new_speed = "M"
@@ -306,10 +161,7 @@ class VRFController1(VRFController):
                             new_speed = "LL"
                         else:
                             new_speed = "hold"
-                    elif (
-                        self.feedback == FeedbackValue.a_little_hot
-                        or self.feedback == FeedbackValue.so_hot
-                    ):
+                    elif self.feedback == FeedbackValue.a_little_hot or self.feedback == FeedbackValue.so_hot:
                         if self.device.speed == "LL":
                             new_speed = "M"
                         elif self.device.speed == "M":
@@ -319,9 +171,8 @@ class VRFController1(VRFController):
                 else:
                     new_speed = "M"
         elif self.device.work_mode == 1.0 or self.device.work_mode == 6.0:
-            # elif self.season == Season.cooling:
             new_speed = "hold"
-            if np.isnan(self.target):
+            if self.target is None:
                 return new_speed
 
             # Default speed set:
@@ -335,10 +186,7 @@ class VRFController1(VRFController):
             # Feedback.
             if self.feedback == FeedbackValue.so_cold:
                 if self.device.return_air_temp and self.device.current_temperature_set:
-                    if (
-                        self.device.return_air_temp
-                        > self.device.current_temperature_set
-                    ):
+                    if self.device.return_air_temp > self.device.current_temperature_set:
                         if self.device.speed == "HH":
                             new_speed = "M"
                         elif self.device.speed == "M":
@@ -357,7 +205,7 @@ class VRFController1(VRFController):
                     new_speed = "LL"
         elif self.device.work_mode == 2.0 or self.device.work_mode == 7.0:
             new_speed = "hold"
-            if np.isnan(self.target):
+            if self.target is None:
                 return new_speed
 
             # Default speed set:
@@ -371,10 +219,7 @@ class VRFController1(VRFController):
             # Feedback.
             if self.feedback == FeedbackValue.so_hot:
                 if self.device.return_air_temp and self.device.current_temperature_set:
-                    if (
-                        self.device.return_air_temp
-                        < self.device.current_temperature_set
-                    ):
+                    if self.device.return_air_temp < self.device.current_temperature_set:
                         if self.device.speed == "HH":
                             new_speed = "M"
                         elif self.device.speed == "M":
@@ -394,51 +239,29 @@ class VRFController1(VRFController):
         else:
             new_speed = "hold"
 
-        # a_now = arrow.utcnow()
-
-        # Restriction.
-        # if a_now.date() == arrow.get(self.blow_feedback_time).date():
-        #     if new_speed == "HH":
-        #         new_speed = "M"
-
-        # Recovery.
-        # logger.debug(self.high_speed_time)
-        # if (a_now - arrow.get(self.high_speed_time)).seconds > 60 * 60:
-        #     logger.debug(self.high_speed_time)
-        #     if new_speed == "HH":
-        #         new_speed = "M"
-
         self.device.speed_set = new_speed
 
         return new_speed
 
     def ventilation_mode(self) -> str:
         new_speed = "hold"
-        if np.isnan(self.target):
+        if self.target is None:
             return new_speed
         else:
             if not self.device.running_status:
                 new_speed = "HH"
             else:
-                # if self.realtime > 26.0:
-                #     new_speed = "HH"
-                # elif self.realtime < 22.0:
-                #     new_speed = "LL"
-
                 if (
-                    self.feedback == FeedbackValue.a_little_cold
-                    or self.feedback == FeedbackValue.so_cold
-                    or self.feedback == FeedbackValue.noisy_or_blowy
+                        self.feedback == FeedbackValue.a_little_cold
+                        or self.feedback == FeedbackValue.so_cold
+                        or self.feedback == FeedbackValue.noisy_or_blowy
                 ):
                     if self.device.speed == "HH":
                         new_speed = "M"
                     elif self.device.speed == "M":
                         new_speed = "LL"
 
-                if (
-                    self.feedback == FeedbackValue.a_little_hot
-                    or self.feedback == FeedbackValue.so_hot
-                ):
+                if self.feedback == FeedbackValue.a_little_hot or self.feedback == FeedbackValue.so_hot:
                     if self.device.speed == "LL":
                         new_speed = "M"
                     elif self.device.speed == "M":
@@ -449,9 +272,17 @@ class VRFController1(VRFController):
         return new_speed
 
     async def run(self):
-        self.get_switch_set()
-        self.get_speed_set()
-        self.get_temperature_set()
+        try:
+            logger.debug(self.device.current_temperature_set - 1)
+            self.get_switch_set()
+            self.get_speed_set()
+            self.get_temperature_set()
+        except TypeError:
+            logger.debug("missing data error")
+            raise MissingIOTDataError
+
+    def get_results(self):
+        return self.device
 
 
 async def query_status_time(db: Session, device_id: str) -> Tuple[datetime, datetime]:
@@ -478,92 +309,44 @@ async def query_status_time(db: Session, device_id: str) -> Tuple[datetime, date
         high_time = past.naive
         if not device.get(db, device_id):
             device.create(db=db, obj_in=DeviceCreate(id=device_id))
-        high_speed_time.create(
-            db=db, obj_in=HighSpeedTimeCreate(timestamp=high_time, device_id=device_id)
-        )
+        high_speed_time.create(db=db, obj_in=HighSpeedTimeCreate(timestamp=high_time, device_id=device_id))
 
     return feedback_time, high_time
 
 
-@logger.catch()
-async def build_acatvi_instructions(
-    params: ACATVIInstructionsRequest, db: Session
-) -> Dict:
-    target = (
-        np.NAN
-        if params.space_temperature_target == -1.0
-        else params.space_temperature_target
-    )
-    realtime = (
-        np.NAN
-        if params.space_realtime_temperature == -1.0
-        else params.space_realtime_temperature
-    )
-    return_air_temp = (
-        np.NAN
-        if params.return_air_temperature == -1.0
-        else params.return_air_temperature
-    )
-    current_temperature_set = (
-        np.NAN
-        if params.current_temperature_set == -1.0
-        else round_half_up(params.current_temperature_set)
-    )
+def transform_mode(mode_value: float) -> VRFMode:
+    try:
+        if mode_value == 1.0 or mode_value == 6.0:
+            mode = VRFMode.cooling
+        elif mode_value == 2.0 or mode_value == 7.0:
+            mode = VRFMode.heating
+        elif mode_value == 4.0 or mode_value == 8.0:
+            mode = VRFMode.ventilation
+        else:
+            mode = VRFMode.unknown
+    except TypeError:
+        raise MissingIOTDataError
+    return mode
+
+
+@logger.catch
+@missing_iot_data_handler
+async def build_acatvi_instructions(params: ACATVIInstructionsRequest) -> Dict:
+    work_mode = transform_mode(params.work_mode)
 
     vrf = VRF(
-        return_air_temp=return_air_temp,
-        current_temperature_set=current_temperature_set,
+        return_air_temp=params.return_air_temperature,
+        current_temperature_set=params.current_temperature_set,
         speed=params.current_speed,
         running_status=params.running_status,
-        work_mode=params.work_mode,
+        work_mode=work_mode,
     )
 
-    controller = VRFController1(
-        vrf, target, realtime, params.feedback, params.on_time, params.off_time
-    )
+    controller = VRFController(vrf, params.space_temperature_target, params.space_realtime_temperature, params.feedback,
+                               params.on_time, params.off_time)
     await controller.run()
     regulated_vrf = controller.get_results()
 
-    # if params.feedback == FeedbackValue.noisy_or_blowy:
-    #     blowy_feedback_time_in_db = blowy_feedback_time.get_time_by_device(
-    #         db=db, device_id=params.device_id
-    #     )
-    #     if blowy_feedback_time_in_db:
-    #         blowy_feedback_time.update(
-    #             db=db,
-    #             db_obj=blowy_feedback_time_in_db,
-    #             obj_in=BlowyFeedbackTimeUpdate(
-    #                 timestamp=datetime.utcnow(), device_id=params.device_id
-    #             ),
-    #         )
-    #     else:
-    #         blowy_feedback_time.create(
-    #             db=db,
-    #             obj_in=BlowyFeedbackTimeCreate(
-    #                 timestamp=datetime.utcnow(), device_id=params.device_id
-    #             ),
-    #         )
-
-    # if regulated_vrf.speed_set == "HH":
-    #     high_speed_time_in_db = high_speed_time.get_time_by_device(
-    #         db=db, device_id=params.device_id
-    #     )
-    #     if high_speed_time_in_db:
-    #         high_speed_time.update(
-    #             db=db,
-    #             db_obj=high_speed_time_in_db,
-    #             obj_in=HighSpeedTimeUpdate(
-    #                 timestamp=datetime.utcnow(), device_id=params.device_id
-    #             ),
-    #         )
-    #     else:
-    #         high_speed_time.create(
-    #             db=db,
-    #             obj_in=HighSpeedTimeCreate(
-    #                 timestamp=datetime.utcnow(), device_id=params.device_id
-    #             ),
-    #         )
-
     instructions = dict()
     instructions.update({"switch_set": regulated_vrf.equip_switch_set})
     instructions.update({"speed_set": regulated_vrf.speed_set})

+ 59 - 61
app/models/domain/devices.py

@@ -36,16 +36,16 @@ class DevicesEarlyStartTime(BaseModel):
 
 class ACATVIInstructionsRequest(BaseModel):
     device_id: str
-    return_air_temperature: float
-    running_status: bool
-    work_mode: float
-    current_speed: str
-    current_temperature_set: float
-    space_temperature_target: float
-    space_realtime_temperature: float
+    return_air_temperature: Optional[float]
+    running_status: Optional[bool]
+    work_mode: Optional[float]
+    current_speed: Optional[str]
+    current_temperature_set: Optional[float]
+    space_temperature_target: Optional[float]
+    space_realtime_temperature: Optional[float]
     feedback: FeedbackValue
-    on_time: str
-    off_time: str
+    on_time: Optional[str]
+    off_time: Optional[str]
 
 
 class ACATVIInstructionsTemporaryResponse(BaseModel):
@@ -56,7 +56,6 @@ class ACATVIInstructionsResponse(BaseModel):
     switch_set: Optional[str]
     speed_set: Optional[str]
     temperature_set: Optional[float]
-    # mode_set: Optional[str]
 
 
 class ACATVIModeRequest(BaseModel):
@@ -71,10 +70,10 @@ class ACATVIModeResponse(BaseModel):
 class ACATFCInstructionsRequestBase(BaseModel):
     device_id: str
     season: str
-    space_temperature_target: float
+    space_temperature_target: Optional[float]
     space_realtime_temperature: Optional[float]
-    running_status: bool
-    speed: Speed
+    running_status: Optional[bool]
+    speed: Optional[Speed]
     feedback: FeedbackValue
 
 
@@ -112,8 +111,8 @@ class ACATFCEarlyStartPredictionRequest(BaseModel):
     season: Season
     space_id: Optional[str]
     device_id: str
-    space_realtime_temperature: float
-    outdoor_realtime_temperature: float
+    space_realtime_temperature: Optional[float]
+    outdoor_realtime_temperature: Optional[float]
 
 
 class ACATFCEarlyStartPredictionResponse(BaseModel):
@@ -121,25 +120,25 @@ class ACATFCEarlyStartPredictionResponse(BaseModel):
 
 
 class Space(BaseModel):
-    realtime_temperature: float
+    realtime_temperature: Optional[float]
 
 
 class ACATVASpace(Space):
-    temperature_target: float
-    vav_default_weight: float
-    vav_temporary_weight: float
-    vav_temporary_update_time: str
+    space_temperature_target: Optional[float]
+    vav_default_weight: Optional[float]
+    vav_temporary_weight: Optional[float]
+    vav_temporary_update_time: Optional[str]
 
 
 class ACATAHSpace(Space):
-    temperature_target: float
-    ahu_default_weight: float
-    ahu_temporary_weight: float
-    ahu_temporary_update_time: str
+    space_temperature_target: Optional[float]
+    ahu_default_weight: Optional[float]
+    ahu_temporary_weight: Optional[float]
+    ahu_temporary_update_time: Optional[str]
 
 
 class ACATFUSpace(Space):
-    realtime_co2: float
+    space_realtime_co2: Optional[float]
 
 
 class ACATVAInstructionsRequestBase(BaseModel):
@@ -158,8 +157,7 @@ class ACATVAInstructionsRequest(ACATVAInstructionsRequestBase):
 
 class ACATVAInstructionsRequestV2(ACATVAInstructionsRequestBase):
     season: str
-    # temperature_set: float
-    return_air_temp: float
+    return_air_temperature: Optional[float]
 
 
 class ACATVAInstructionsResponse(BaseModel):
@@ -178,11 +176,11 @@ class ACATVAInstructionsResponseV2(BaseModel):
 
 class ACATAHFreqSetRequest(BaseModel):
     device_id: str
-    system_supply_static_press: float
-    system_supply_static_press_set: float
-    current_freq_set: float
+    system_supply_static_press: Optional[float]
+    system_supply_static_press_set: Optional[float]
+    current_freq_set: Optional[float]
     supply_air_temperature_set_list: List[float]
-    spaces_hot_rate: float
+    spaces_hot_rate: Optional[float]
 
 
 class ACATAHFreqSetResponse(BaseModel):
@@ -193,15 +191,15 @@ class ACATAHInstructionsRequest(BaseModel):
     device_id: str
     season: Season
     spaces: List[ACATAHSpace]
-    running_status: bool
-    return_air_temperature: float
-    return_air_temperature_set: float
-    supply_air_temperature: float
-    supply_air_temperature_set: float
-    freq: float
-    freq_set: float
-    fan_freq_upper_limit_set: float
-    fan_freq_lower_limit_set: float
+    running_status: Optional[bool]
+    return_air_temperature: Optional[float]
+    return_air_temperature_set: Optional[float]
+    supply_air_temperature: Optional[float]
+    supply_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 ACATAHInstructionsResponse(BaseModel):
@@ -213,11 +211,11 @@ class ACATAHInstructionsResponse(BaseModel):
 
 class SwitchSetRequestBase(BaseModel):
     device_id: str
-    running_status: bool
-    in_cloud_status: bool
-    on_time: str
-    off_time: str
-    is_workday: bool
+    running_status: Optional[bool]
+    in_cloud_status: Optional[bool]
+    on_time: Optional[str]
+    off_time: Optional[str]
+    is_workday: Optional[bool]
 
 
 class SwitchSetResponseBase(BaseModel):
@@ -252,12 +250,12 @@ class ACATAHSwitchSetResponse(SwitchSetResponseBase):
 
 class VAV(BaseModel):
     id: str
-    virtual_realtime_temperature: float
-    virtual_temperature_target: float
-    supply_air_flow_lower_limit: float
-    supply_air_flow_upper_limit: float
-    supply_air_flow_set: float
-    valve_opening: float
+    virtual_realtime_temperature: Optional[float]
+    virtual_temperature_target: Optional[float]
+    supply_air_flow_lower_limit: Optional[float]
+    supply_air_flow_upper_limit: Optional[float]
+    supply_air_flow_set: Optional[float]
+    valve_opening: Optional[float]
 
 
 class ACATAHRequestBase(BaseModel):
@@ -275,11 +273,11 @@ class ACATAHThermalModeSetResponse(BaseModel):
 
 
 class ACATAHSupplyAirTempSetRequest(ACATAHRequestBase):
-    supply_air_temperature_set: float
-    return_air_temperature: float
-    chill_water_valve_opening_set_list: Optional[List[float]]
-    hot_water_valve_opening_set_list: Optional[List[float]]
-    equip_switch_set_list: Optional[List[float]]
+    supply_air_temperature_set: Optional[float]
+    return_air_temperature: Optional[float]
+    chill_water_valve_opening_set_list: List[float]
+    hot_water_valve_opening_set_list: List[float]
+    equip_switch_set_list: List[float]
     is_clear_day: Optional[bool]
 
 
@@ -290,9 +288,9 @@ class ACATAHSupplyAirTempSetResponse(BaseModel):
 class ACATFUSupplyAirTempSetRequest(BaseModel):
     device_id: str
     season: Season
-    supply_air_temperature_set: float
-    hot_ratio: float
-    cold_ratio: float
+    supply_air_temperature_set: Optional[float]
+    hot_ratio: Optional[float]
+    cold_ratio: Optional[float]
     running_status_list: List[float]
 
 
@@ -302,8 +300,8 @@ class ACATFUSupplyAirTempSetResponse(BaseModel):
 
 class ACATFUFreqSetRequest(BaseModel):
     device_id: str
-    freq: float
-    fresh_air_temperature: float
+    freq: Optional[float]
+    fresh_air_temperature: Optional[float]
     spaces: List[ACATFUSpace]
     season: Season
     running_status_list: List[float]

+ 9 - 10
app/schemas/equipment.py

@@ -4,19 +4,11 @@ from enum import Enum
 from typing import List, Optional
 
 import numpy as np
-from pydantic import BaseModel as PydanticBaseModel, validator
+from pydantic import BaseModel
 
 from app.schemas.space import Space
 
 
-class BaseModel(PydanticBaseModel):
-    @validator("*")
-    def change_to_nan(cls, v):
-        if v == -999.9:
-            v = np.NAN
-        return v
-
-
 class AirValveSpeed(float, Enum):
     off = 0.0
     low = 1.0
@@ -24,6 +16,13 @@ class AirValveSpeed(float, Enum):
     high = 3.0
 
 
+class VRFMode(str, Enum):
+    cooling = "cooling"
+    heating = "heating"
+    ventilation = "ventilation"
+    unknown = "unknown"
+
+
 class BaseEquipment(BaseModel):
     id: Optional[str]
     running_status: Optional[bool] = False
@@ -81,7 +80,7 @@ class PAU(BaseEquipment):
 
 class VRF(BaseEquipment):
     equip_switch_set: Optional[str]
-    work_mode: Optional[float]
+    work_mode: Optional[VRFMode]
     speed: Optional[str]
     speed_set: Optional[str]
     current_temperature_set: Optional[float]

+ 1 - 1
app/services/service.py

@@ -16,7 +16,7 @@ def api_exception(func):
         except Exception:
             raise HTTPException(
                 status_code=500,
-                detail=("The server did not receive a correct response fromtheupstream server."),
+                detail="The server did not receive a correct response from the up stream server.",
             )
         else:
             return r