Browse Source

add some device control routers

highing666 3 years ago
parent
commit
7f897aa7b3

+ 93 - 18
app/api/routers/devices.py

@@ -1,21 +1,24 @@
-from fastapi import APIRouter, BackgroundTasks, Depends, Query
+from fastapi import APIRouter, Depends, Query
 from loguru import logger
 from loguru import logger
 from sqlalchemy.orm import Session
 from sqlalchemy.orm import Session
 
 
 import app.models.domain.devices as domain_devices
 import app.models.domain.devices as domain_devices
 from app.api.dependencies.db import get_db
 from app.api.dependencies.db import get_db
-from app.controllers.equipment.ahu.supply_air_temperature_set import get_next_supply_air_temperature_set
-from app.controllers.equipment.ahu.thermal_mode import get_thermal_mode
 from app.controllers.equipment.ahu.basic import build_acatah_freq_set
 from app.controllers.equipment.ahu.basic import build_acatah_freq_set
+from app.controllers.equipment.ahu.supply_air_temperature_set import get_next_supply_air_temperature_set
+from app.controllers.equipment.ahu.supply_air_temperature_set import build_acatah_supply_air_temperature_set
 from app.controllers.equipment.ahu.switch import build_acatah_switch_set
 from app.controllers.equipment.ahu.switch import build_acatah_switch_set
+from app.controllers.equipment.ahu.thermal_mode import get_thermal_mode, build_acatah_thermal_mode_set
 from app.controllers.equipment.fcu.basic import build_acatfc_instructions
 from app.controllers.equipment.fcu.basic import build_acatfc_instructions
+from app.controllers.equipment.fcu.early_start import build_acatfc_early_start_prediction
 from app.controllers.equipment.fcu.early_start import get_recommended_early_start_time
 from app.controllers.equipment.fcu.early_start import get_recommended_early_start_time
-from app.controllers.equipment.pau.freq_set import get_next_acatfu_freq_set
+from app.controllers.equipment.pau.freq_set import get_next_acatfu_freq_set, build_acatfu_freq_set
 from app.controllers.equipment.pau.supply_air_temperature_set import get_next_acatfu_supply_air_temperature_set
 from app.controllers.equipment.pau.supply_air_temperature_set import get_next_acatfu_supply_air_temperature_set
-from app.controllers.equipment.pau.switch import get_switch_action
+from app.controllers.equipment.pau.supply_air_temperature_set import build_acatfu_supply_air_temperature
+from app.controllers.equipment.pau.switch import get_switch_action, build_acatfu_switch_set
 from app.controllers.equipment.vav import build_acatva_instructions
 from app.controllers.equipment.vav import build_acatva_instructions
-from app.controllers.equipment.vrf.basic import build_acatvi_instructions
 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.models.domain.devices import DevicesInstructionsBaseResponse, DevicesEarlyStartTime
 from app.models.domain.devices import DevicesInstructionsBaseResponse, DevicesEarlyStartTime
 
 
 router = APIRouter()
 router = APIRouter()
@@ -37,6 +40,16 @@ async def get_acatah_thermal_mode_set(
     }
     }
 
 
 
 
+@router.post('/instructions/acatah/thermal-mode-set', response_model=domain_devices.ACATAHThermalModeSetResponse)
+async def get_acatah_thermal_mode_set_v2(params: domain_devices.ACATAHThermalModeSetRequest):
+    thermal_mode = build_acatah_thermal_mode_set(params)
+
+    logger.info(f'{params.device_id}: thermal mode set - {thermal_mode}')
+    resp = {'thermal_mode_set': thermal_mode}
+
+    return resp
+
+
 @router.get('/instructions/acatah/supply-air-temperature-set', response_model=DevicesInstructionsBaseResponse)
 @router.get('/instructions/acatah/supply-air-temperature-set', response_model=DevicesInstructionsBaseResponse)
 async def get_acatah_supply_air_temperature_set(
 async def get_acatah_supply_air_temperature_set(
         project_id: str = Query(..., max_length=50, regex='^Pj', alias='projectId'),
         project_id: str = Query(..., max_length=50, regex='^Pj', alias='projectId'),
@@ -53,6 +66,20 @@ async def get_acatah_supply_air_temperature_set(
     }
     }
 
 
 
 
+@router.post(
+    '/instructions/acatah/supply-air-temperature-set',
+    response_model=domain_devices.ACATAHSupplyAirTempSetResponse
+)
+async def get_acatah_supply_air_temperature_set_v2(params: domain_devices.ACATAHSupplyAirTempSetRequest):
+    supply_air_temperature_set = build_acatah_supply_air_temperature_set(params)
+
+    logger.info(supply_air_temperature_set)
+
+    resp = {'supply_air_temperature_set': supply_air_temperature_set}
+
+    return resp
+
+
 @router.post('/instructions/acatah/freq-set', response_model=domain_devices.ACATAHFreqSetResponse)
 @router.post('/instructions/acatah/freq-set', response_model=domain_devices.ACATAHFreqSetResponse)
 async def get_acatah_freq_set(params: domain_devices.ACATAHFreqSetRequest):
 async def get_acatah_freq_set(params: domain_devices.ACATAHFreqSetRequest):
     freq_set = await build_acatah_freq_set(params)
     freq_set = await build_acatah_freq_set(params)
@@ -60,7 +87,9 @@ async def get_acatah_freq_set(params: domain_devices.ACATAHFreqSetRequest):
     logger.info(params)
     logger.info(params)
     logger.info(f'{params.device_id}: freq set - {freq_set}')
     logger.info(f'{params.device_id}: freq set - {freq_set}')
 
 
-    return freq_set
+    resp = {'freq_set': freq_set}
+
+    return resp
 
 
 
 
 @router.post('/instructions/acatah/switch-set', response_model=domain_devices.ACATAHSwitchSetResponse)
 @router.post('/instructions/acatah/switch-set', response_model=domain_devices.ACATAHSwitchSetResponse)
@@ -70,7 +99,9 @@ async def get_acatah_switch_set(params: domain_devices.ACATAHSwitchSetRequest):
     logger.info(params)
     logger.info(params)
     logger.info(f'{params.device_id}: switch set - {switch_set}')
     logger.info(f'{params.device_id}: switch set - {switch_set}')
 
 
-    return switch_set
+    resp = {'switch_set': switch_set}
+
+    return resp
 
 
 
 
 @router.post('/instructions/acvtsf/switch-set', response_model=domain_devices.ACVTSFSwitchSetResponse)
 @router.post('/instructions/acvtsf/switch-set', response_model=domain_devices.ACVTSFSwitchSetResponse)
@@ -80,17 +111,9 @@ async def get_acvtsf_switch_set(params: domain_devices.ACVTSFSwitchSetRequest):
     logger.info(params)
     logger.info(params)
     logger.info(f'{params.device_id}: switch set - {switch_set}')
     logger.info(f'{params.device_id}: switch set - {switch_set}')
 
 
-    return switch_set
-
+    resp = {'switch_set': switch_set}
 
 
-# @router.post('/on-ratio-experiment/fcu/{fcu_id}/target/{target}/period/{period}')
-# async def run_on_ratio_experiment(fcu_id: str, target: float, period: int, background_tasks: BackgroundTasks):
-#     background_tasks.add_task(start_on_ratio_mode, fcu_id, target, period)
-#     return {
-#         'fcu': fcu_id,
-#         'target': target,
-#         'period': period
-#     }
+    return resp
 
 
 
 
 @router.get('/instructions/acatfu/equip-switch-set', response_model=DevicesInstructionsBaseResponse)
 @router.get('/instructions/acatfu/equip-switch-set', response_model=DevicesInstructionsBaseResponse)
@@ -109,6 +132,18 @@ async def get_acatfu_equip_switch_set(
     }
     }
 
 
 
 
+@router.post('/instructions/acatfu/switch-set', response_model=domain_devices.ACATFUSwitchSetResponse)
+async def get_acatfu_switch_set(params: domain_devices.ACATFUSwitchSetRequest):
+    switch_set = await build_acatfu_switch_set(params)
+
+    logger.info(params)
+    logger.info(f'{params.device_id}: switch set - {switch_set}')
+
+    resp = {'switch_set': switch_set}
+
+    return resp
+
+
 @router.get('/instructions/acatfu/supply-air-temperature-set', response_model=DevicesInstructionsBaseResponse)
 @router.get('/instructions/acatfu/supply-air-temperature-set', response_model=DevicesInstructionsBaseResponse)
 async def get_acatfu_supply_air_temperature_set(
 async def get_acatfu_supply_air_temperature_set(
         project_id: str = Query(..., max_length=50, regex='^Pj', alias='projectId'),
         project_id: str = Query(..., max_length=50, regex='^Pj', alias='projectId'),
@@ -125,6 +160,20 @@ async def get_acatfu_supply_air_temperature_set(
     }
     }
 
 
 
 
+@router.post(
+    '/instructions/acatfu/supply-air-temperature-set',
+    response_model=domain_devices.ACATFUSupplyAirTempSetResponse
+)
+async def get_acatfu_supply_air_temperature_set_v2(params: domain_devices.ACATFUSupplyAirTempSetRequest):
+    supply_air_temperature_set = build_acatfu_supply_air_temperature(params)
+
+    logger.info(supply_air_temperature_set)
+
+    resp = {'supply_air_temperature_set': supply_air_temperature_set}
+
+    return resp
+
+
 @router.get('/instructions/acatfu/freq-set', response_model=DevicesInstructionsBaseResponse)
 @router.get('/instructions/acatfu/freq-set', response_model=DevicesInstructionsBaseResponse)
 async def get_acatfu_freq_set(
 async def get_acatfu_freq_set(
         project_id: str = Query(..., max_length=50, regex='^Pj', alias='projectId'),
         project_id: str = Query(..., max_length=50, regex='^Pj', alias='projectId'),
@@ -141,6 +190,17 @@ async def get_acatfu_freq_set(
     }
     }
 
 
 
 
+@router.post('/instruction/acatfu/freq-set', response_model=domain_devices.ACATFUFreqSetResponse)
+async def get_acatfu_freq_set(params: domain_devices.ACATFUFreqSetRequest):
+    freq_set = build_acatfu_freq_set(params)
+
+    logger.info(f'{params.device_id} - {freq_set}')
+
+    resp = {'freq_set': freq_set}
+
+    return resp
+
+
 @router.get('/early-start/prediction/acatfc', response_model=DevicesEarlyStartTime)
 @router.get('/early-start/prediction/acatfc', response_model=DevicesEarlyStartTime)
 async def get_acatfc_early_start_time(
 async def get_acatfc_early_start_time(
         project_id: str = Query(..., max_length=50, regex='^Pj', alias='projectId'),
         project_id: str = Query(..., max_length=50, regex='^Pj', alias='projectId'),
@@ -155,6 +215,21 @@ async def get_acatfc_early_start_time(
     }
     }
 
 
 
 
+@router.post('/prediction/acatfc/early-start', response_model=domain_devices.ACATFCEarlyStartPredictionResponse)
+async def get_acatfc_early_start_prediction(
+        params: domain_devices.ACATFCEarlyStartPredictionRequest,
+        db: Session = Depends(get_db)
+):
+    minutes = await build_acatfc_early_start_prediction(params, db)
+
+    logger.info(params)
+    logger.info(f'{params.space_id} - {minutes}')
+
+    resp = {'minutes': minutes}
+
+    return resp
+
+
 @router.post('/instructions/acatvi', response_model=domain_devices.ACATVIInstructionsResponse)
 @router.post('/instructions/acatvi', response_model=domain_devices.ACATVIInstructionsResponse)
 async def get_acatvi_instructions(params: domain_devices.ACATVIInstructionsRequest):
 async def get_acatvi_instructions(params: domain_devices.ACATVIInstructionsRequest):
     instructions = await build_acatvi_instructions(params)
     instructions = await build_acatvi_instructions(params)

+ 1 - 1
app/controllers/equipment/ahu/basic.py

@@ -106,6 +106,6 @@ async def build_acatah_freq_set(params: ACATAHFreqSetRequest) -> float:
     )
     )
 
 
     ahu_controller = AHUController(ahu, acat_system)
     ahu_controller = AHUController(ahu, acat_system)
-    new_freq_set = await ahu_controller.build_freq_set(params.supply_air_temperature_set, params.spaces_hot_rate)
+    new_freq_set = await ahu_controller.build_freq_set(params.supply_air_temperature_set_list, params.spaces_hot_rate)
 
 
     return new_freq_set
     return new_freq_set

+ 46 - 1
app/controllers/equipment/ahu/supply_air_temperature_set.py

@@ -6,7 +6,7 @@ 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.controllers.equipment.ahu.thermal_mode import count_vav_box_weight, fetch_status_params
-from app.models.domain.devices import ThermalMode
+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.platform import DataPlatformService, InfoCode
 from app.services.transfer import Duoduo, Season
 from app.services.transfer import Duoduo, Season
@@ -240,3 +240,48 @@ async def get_next_supply_air_temperature_set(project_id: str, device_id: str) -
     logger.debug(f'next supply air temperature set: {device_id} - {new}')
     logger.debug(f'next supply air temperature set: {device_id} - {new}')
 
 
     return new
     return new
+
+
+@logger.catch()
+def build_acatah_supply_air_temperature_set(params: ACATAHSupplyAirTempSetRequest) -> float:
+    try:
+        vav_list = list()
+        for raw_vav in params.vav_list:
+            vav = VAVBox(**raw_vav.dict())
+            vav.virtual_target_temperature = raw_vav.virtual_temperature_target
+            vav_list.append(vav)
+
+        if params.chill_water_valve_opening_set_list[-1] == 0.0:
+            thermal_mode = ThermalMode.heating
+        else:
+            thermal_mode = ThermalMode.cooling
+
+        is_off_to_on = False
+        if params.equip_switch_set_list[-1] == 1.0:
+            for item in params.equip_switch_set_list[::-1]:
+                if item == 0.0:
+                    is_off_to_on = True
+                    break
+
+        is_thermal_mode_switched = False
+        if len(set([item for item in params.hot_water_valve_opening_set_list])) > 1:
+            is_thermal_mode_switched = True
+        if len(set([item for item in params.chill_water_valve_opening_set_list])) > 1:
+            is_thermal_mode_switched = True
+
+        controller = ACATAHSupplyAirTemperatureController(
+            vav_list,
+            params.supply_air_temperature,
+            params.return_air_temperature,
+            thermal_mode,
+            is_off_to_on,
+            is_thermal_mode_switched,
+            Season(params.season)
+        )
+        supply_air_temperature_set = controller.build()
+
+    except (KeyError, IndexError):
+        controller = ACATAHSupplyAirTemperatureDefaultController(params.is_clear_day)
+        supply_air_temperature_set = controller.build()
+
+    return supply_air_temperature_set

+ 21 - 0
app/controllers/equipment/ahu/thermal_mode.py

@@ -4,6 +4,7 @@ from httpx import AsyncClient
 from loguru import logger
 from loguru import logger
 
 
 from app.models.domain.devices import ThermalMode
 from app.models.domain.devices import ThermalMode
+from app.models.domain.devices import ACATAHThermalModeSetRequest
 from app.schemas.equipment import VAVBox
 from app.schemas.equipment import VAVBox
 from app.services.platform import DataPlatformService, InfoCode
 from app.services.platform import DataPlatformService, InfoCode
 from app.services.transfer import Duoduo, Season
 from app.services.transfer import Duoduo, Season
@@ -122,3 +123,23 @@ async def get_thermal_mode(project_id: str, device_id: str) -> ThermalMode:
     mode = controller.build()
     mode = controller.build()
 
 
     return ThermalMode(mode)
     return ThermalMode(mode)
+
+
+@logger.catch()
+def build_acatah_thermal_mode_set(params: ACATAHThermalModeSetRequest) -> str:
+    vav_list = 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)
+
+    controller = ACATAHThermalModeController(vav_list, Season(params.season))
+    mode = controller.build()
+
+    return mode

+ 11 - 0
app/controllers/equipment/fcu/early_start.py

@@ -7,6 +7,7 @@ from sqlalchemy.orm import Session
 
 
 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.services.platform import DataPlatformService
 from app.services.platform import DataPlatformService
 from app.services.transfer import SpaceInfoService
 from app.services.transfer import SpaceInfoService
 from app.services.weather import WeatherService
 from app.services.weather import WeatherService
@@ -70,3 +71,13 @@ async def get_recommended_early_start_time(db: Session, project_id: str, space_i
     logger.debug(f'{space_id}: indoor-{indoor_temp}, outdoor-{outdoor_temp}, prediction-{hour * 60}')
     logger.debug(f'{space_id}: indoor-{indoor_temp}, outdoor-{outdoor_temp}, prediction-{hour * 60}')
 
 
     return hour * 60
     return hour * 60
+
+
+@logger.catch()
+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)
+
+    builder = EarlyStartTimeDTRBuilder(model_path)
+    hour = await builder.get_prediction(params.space_realtime_temperature, params.outdoor_realtime_temperature)
+
+    return hour * 60

+ 13 - 0
app/controllers/equipment/pau/freq_set.py

@@ -5,6 +5,7 @@ from typing import Tuple
 from httpx import AsyncClient
 from httpx import AsyncClient
 from loguru import logger
 from loguru import logger
 
 
+from app.models.domain.devices import ACATFUFreqSetRequest
 from app.services.platform import DataPlatformService, InfoCode
 from app.services.platform import DataPlatformService, InfoCode
 from app.services.transfer import Duoduo
 from app.services.transfer import Duoduo
 
 
@@ -62,3 +63,15 @@ async def get_next_acatfu_freq_set(project_id: str, device_id: str) -> float:
     next_freq_set = controller.get_next_set()
     next_freq_set = controller.get_next_set()
 
 
     return next_freq_set
     return next_freq_set
+
+
+@logger.catch()
+def build_acatfu_freq_set(params: ACATFUFreqSetRequest) -> float:
+    controller = ACATFUFanFreqController(
+        params.freq,
+        params.hot_ratio,
+        params.cold_ratio
+    )
+    freq_set = controller.get_next_set()
+
+    return freq_set

+ 20 - 0
app/controllers/equipment/pau/supply_air_temperature_set.py

@@ -3,6 +3,7 @@ from typing import Tuple
 from httpx import AsyncClient
 from httpx import AsyncClient
 from loguru import logger
 from loguru import logger
 
 
+from app.models.domain.devices import ACATFUSupplyAirTempSetRequest
 from app.services.platform import DataPlatformService, InfoCode
 from app.services.platform import DataPlatformService, InfoCode
 from app.services.transfer import Duoduo
 from app.services.transfer import Duoduo
 
 
@@ -86,3 +87,22 @@ async def get_next_acatfu_supply_air_temperature_set(project_id: str, device_id:
     next_temperature_set = controller.get_next_set(is_just_booted)
     next_temperature_set = controller.get_next_set(is_just_booted)
 
 
     return next_temperature_set
     return next_temperature_set
+
+
+@logger.catch()
+def build_acatfu_supply_air_temperature(params: ACATFUSupplyAirTempSetRequest) -> float:
+    is_just_booted = False
+    if params.running_status_list[-1] == 1.0:
+        for item in params.running_status_list[::-1]:
+            if item == 0.0:
+                is_just_booted = True
+                break
+
+    controller = ACATFUSupplyAirTemperatureController(
+        params.supply_air_temperature,
+        params.hot_ratio,
+        params.cold_ratio
+    )
+    supply_air_temperature_set = controller.get_next_set(is_just_booted)
+
+    return supply_air_temperature_set

+ 16 - 0
app/controllers/equipment/pau/switch.py

@@ -3,6 +3,7 @@
 from loguru import logger
 from loguru import logger
 
 
 from app.controllers.equipment.switch import Switch, fetch_data, send_switch_command
 from app.controllers.equipment.switch import Switch, fetch_data, send_switch_command
+from app.models.domain.devices import ACATFUSwitchSetRequest
 from app.schemas.equipment import PAU
 from app.schemas.equipment import PAU
 
 
 
 
@@ -27,3 +28,18 @@ async def get_switch_action(project_id: str, device_id: str) -> str:
     action = await PAUSwitch(PAU(**device_params)).build_next_action(is_workday)
     action = await PAUSwitch(PAU(**device_params)).build_next_action(is_workday)
 
 
     return action
     return action
+
+
+@logger.catch()
+async def build_acatfu_switch_set(params: ACATFUSwitchSetRequest) -> str:
+    pau = PAU(
+        running_status=params.running_status,
+        in_cloud_status=params.in_cloud_status,
+        on_time=params.off_time,
+        off_time=params.off_time
+    )
+    action = await PAUSwitch(pau).build_next_action(params.is_workday)
+    if not params.is_workday:
+        action = 'off'
+
+    return action

+ 83 - 4
app/models/domain/devices.py

@@ -61,6 +61,17 @@ class ACATFCInstructionsResponse(BaseModel):
     water_valve_switch_set: int = Field(None, alias='water')
     water_valve_switch_set: int = Field(None, alias='water')
 
 
 
 
+class ACATFCEarlyStartPredictionRequest(BaseModel):
+    space_id: Optional[str]
+    device_id: str
+    space_realtime_temperature: float
+    outdoor_realtime_temperature: float
+
+
+class ACATFCEarlyStartPredictionResponse(BaseModel):
+    minutes: float
+
+
 class Space(BaseModel):
 class Space(BaseModel):
     realtime_temperature: float
     realtime_temperature: float
     temperature_target: float
     temperature_target: float
@@ -90,7 +101,7 @@ class ACATAHFreqSetRequest(BaseModel):
     system_supply_static_press: float
     system_supply_static_press: float
     system_supply_static_press_set: float
     system_supply_static_press_set: float
     current_freq_set: float
     current_freq_set: float
-    supply_air_temperature_set: List[float]
+    supply_air_temperature_set_list: List[float]
     spaces_hot_rate: float
     spaces_hot_rate: float
 
 
 
 
@@ -117,6 +128,22 @@ class SwitchSetResponseBase(BaseModel):
     switch_set: SwitchSet
     switch_set: SwitchSet
 
 
 
 
+class ACVTSFSwitchSetRequest(SwitchSetRequestBase):
+    pass
+
+
+class ACVTSFSwitchSetResponse(SwitchSetResponseBase):
+    pass
+
+
+class ACATFUSwitchSetRequest(SwitchSetRequestBase):
+    pass
+
+
+class ACATFUSwitchSetResponse(SwitchSetResponseBase):
+    pass
+
+
 class ACATAHSwitchSetRequest(SwitchSetRequestBase):
 class ACATAHSwitchSetRequest(SwitchSetRequestBase):
     break_start_time: str
     break_start_time: str
     break_end_time: str
     break_end_time: str
@@ -126,9 +153,61 @@ class ACATAHSwitchSetResponse(SwitchSetResponseBase):
     pass
     pass
 
 
 
 
-class ACVTSFSwitchSetRequest(SwitchSetRequestBase):
-    pass
+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
 
 
 
 
-class ACVTSFSwitchSetResponse(SwitchSetResponseBase):
+class ACATAHRequestBase(BaseModel):
+    device_id: str
+    season: str
+    vav_list: List[VAV]
+
+
+class ACATAHThermalModeSetRequest(ACATAHRequestBase):
     pass
     pass
+
+
+class ACATAHThermalModeSetResponse(BaseModel):
+    thermal_mode_set: ThermalMode
+
+
+class ACATAHSupplyAirTempSetRequest(ACATAHRequestBase):
+    supply_air_temperature: 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]]
+    is_clear_day: Optional[bool]
+
+
+class ACATAHSupplyAirTempSetResponse(BaseModel):
+    supply_air_temperature_set: float
+
+
+class ACATFUSupplyAirTempSetRequest(BaseModel):
+    device_id: str
+    supply_air_temperature: float
+    hot_ratio: float
+    cold_ratio: float
+    running_status_list: List[float]
+
+
+class ACATFUSupplyAirTempSetResponse(BaseModel):
+    supply_air_temperature_set: float
+
+
+class ACATFUFreqSetRequest(BaseModel):
+    device_id: float
+    freq: float
+    hot_ratio: float
+    cold_ratio: float
+
+
+class ACATFUFreqSetResponse(BaseModel):
+    freq_set: float