Browse Source

complete on ratio experiment code

chenhaiyang 4 years ago
parent
commit
64d913431c

+ 16 - 0
app/controllers/equipment/events.py

@@ -5,6 +5,7 @@ from httpx import AsyncClient
 
 from app.controllers.equipment.ahu.basic import get_freq_controlled
 from app.controllers.equipment.ahu.switch import ahu_switch_control
+from app.controllers.equipment.fcu.on_ratio import start_control_group_mode, start_on_ratio_mode
 from app.controllers.equipment.pau.switch import pau_switch_control
 from app.controllers.equipment.ventilation_fan.switch import ventilation_fan_switch_control
 from app.services.platform import DataPlatformService
@@ -53,3 +54,18 @@ async def regulate_ventilation_fan_switch():
 
     for eq in eq_list:
         await ventilation_fan_switch_control(_PROJECT_ID, eq)
+
+
+@repeat_every(seconds=60 * 15)
+async def run_control_group():
+    _FCU_LIST = [
+        'Eq11010802593142c55b64c5492c92560d280885a2f7',
+        'Eq11010802598449efe230f444cca826e840dbf67f41'
+    ]
+    for fcu in _FCU_LIST:
+        await start_control_group_mode(fcu)
+
+
+async def run_experiment_group():
+    await start_on_ratio_mode('Eq11010802593129d7ff3d9b4fd296f30927fd8fb76d')
+    await start_on_ratio_mode('Eq1101080259ea519ed43678481c8a8c108fa85e5aa3')

+ 102 - 19
app/controllers/equipment/fcu/on_ratio.py

@@ -1,12 +1,18 @@
+import asyncio
 import time
-from typing import Dict, Tuple
+from typing import Tuple
 
 import arrow
 from httpx import AsyncClient
 from loguru import logger
 
-from app.utils.math import round_half_up
+from app.controllers.equipment.fcu.basic import FCUControllerV2
+from app.schemas.equipment import FCU
+from app.schemas.space import Space
+from app.services.platform import DataPlatformService, InfoCode
+from app.services.transfer import Season
 from app.utils.date import get_time_str, TIME_FMT
+from app.utils.math import round_half_up
 
 
 class OnRatioController:
@@ -28,12 +34,12 @@ class OnRatioController:
 
         return mode
 
-    def select_speed(self, last_return_air: float) -> str:
+    def select_speed(self, delta_all: float) -> str:
         mode = self.select_mode()
         if mode == 'off':
             speed = 'off'
         elif mode == 'normal':
-            if (self.return_air - last_return_air) > 0.8:
+            if delta_all > 0.00088889:
                 speed = 'medium'
             else:
                 speed = 'high'
@@ -68,16 +74,52 @@ class OnRatioController:
         return ratio
 
 
-async def send_instructions(switch: bool, speed: str, water_valve: bool) -> None:
-    pass
-
+async def send_instructions(device_id: str, switch: bool, speed: str, water_valve: bool) -> None:
+    switch_value = 1.0 if switch else 0.0
+    water_valve_value = 1.0 if water_valve else 0.0
+    speed_value_dict = {
+        'off': 0.0,
+        'low': 1.0,
+        'medium': 2.0,
+        'high': 3.0
+    }
+    speed_value = speed_value_dict.get(speed)
+    async with AsyncClient() as client:
+        platform = DataPlatformService(client, 'Pj1101080259')
+
+        await platform.set_code_value(device_id, code=InfoCode.equip_switch_set, value=switch_value)
+        await platform.set_code_value(device_id, code=InfoCode.water_valve_switch_set, value=water_valve_value)
+        await platform.set_code_value(device_id, code=InfoCode.fan_speed_set, value=speed_value)
+
+        await platform.set_code_value(device_id, code=InfoCode.work_mode_set, value=2.0)
+        # await platform.set_code_value(device_id, code=InfoCode.in_cloud_set, value=1.0)
+
+
+async def fetch_params(device_id: str, period_time: int, last_ratio: float) -> Tuple[float, float, float, float]:
+    async with AsyncClient() as client:
+        middle_time = int(round_half_up(period_time * (1 - last_ratio)))
+        platform = DataPlatformService(client, 'Pj1101080259')
+
+        return_air_c = await platform.get_realtime_data(InfoCode.return_air_temperature, device_id)
+        return_air_a = await platform.get_past_data(InfoCode.return_air_temperature, device_id, period_time)
+        return_air_b = await platform.get_past_data(InfoCode.return_air_temperature, device_id, middle_time)
+
+        delta_all = (return_air_c - return_air_a) / period_time
+        if 0 < last_ratio < 1:
+            delta_on = (return_air_b - return_air_a) / (period_time - middle_time)
+            delta_off = (return_air_c - return_air_b) / middle_time
+        elif last_ratio == 0.0:
+            delta_on = 0.0
+            delta_off = (return_air_c - return_air_b) / middle_time
+        else:
+            delta_on = (return_air_b - return_air_a) / (period_time - middle_time)
+            delta_off = 0.0
 
-async def fetch_params(device_id: str, period_time: float, last_ratio: float) -> Tuple[float, float, float, float]:
-    pass
+        return return_air_c, delta_all, delta_on, delta_off
 
 
 @logger.catch()
-async def on_ratio_experiment(device_id):
+async def start_on_ratio_mode(device_id):
     _TARGET = 26.0
     _DAILY_ON_TIME = '060000'
     _DAILY_OFF_TIME = '220000'
@@ -86,13 +128,13 @@ async def on_ratio_experiment(device_id):
     period_num = 0
     last_on_ratio = 1.0
     life_count = 0
-    while life_count < 1000:
+    while life_count < 10:
         time_str = get_time_str()
         if _DAILY_ON_TIME <= arrow.get(time_str, TIME_FMT).time().strftime('%H%M%S') < _DAILY_OFF_TIME:
-            return_air, last_return_air, delta_on, delta_off = await fetch_params(device_id, period_time, last_on_ratio)
+            return_air, delta_all, delta_on, delta_off = await fetch_params(device_id, period_time, last_on_ratio)
             controller = OnRatioController(_TARGET, return_air, period_num)
             mode = controller.select_mode()
-            speed = controller.select_speed(last_return_air)
+            speed = controller.select_speed(delta_all)
             switch = False if speed == 'off' else True
             water_valve = controller.select_water_valve()
 
@@ -101,22 +143,63 @@ async def on_ratio_experiment(device_id):
                 on_range = round_half_up(period_time * on_ratio)
                 off_range = period_time - on_range
 
-                await send_instructions(switch, speed, water_valve)
-                time.sleep(on_range)
-                await send_instructions(switch, speed, False)
-                time.sleep(off_range)
+                await send_instructions(device_id, switch, speed, water_valve)
+                await asyncio.sleep(on_range)
+                await send_instructions(device_id, switch, speed, False)
+                await asyncio.sleep(off_range)
 
                 period_num += 1
                 last_on_ratio = on_ratio
             else:
-                await send_instructions(switch, speed, water_valve)
+                await send_instructions(device_id, switch, speed, water_valve)
                 time.sleep(period_time)
 
                 period_num = 0
                 last_on_ratio = 1.0
 
             life_count += 1
+
+            logger.info(f'{life_count}: {device_id} - {mode}')
         else:
-            await send_instructions(False, 'off', False)
+            await send_instructions(device_id, False, 'off', False)
             period_num = 0
             last_on_ratio = 0.0
+
+
+@logger.catch()
+async def start_control_group_mode(device_id: str):
+    async with AsyncClient() as client:
+        platform = DataPlatformService(client, 'Pj1101080259')
+
+        return_air = await platform.get_realtime_data(InfoCode.return_air_temperature, device_id)
+        space_params = {
+            'id': device_id,
+            'temperature_target': 26.0,
+            'realtime_temperature': return_air
+        }
+        space = Space(**space_params)
+
+        fcu_params = {
+            'id': device_id,
+            'space': space
+        }
+        fcu = FCU(**fcu_params)
+
+        controller = FCUControllerV2(fcu, Season.heating)
+        await controller.run()
+        regulated_fcu = controller.get_results()
+
+        speed_value_dict = {
+            0.0: 'off',
+            1.0: 'low',
+            2.0: 'medium',
+            3.0: 'high'
+        }
+
+        await send_instructions(
+            device_id,
+            regulated_fcu.running_status,
+            speed_value_dict.get(regulated_fcu.air_valve_speed),
+            regulated_fcu.running_status
+        )
+        logger.info(f'{device_id} - {speed_value_dict.get(regulated_fcu.air_valve_speed)}')

+ 5 - 1
app/core/events.py

@@ -8,7 +8,9 @@ from app.controllers.equipment.events import (
     regulate_ahu_freq,
     regulate_ahu_switch,
     regulate_pau_switch,
-    regulate_ventilation_fan_switch
+    regulate_ventilation_fan_switch,
+    run_control_group,
+    run_experiment_group
 )
 from app.controllers.events import load_q_learning_model
 
@@ -20,5 +22,7 @@ def create_start_app_handler(app: Optional[FastAPI] = None) -> Callable:
         await regulate_ahu_switch()
         await regulate_pau_switch()
         await regulate_ventilation_fan_switch()
+        # await run_experiment_group()
+        await run_control_group()
 
     return start_app

+ 4 - 0
app/services/platform.py

@@ -24,6 +24,7 @@ class InfoCode(str, Enum):
     supply_air_temperature = 'SupplyAirTemp'
     supply_air_temperature_set = 'SupplyAirTempSet'
     fan_speed = 'FanGear'
+    fan_speed_set = 'FanGearSet'
     fan_freq = 'FanFreq'
     fan_freq_set = 'FanFreqSet'
     supply_static_press = 'SupplyStaticPress'
@@ -34,6 +35,9 @@ class InfoCode(str, Enum):
     return_air_temperature = 'ReturnAirTemp'
     chill_water_valve_opening_set = 'ChillWaterValveOpeningSet'
     hot_water_valve_opening_set = 'HotWaterValveOpeningSet'
+    water_valve_switch_set = 'WaterValveSwitchSet'
+    in_cloud_set = 'InCloudSet'
+    work_mode_set = 'WorkModeSet'
 
 
 class DataPlatformService(Service):