Selaa lähdekoodia

add some device control routers

highing666 3 vuotta sitten
vanhempi
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 sqlalchemy.orm import Session
 
 import app.models.domain.devices as domain_devices
 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.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.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.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.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.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.vrf.basic import build_acatvi_instructions
 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
 
 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)
 async def get_acatah_supply_air_temperature_set(
         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)
 async def get_acatah_freq_set(params: domain_devices.ACATAHFreqSetRequest):
     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(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)
@@ -70,7 +99,9 @@ async def get_acatah_switch_set(params: domain_devices.ACATAHSwitchSetRequest):
     logger.info(params)
     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)
@@ -80,17 +111,9 @@ async def get_acvtsf_switch_set(params: domain_devices.ACVTSFSwitchSetRequest):
     logger.info(params)
     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)
@@ -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)
 async def get_acatfu_supply_air_temperature_set(
         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)
 async def get_acatfu_freq_set(
         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)
 async def get_acatfc_early_start_time(
         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)
 async def get_acatvi_instructions(params: domain_devices.ACATVIInstructionsRequest):
     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)
-    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

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

@@ -6,7 +6,7 @@ from httpx import AsyncClient
 from loguru import logger
 
 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.services.platform import DataPlatformService, InfoCode
 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}')
 
     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 app.models.domain.devices import ThermalMode
+from app.models.domain.devices import ACATAHThermalModeSetRequest
 from app.schemas.equipment import VAVBox
 from app.services.platform import DataPlatformService, InfoCode
 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()
 
     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.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.transfer import SpaceInfoService
 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}')
 
     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 loguru import logger
 
+from app.models.domain.devices import ACATFUFreqSetRequest
 from app.services.platform import DataPlatformService, InfoCode
 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()
 
     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 loguru import logger
 
+from app.models.domain.devices import ACATFUSupplyAirTempSetRequest
 from app.services.platform import DataPlatformService, InfoCode
 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)
 
     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 app.controllers.equipment.switch import Switch, fetch_data, send_switch_command
+from app.models.domain.devices import ACATFUSwitchSetRequest
 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)
 
     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')
 
 
+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):
     realtime_temperature: float
     temperature_target: float
@@ -90,7 +101,7 @@ class ACATAHFreqSetRequest(BaseModel):
     system_supply_static_press: float
     system_supply_static_press_set: float
     current_freq_set: float
-    supply_air_temperature_set: List[float]
+    supply_air_temperature_set_list: List[float]
     spaces_hot_rate: float
 
 
@@ -117,6 +128,22 @@ class SwitchSetResponseBase(BaseModel):
     switch_set: SwitchSet
 
 
+class ACVTSFSwitchSetRequest(SwitchSetRequestBase):
+    pass
+
+
+class ACVTSFSwitchSetResponse(SwitchSetResponseBase):
+    pass
+
+
+class ACATFUSwitchSetRequest(SwitchSetRequestBase):
+    pass
+
+
+class ACATFUSwitchSetResponse(SwitchSetResponseBase):
+    pass
+
+
 class ACATAHSwitchSetRequest(SwitchSetRequestBase):
     break_start_time: str
     break_end_time: str
@@ -126,9 +153,61 @@ class ACATAHSwitchSetResponse(SwitchSetResponseBase):
     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
+
+
+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