transfer.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. # -*- coding: utf-8 -*-
  2. from enum import Enum
  3. import time
  4. from typing import Dict, List
  5. import arrow
  6. import httpx
  7. import numpy as np
  8. import pandas as pd
  9. from httpx import AsyncClient, URL
  10. from loguru import logger
  11. from app.core.config import settings
  12. from app.services.service import Service
  13. from app.utils.date import get_time_str, TIME_FMT
  14. from app.utils.math import round_half_up
  15. class Season(str, Enum):
  16. cooling = "Cooling"
  17. heating = "Warm"
  18. transition = "Transition"
  19. class SpaceInfoService(Service):
  20. def __init__(
  21. self,
  22. client: AsyncClient,
  23. project_id: str,
  24. space_id: str,
  25. server_settings=settings,
  26. ) -> None:
  27. super(SpaceInfoService, self).__init__(client)
  28. self._project_id = project_id
  29. self._space_id = space_id
  30. self._base_url = URL(server_settings.TRANSFER_HOST)
  31. self._now_time = get_time_str()
  32. def _common_parameters(self) -> Dict:
  33. return {"projectId": self._project_id, "spaceId": self._space_id}
  34. async def is_customized(self) -> bool:
  35. url = self._base_url.join("duoduo-service/custom-service/custom/timetarget")
  36. time_str = arrow.get(
  37. arrow.get(self._now_time, TIME_FMT).shift(minutes=15).timestamp()
  38. // 900
  39. * 900
  40. ).strftime("%Y%m%d%H%M%S")
  41. params = {
  42. "projectId": self._project_id,
  43. "objectId": self._space_id,
  44. "timepoint": time_str,
  45. }
  46. raw_info = await self._get(url, params)
  47. flag = False
  48. if raw_info.get("data"):
  49. flag = True
  50. return flag
  51. async def is_temporary(self) -> bool:
  52. url = self._base_url.join("duoduo-service/transfer/environment/temp/target")
  53. params = self._common_parameters()
  54. params.update({"time": self._now_time})
  55. raw_info = await self._get(url, params)
  56. flag = False
  57. if raw_info.get("flag") == 1:
  58. flag = True
  59. return flag
  60. async def get_feedback(self, wechat_time: str) -> Dict:
  61. url = self._base_url.join("duoduo-service/transfer/environment/feedbackCount")
  62. params = self._common_parameters()
  63. params.update({"time": wechat_time})
  64. raw_info = await self._get(url, params)
  65. meaning_dict = {
  66. "Id1": "a little cold",
  67. "Id2": "so cold",
  68. "Id3": "a little hot",
  69. "Id4": "so hot",
  70. "Id5": "noisy or blowy",
  71. "Id6": "so stuffy",
  72. "Id7": "more sunshine",
  73. "Id8": "less sunshine",
  74. "Id9": "send a repairman",
  75. "Id10": "switch off",
  76. "Id11": "nice",
  77. "Id12": "switch on",
  78. }
  79. feedback_dic = {
  80. meaning_dict.get(k): v for k, v in raw_info.items() if k != "result"
  81. }
  82. return feedback_dic
  83. async def get_custom_target(self) -> Dict[str, pd.DataFrame]:
  84. url = self._base_url.join(
  85. "duoduo-service/transfer/environment/normalAndPreDayTarget"
  86. )
  87. params = self._common_parameters()
  88. params.update(
  89. {"date": arrow.get(self._now_time, TIME_FMT).date().strftime("%Y%m%d")}
  90. )
  91. raw_info = await self._get(url, params)
  92. try:
  93. pre_target_df = pd.DataFrame(raw_info.get("preTargets"))
  94. pre_target_df.set_index("time", inplace=True)
  95. except (KeyError, TypeError):
  96. pre_target_df = pd.DataFrame()
  97. try:
  98. normal_target_df = pd.DataFrame(raw_info.get("normalTargets"))
  99. normal_target_df.set_index("time", inplace=True)
  100. except (KeyError, TypeError):
  101. normal_target_df = pd.DataFrame()
  102. return {"pre_targets": pre_target_df, "normal_targets": normal_target_df}
  103. async def get_current_temperature_target(self) -> float:
  104. targets = await self.get_custom_target()
  105. if len(targets.get("pre_targets")) > 0:
  106. current_targets = targets.get("pre_targets").append(
  107. targets.get("normal_targets")
  108. )
  109. else:
  110. current_targets = targets.get("normal_targets")
  111. temp = (
  112. arrow.get(self._now_time, TIME_FMT).shift(minutes=15).timestamp()
  113. // (15 * 60)
  114. * (15 * 60)
  115. )
  116. next_quarter_minutes = arrow.get(temp).time().strftime("%H%M%S")
  117. try:
  118. current_lower_target = current_targets["temperatureMin"].loc[
  119. next_quarter_minutes
  120. ]
  121. current_upper_target = current_targets["temperatureMax"].loc[
  122. next_quarter_minutes
  123. ]
  124. except KeyError:
  125. current_lower_target, current_upper_target = np.NAN, np.NAN
  126. return round_half_up((current_lower_target + current_upper_target) / 2, 2)
  127. async def env_database_set(self, form: str, value: float) -> None:
  128. url = self._base_url.join("duoduo-service/transfer/environment/hispoint/set")
  129. params = self._common_parameters()
  130. time_str = arrow.get(
  131. arrow.get(self._now_time, TIME_FMT).timestamp() // 900 * 900
  132. ).strftime("%Y%m%d%H%M%S")
  133. params.update({"time": time_str, "type": form, "value": value})
  134. await self._get(url, params)
  135. async def env_database_get(self) -> Dict[str, pd.DataFrame]:
  136. url = self._base_url.join("duoduo-service/transfer/environment/hispoint/get")
  137. params = self._common_parameters()
  138. params.update(
  139. {"date": arrow.get(self._now_time, TIME_FMT).date().strftime("%Y%m%d")}
  140. )
  141. raw_info = await self._get(url, params)
  142. result = {}
  143. if raw_info.get("result") == "success":
  144. for k, v in raw_info.items():
  145. if k != "result":
  146. if len(v) > 0:
  147. temp = {}
  148. data = np.array(v)
  149. temp.update({"timestamp": data[:, 0]})
  150. temp.update({"value": data[:, 1].astype(np.float)})
  151. result.update({k: pd.DataFrame(temp)})
  152. else:
  153. result.update({k: pd.DataFrame()})
  154. return result
  155. def set_custom_target(
  156. self, form: str, target_value: Dict[str, List[float]], flag: str = "1"
  157. ) -> None:
  158. url = self._base_url.join("duoduo-service/transfer/environment/target/setting")
  159. params = {
  160. "projectId": self._project_id,
  161. "spaceId": self._space_id,
  162. "timepoint": self._now_time,
  163. "type": form,
  164. "flag": flag,
  165. }
  166. start = time.perf_counter()
  167. httpx.post(url, params=params, json=target_value)
  168. logger.debug(time.perf_counter() - start)
  169. # await self._post(url, params=params, payload=target_value)
  170. async def set_temporary_custom(self) -> None:
  171. url = self._base_url.join("duoduo-service/transfer/environment/setServiceFlag")
  172. params = self._common_parameters()
  173. params.update({"time": self._now_time})
  174. await self._get(url, params)
  175. async def get_equipment(self) -> List[dict]:
  176. url = self._base_url.join(
  177. "duoduo-service/object-service/object/equipment/findForServe"
  178. )
  179. params = self._common_parameters()
  180. raw_info = await self._post(url, params)
  181. result = []
  182. for eq in raw_info.get("data"):
  183. result.append({"id": eq.get("id"), "category": eq.get("equipmentCategory")})
  184. return result
  185. class Duoduo(Service):
  186. def __init__(self, client: AsyncClient, project_id: str, server_settings=settings):
  187. super(Duoduo, self).__init__(client)
  188. self._project_id = project_id
  189. self._base_url = URL(server_settings.TRANSFER_HOST)
  190. self._now_time = get_time_str()
  191. async def get_season(self) -> Season:
  192. url = self._base_url.join("duoduo-service/transfer/environment/getSeasonType")
  193. params = {
  194. "projectId": self._project_id,
  195. "date": self._now_time,
  196. }
  197. raw_info = await self._get(url, params)
  198. return Season(raw_info.get("data"))
  199. async def get_fill_count(self) -> Dict:
  200. url = self._base_url.join(
  201. "duoduo-service/review-service/space/report/quarter/query"
  202. )
  203. payload = {
  204. "criteria": {
  205. "projectId": self._project_id,
  206. "date": arrow.get(self._now_time, TIME_FMT).date().strftime("%Y%m%d"),
  207. },
  208. "orders": [{"column": "time", "asc": False}],
  209. "page": 1,
  210. "size": 1,
  211. }
  212. raw_info = await self._post(url, payload=payload)
  213. try:
  214. result = raw_info.get("content")[-1]
  215. except (IndexError, TypeError):
  216. result = {}
  217. return result
  218. async def get_space_by_equipment(self, equipment_id: str) -> List[dict]:
  219. url = self._base_url.join(
  220. "duoduo-service/object-service/object/space/findForServe"
  221. )
  222. params = {"projectId": self._project_id, "objectId": equipment_id}
  223. raw_info = await self._post(url, params)
  224. result = []
  225. for sp in raw_info.get("data"):
  226. if sp.get("isControlled"):
  227. result.append({"id": sp.get("id")})
  228. return result
  229. async def get_system_by_equipment(self, equipment_id: str) -> List:
  230. url = self._base_url.join(
  231. "duoduo-service/object-service/object/system/findForCompose"
  232. )
  233. params = {"projectId": self._project_id, "equipmentId": equipment_id}
  234. raw_info = await self._post(url, params)
  235. system_list = []
  236. for sy in raw_info.get("data"):
  237. system_list.append({"id": sy.get("id")})
  238. return system_list
  239. async def get_day_type(self) -> Dict:
  240. url = self._base_url.join("duoduo-service/custom-service/custom/getDateInfo")
  241. params = {
  242. "projectId": self._project_id,
  243. "date": arrow.get(self._now_time, TIME_FMT).date().strftime("%Y%m%d"),
  244. }
  245. raw_info = await self._get(url, params)
  246. result = {
  247. "day_type": raw_info.get("dayType"),
  248. "season": raw_info.get("seasonType"),
  249. }
  250. return result
  251. async def query_device_virtual_data(self, device_id: str, info_code: str) -> float:
  252. url = self._base_url.join("duoduo-service/review-service/equipment/order/query")
  253. payload = {
  254. "criteria": {
  255. "projectId": self._project_id,
  256. "objectId": device_id,
  257. "date": arrow.get(self._now_time, TIME_FMT).date().strftime("%Y%m%d"),
  258. "funcId": info_code,
  259. }
  260. }
  261. raw_info = await self._post(url, payload=payload)
  262. try:
  263. latest_data = raw_info.get("data")[-1].get("value")
  264. latest_time = raw_info.get("data")[-1].get("realTime")
  265. if arrow.get(latest_time, TIME_FMT).shift(minutes=15) < arrow.get(
  266. self._now_time, TIME_FMT
  267. ):
  268. value = np.NAN
  269. else:
  270. value = latest_data
  271. except (KeyError, TypeError, IndexError):
  272. value = np.NAN
  273. return value
  274. async def query_fill_rate_by_device(self, device_id: str) -> [float, float]:
  275. url = self._base_url.join(
  276. "duoduo-service/review-service/space/quarter/getQueryByCategory"
  277. )
  278. payload = {
  279. "criteria": {
  280. "projectId": self._project_id,
  281. "date": arrow.get(self._now_time, TIME_FMT).date().strftime("%Y%m%d"),
  282. "eqId": device_id,
  283. }
  284. }
  285. raw_info = await self._post(url, payload=payload)
  286. try:
  287. value_info = raw_info["content"][-1]
  288. hot_count = value_info["hotSpaceNum"]
  289. cold_count = value_info["coldSpaceNum"]
  290. total = value_info["spaceNum"]
  291. hot_rate = hot_count / total
  292. cold_rate = cold_count / total
  293. except (KeyError, IndexError, ZeroDivisionError):
  294. hot_rate, cold_rate = np.NAN, np.NAN
  295. return hot_rate, cold_rate