transfer.py 12 KB

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