ソースを参照

Merge branch 'dev'

highing666 2 年 前
コミット
ce9cd18408

+ 7 - 1
app/api/routers/devices.py

@@ -12,6 +12,7 @@ from app.controllers.equipment.ahu.supply_air_temperature_set import (
 )
 from app.controllers.equipment.ahu.switch import build_acatah_switch_set
 from app.controllers.equipment.ahu.thermal_mode import build_acatah_thermal_mode_set
+from app.controllers.equipment.ashp.basic import build_ashp_instructions
 from app.controllers.equipment.fcu.basic import (
     build_acatfc2_instructions,
     build_acatfc4_instructions,
@@ -334,4 +335,9 @@ async def get_acatva_instructions_v2(
 
 @router.post("/instructions/ashp", response_model=domain_devices.ASHPResponse)
 async def get_ashp_instructions(params: domain_devices.ASHPRequest):
-    pass
+    instructions = await build_ashp_instructions(params)
+
+    logger.info(params)
+    logger.debug(instructions)
+
+    return instructions

+ 152 - 55
app/controllers/equipment/ashp/basic.py

@@ -1,81 +1,141 @@
 # -*- coding: utf-8 -*-
 
-from typing import List, Tuple
+from typing import Dict, List, Tuple
 
 import arrow
 import numpy as np
 
+from app.api.errors.iot import MissingIOTDataError
+from app.models.domain.devices import ASHPRequest
 from app.schemas.equipment import ASHP
+from app.schemas.season import Season
 
 
 class ASHPGroupController:
-    def __init__(self, ashp_list: List[ASHP], outdoor_temp_list: List[float]):
+    def __init__(self, ashp_list: List[ASHP], outdoor_temp_list: List[float], season: Season):
+        self._season = season
         self._ashp_list = ashp_list
         self._outdoor_temp_list = outdoor_temp_list
+        self._interval = 0
         self._is_warning = False
 
-    def initialization(self) -> Tuple[float, float, float]:
-        if self._outdoor_temp_list:
-            outdoor_temp_avg = np.mean(self._outdoor_temp_list)
-        else:
-            outdoor_temp_avg = 22.0
-
-        total_device_num = len(self._ashp_list)
-        if outdoor_temp_avg <= 20.0:
-            device_num = 1
-            out_temp_set = 10.0
-            interval = 45 * 60
-        elif outdoor_temp_avg < 24.0:
-            device_num = total_device_num // 3
-            out_temp_set = 9.0
-            interval = 0
+    def initialization(self) -> Tuple[float, float]:
+        if self._season == Season.cooling:
+            if self._outdoor_temp_list:
+                outdoor_temp_avg = np.mean(self._outdoor_temp_list)
+            else:
+                outdoor_temp_avg = 22.0
+
+            total_device_num = len(self._ashp_list)
+            if outdoor_temp_avg <= 20.0:
+                device_num = 1
+                out_temp_set = 10.0
+                interval = 45 * 60
+            elif outdoor_temp_avg < 24.0:
+                device_num = total_device_num // 3
+                out_temp_set = 9.0
+                interval = 0
+            else:
+                device_num = total_device_num // 3 + 1
+                out_temp_set = 8.5
+                interval = 0
+
+            if self._outdoor_temp_list:
+                if np.max(self._outdoor_temp_list) > 34.0:
+                    device_num += 1
+                    device_num = min(device_num, total_device_num - 1)
+        elif self._season == Season.heating:
+            if self._outdoor_temp_list:
+                outdoor_temp_avg = np.mean(self._outdoor_temp_list)
+            else:
+                outdoor_temp_avg = -10.0
+
+            total_device_num = len(self._ashp_list)
+            if outdoor_temp_avg >= 0.0:
+                device_num = 1
+                out_temp_set = 45.0
+                interval = 45 * 60
+            elif outdoor_temp_avg > -15.0:
+                device_num = total_device_num // 3
+                out_temp_set = 45.0
+                interval = 0
+            else:
+                device_num = total_device_num // 3 + 1
+                out_temp_set = 50.0
+                interval = 0
+
+            if self._outdoor_temp_list:
+                if np.min(self._outdoor_temp_list) < -15.0:
+                    device_num += 1
+                    device_num = min(device_num, total_device_num - 1)
         else:
-            device_num = total_device_num // 3 + 1
-            out_temp_set = 8.5
+            device_num = 0
             interval = 0
+            out_temp_set = np.NAN
 
-        if self._outdoor_temp_list:
-            if np.max(self._outdoor_temp_list) > 34.0:
-                device_num += 1
-                device_num = min(device_num, total_device_num - 1)
+        self._interval = interval
 
-        return device_num, out_temp_set, interval
+        return device_num, out_temp_set
 
-    def device_num_adjustment(self) -> float:
-        out_temp_15_avg = np.mean([np.mean(device.out_temp_15min) for device in self._ashp_list])
-        out_temp_set_15_avg = np.mean([np.mean(device.out_temp_set_15min) for device in self._ashp_list])
-        iplr_15_avg = np.mean([np.mean(device.iplr_15min) for device in self._ashp_list])
+    def device_num_adjustment(self) -> Tuple[float, float]:
+        out_temp_15_avg = np.mean(
+            [np.mean(device.out_temp_15min) for device in self._ashp_list if device.running_status])
+        out_temp_set_15_avg = np.mean(
+            [np.mean(device.out_temp_set_15min) for device in self._ashp_list if device.running_status])
+        iplr_15_avg = np.mean([np.mean(device.iplr_15min) for device in self._ashp_list if device.running_status])
 
-        out_temp_30_avg = np.mean([np.mean(device.out_temp_30min) for device in self._ashp_list])
-        out_temp_set_30_avg = np.mean([np.mean(device.out_temp_set_30min) for device in self._ashp_list])
-        iplr_30_avg = np.mean([np.mean(device.iplr_30min) for device in self._ashp_list])
+        out_temp_30_avg = np.mean(
+            [np.mean(device.out_temp_30min) for device in self._ashp_list if device.running_status])
+        out_temp_set_30_avg = np.mean(
+            [np.mean(device.out_temp_set_30min) for device in self._ashp_list if device.running_status])
+        iplr_30_avg = np.mean([np.mean(device.iplr_30min) for device in self._ashp_list if device.running_status])
 
         device_num_diff = 0
-        if out_temp_15_avg > out_temp_set_15_avg + 1 and iplr_15_avg > 0.85:
-            device_num_diff = 1
-        if out_temp_30_avg > out_temp_set_30_avg + 1 and iplr_30_avg <= 0.85:
-            device_num_diff = 1
-            self._is_warning = True
-
-        if out_temp_15_avg <= out_temp_set_15_avg + 0.3 and iplr_15_avg < 0.6:
-            device_num_diff = -1
-
-        return device_num_diff
+        if self._season == Season.cooling:
+            if out_temp_15_avg < out_temp_set_15_avg - 1 and iplr_15_avg > 0.85:
+                device_num_diff = 1
+            if out_temp_30_avg > out_temp_set_30_avg + 1 and iplr_30_avg <= 0.85:
+                device_num_diff = 1
+                self._is_warning = True
+
+            if out_temp_15_avg >= out_temp_set_15_avg and iplr_15_avg < 0.6:
+                device_num_diff = -1
+        elif self._season == Season.heating:
+            if out_temp_15_avg > out_temp_set_15_avg + 1 and iplr_15_avg > 0.85:
+                device_num_diff = 1
+            if out_temp_30_avg > out_temp_set_30_avg + 1 and iplr_30_avg <= 0.85:
+                device_num_diff = 1
+                self._is_warning = True
+
+            if out_temp_15_avg <= out_temp_set_15_avg + 0.3 and iplr_15_avg < 0.6:
+                device_num_diff = -1
+
+        return device_num_diff, float(out_temp_set_30_avg)
 
     def out_temp_set_adjustment(self) -> float:
         out_temp_set = np.NAN
         if self._outdoor_temp_list:
             current_outdoor_temp = self._outdoor_temp_list[-1]
-            if current_outdoor_temp >= 30.0:
-                out_temp_set = 8.0
-            elif current_outdoor_temp >= 28.0:
-                out_temp_set = 8.5
-            elif current_outdoor_temp >= 26.0:
-                out_temp_set = 9.0
-            elif current_outdoor_temp > 22.0:
-                out_temp_set = 10.0
-            else:
-                out_temp_set = 11.0
+            if self._season == Season.cooling:
+                if current_outdoor_temp >= 30.0:
+                    out_temp_set = 8.0
+                elif current_outdoor_temp >= 28.0:
+                    out_temp_set = 8.5
+                elif current_outdoor_temp >= 26.0:
+                    out_temp_set = 9.0
+                elif current_outdoor_temp > 22.0:
+                    out_temp_set = 10.0
+                else:
+                    out_temp_set = 11.0
+            elif self._season == Season.heating:
+                if current_outdoor_temp > 10.0:
+                    out_temp_set = 40.0
+                elif current_outdoor_temp >= 0.0:
+                    out_temp_set = 45.0
+                elif current_outdoor_temp > -10.0:
+                    out_temp_set = 50.0
+                else:
+                    out_temp_set = 55.0
 
         return out_temp_set
 
@@ -97,19 +157,56 @@ class ASHPGroupController:
 
         if not np.isnan(out_temp_set):
             for device in self._ashp_list:
-                if device.running_status or device.equip_switch_set:
+                if device.equip_switch_set:
                     device.out_temp_set = out_temp_set
 
+    def turn_off_all(self):
+        for device in self._ashp_list:
+            device.equip_switch_set = False
+
+    def antifreeze(self):
+        pass
+
     def run(self):
         t = arrow.utcnow()
+        on_time = arrow.get(self._ashp_list[0].on_time, 'HHmmss')
+        off_time = arrow.get(self._ashp_list[0].off_time, 'HHmmss')
+        if off_time.hour > on_time.hour:
+            if not on_time.hour < t.hour < off_time.hour:
+                self.turn_off_all()
+                return
+        else:
+            if off_time.hour < t.hour < on_time.hour:
+                self.turn_off_all()
+                return
+
         if t.minute < 30:
             if t.hour == 1:
                 if not np.any([device.running_status for device in self._ashp_list]):  # no device is running
-                    device_num_diff, out_temp_set, interval = self.initialization()
+                    device_num_diff, out_temp_set = self.initialization()
                     self.build_up(device_num_diff, out_temp_set)
             else:
-                device_num_diff = self.device_num_adjustment()
-                self.build_up(device_num_diff, np.NAN)
+                device_num_diff, out_temp_set = self.device_num_adjustment()
+                self.build_up(device_num_diff, out_temp_set)
         else:
             out_temp_set = self.out_temp_set_adjustment()
             self.build_up(0, out_temp_set)
+
+    def get_results(self) -> Tuple[List[ASHP], float, bool]:
+        return self._ashp_list, self._interval, self._is_warning
+
+
+async def build_ashp_instructions(params: ASHPRequest) -> Dict:
+    controller = ASHPGroupController(params.device_list, params.outdoor_temp, params.season)
+    try:
+        controller.run()
+    except (TypeError, IndexError):
+        raise MissingIOTDataError
+    device_list, interval, is_warning = controller.get_results()
+    instructions = {
+        "device_list": device_list,
+        "interval": interval,
+        "is_warning": is_warning
+    }
+
+    return instructions

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

@@ -304,6 +304,7 @@ class ACATFUFreqSetResponse(BaseModel):
 
 
 class ASHPRequest(BaseModel):
+    season: Season
     outdoor_temp: List[float]  # 30min
     device_list: List[ASHP]
 

+ 1 - 1
docker-compose.yml

@@ -2,7 +2,7 @@ version: "3"
 
 services:
   app:
-      image: registry.persagy.com/sagacloud/saga_algo_api:0.4.13
+      image: registry.persagy.com/sagacloud/saga_algo_api:0.4.14
       container_name: saga_algo_api
       ports:
         - "8002:8002"