SignalMonitor.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. import datetime
  2. # import os
  3. import pandas as pd
  4. # import Tools
  5. # import sys
  6. # import xlutils
  7. from xlrd import open_workbook
  8. from xlutils.copy import copy
  9. # import CONFIGURE.PathSetting as PathSetting
  10. # sys.path.append(PathSetting.backend_path)
  11. from LIB.BACKEND import DBManager
  12. dbManager = DBManager.DBManager()
  13. class SignalMonitor():
  14. def __init__(self):
  15. pass
  16. @staticmethod
  17. def _set_working_states(df_state):
  18. for i in range(0, len(df_state)):
  19. if abs(df_state.loc[i, 'current']) >= 0.45:
  20. df_state.loc[i, 'PackState'] = 0
  21. else:
  22. df_state.loc[i, 'PackState'] = 1
  23. # path = r'D:\daily_data_analysis_01.csv'
  24. # df_state.to_csv(path, index=True, encoding='GB2312')
  25. return df_state
  26. @staticmethod
  27. def _set_standby_states(df_state):
  28. index = 0
  29. set = 0
  30. while index < len(df_state)-1:
  31. index = index + 1
  32. if set == 0:
  33. if df_state.loc[index, 'PackState'] == 1 and df_state.loc[index-1, 'PackState'] == 0:
  34. set = 1
  35. start_time = df_state.loc[index-1, 'Timestamp']
  36. timeDelta = datetime.timedelta(minutes=10)
  37. end_time = start_time + timeDelta
  38. df_state.loc[index, 'PackState'] = 0
  39. else:
  40. if df_state.loc[index, 'Timestamp'] <= end_time:
  41. df_state.loc[index, 'PackState'] = 0
  42. if abs(df_state.loc[index, 'current']) >= 0.45:
  43. start_time = df_state.loc[index-1, 'Timestamp']
  44. timeDelta = datetime.timedelta(minutes=10)
  45. end_time = start_time + timeDelta
  46. else:
  47. set = 0
  48. # path = r'D:\daily_data_analysis_02.csv'
  49. # df_state.to_csv(path, index=True, encoding='GB2312')
  50. return df_state
  51. @staticmethod
  52. def _set_lowpwr_states(df_state):
  53. index = 0
  54. set = 0
  55. while index < len(df_state)-1:
  56. index = index + 1
  57. if df_state.loc[index,'PackState'] == 1:
  58. if set ==0:
  59. start_time = df_state.loc[index,'Timestamp']
  60. timeDelta = datetime.timedelta(minutes=300)
  61. end_time = start_time + timeDelta
  62. set = 1
  63. else:
  64. if df_state.loc[index,'Timestamp'] > end_time:
  65. df_state.loc[index,'PackState'] = 2
  66. else:
  67. set = 0
  68. # path = r'D:\daily_data_analysis_03.csv'
  69. # df_state.to_csv(path, index=True, encoding='GB2312')
  70. return df_state
  71. @staticmethod
  72. def _judge_offline_state_between_messages(sn, PackState_new, PackState_old, Timestamp_new, Timestamp_old, lat, long, df_res, mode):
  73. delta_time = (Timestamp_new - Timestamp_old).total_seconds()
  74. max_state = max(PackState_new, PackState_old)
  75. if max_state == 0:
  76. if mode == 'BMS':
  77. thres1 = 60
  78. thres2 = 300
  79. elif mode == 'GPS':
  80. thres1 = 120
  81. thres2 = 600
  82. elif max_state == 1:
  83. if mode == 'BMS':
  84. thres1 = 1200
  85. thres2 = 2400
  86. elif mode == 'GPS':
  87. thres1 = 2400
  88. thres2 = 4800
  89. else:
  90. if mode == 'BMS':
  91. thres1 = 3600
  92. thres2 = 7200
  93. elif mode == 'GPS':
  94. thres1 = 7200
  95. thres2 = 14400
  96. if delta_time <= thres1:
  97. LineState = 0
  98. elif delta_time <= thres2:
  99. LineState = 1
  100. else:
  101. LineState = 2
  102. if LineState > 0:
  103. if mode == 'BMS':
  104. df_res = df_res.append({'sn':sn[0], 'PackState':PackState_new*16+PackState_old, 'LineState':LineState, 'StartTime':Timestamp_old,
  105. 'EndTime':Timestamp_new, 'OfflineTime':delta_time}, ignore_index=True)
  106. elif mode == 'GPS':
  107. df_res = df_res.append({'sn':sn[0], 'PackState':PackState_new*16+PackState_old, 'LineState':LineState, 'StartTime':Timestamp_old,
  108. 'EndTime':Timestamp_new, 'OfflineTime':delta_time, 'latitude':lat, 'longitude':long}, ignore_index=True)
  109. return LineState, df_res
  110. @staticmethod
  111. def _get_offline_info(sn, df_state, df_last_state, df_res, mode):
  112. index = 0
  113. if len(df_last_state) == 0:
  114. df_state.loc[0,'LineState'] = 0
  115. while index < len(df_state)-1:
  116. index = index + 1
  117. if mode == 'BMS':
  118. LineState, df_res = SignalMonitor._judge_offline_state_between_messages(sn, df_state.loc[index, 'PackState'], df_state.loc[index-1, 'PackState'],
  119. df_state.loc[index, 'Timestamp'], df_state.loc[index-1, 'Timestamp'], None, None,
  120. df_res, mode=mode)
  121. elif mode == 'GPS':
  122. LineState, df_res = SignalMonitor._judge_offline_state_between_messages(sn, df_state.loc[index, 'PackState'], df_state.loc[index-1, 'PackState'],
  123. df_state.loc[index, 'Timestamp'], df_state.loc[index-1, 'Timestamp'], df_state.loc[index-1, 'latitude'], df_state.loc[index-1, 'longitude'],
  124. df_res, mode=mode)
  125. df_state.loc[index, 'LineState'] = LineState
  126. else:
  127. df_last_info = df_last_state.loc[len(df_last_state) - 1]
  128. if mode == 'BMS':
  129. df_state.loc[0,'LineState'], df_res = SignalMonitor._judge_offline_state_between_messages(sn, df_state.loc[0, 'PackState'], df_last_info['PackState'],
  130. df_state.loc[0, 'Timestamp'], df_last_info['Timestamp'], None, None,
  131. df_res, mode=mode)
  132. elif mode == 'GPS':
  133. df_state.loc[0,'LineState'], df_res = SignalMonitor._judge_offline_state_between_messages(sn, df_state.loc[0, 'PackState'], df_last_info['PackState'],
  134. df_state.loc[0, 'Timestamp'], df_last_info['Timestamp'], df_state.loc[0, 'latitude'], df_state.loc[0, 'longitude'],
  135. df_res, mode=mode)
  136. while index < len(df_state)-1:
  137. index = index + 1
  138. if mode == 'BMS':
  139. LineState, df_res = SignalMonitor._judge_offline_state_between_messages(sn, df_state.loc[index, 'PackState'], df_state.loc[index-1, 'PackState'],
  140. df_state.loc[index, 'Timestamp'], df_state.loc[index-1, 'Timestamp'], None, None,
  141. df_res, mode=mode)
  142. elif mode == 'GPS':
  143. LineState, df_res = SignalMonitor._judge_offline_state_between_messages(sn, df_state.loc[index, 'PackState'], df_state.loc[index-1, 'PackState'],
  144. df_state.loc[index, 'Timestamp'], df_state.loc[index-1, 'Timestamp'], df_state.loc[index-1, 'latitude'], df_state.loc[index-1, 'longitude'],
  145. df_res, mode=mode)
  146. df_state.loc[index, 'LineState'] = LineState
  147. # SignalMonitor._file_write(r'D:\result_03.xls', df_state)
  148. return df_res
  149. @staticmethod
  150. def _set_gps_working_states(df_state, df_state_gps):
  151. for i in range(0, len(df_state_gps)):
  152. if df_state_gps.loc[i, 'Timestamp'] <= df_state.loc[0, 'Timestamp']:
  153. df_state_gps.loc[i, 'PackState'] = df_state.loc[0, 'PackState']
  154. elif df_state_gps.loc[i, 'Timestamp'] >= df_state.loc[len(df_state)-1, 'Timestamp']:
  155. df_state_gps.loc[i:len(df_state_gps)-1, 'PackState'] = df_state.loc[len(df_state)-1, 'PackState']
  156. break
  157. else:
  158. index0 = max(df_state[df_state['Timestamp'] <= df_state_gps.loc[i, 'Timestamp']].index)
  159. index1 = min(df_state[df_state['Timestamp'] >= df_state_gps.loc[i, 'Timestamp']].index)
  160. front = (df_state_gps.loc[i, 'Timestamp'] - df_state.loc[index0, 'Timestamp']).total_seconds()
  161. back = (df_state.loc[index1, 'Timestamp'] - df_state_gps.loc[i, 'Timestamp']).total_seconds()
  162. if front > back:
  163. df_state_gps.loc[i, 'PackState'] = df_state.loc[index1, 'PackState']
  164. elif front == back:
  165. df_state_gps.loc[i, 'PackState'] = max(df_state.loc[index1, 'PackState'], df_state.loc[index0, 'PackState'])
  166. else:
  167. df_state_gps.loc[i, 'PackState'] = df_state.loc[index0, 'PackState']
  168. return df_state_gps
  169. @staticmethod
  170. def _file_write(path, df_res):
  171. r_xls = open_workbook(path) # 读取excel文件
  172. sheet = len(r_xls.sheets())
  173. row = r_xls.sheets()[sheet-1].nrows # 获取已有的行数
  174. excel = copy(r_xls) # 将xlrd的对象转化为xlwt的对象
  175. table = excel.get_sheet(sheet-1) # 获取要操作的sheet
  176. #对excel表追加一行内容
  177. # print(row)
  178. current_row = row
  179. num = len(df_res.columns)
  180. for i in range(0, len(df_res)):
  181. for j in range(0, num):
  182. table.write(current_row, j, df_res.iloc[i][j]) #括号内分别为行数、列数、内容
  183. current_row = current_row + 1
  184. if current_row == 65500:
  185. table = r_xls.add_sheet('sheet'+ str(sheet))
  186. sheet = sheet + 1
  187. current_row = 0
  188. excel.save(path) # 保存并覆盖文件
  189. def get_bms_offline_stat(self, sn, st, et, df_res, df_last_state, cal_Period=24): # 计算一段时间内BMS信号统计数据
  190. df_state = pd.DataFrame(columns=['sn', 'current', 'Timestamp', 'PackState', 'LineState'])
  191. # print("start_time is {}, limit_time is {}".format(st, limit_time))
  192. relative_delta_time = datetime.timedelta(hours=6) # 将时间往前推nh,以便更准确计算BMS状态
  193. end_time = st + datetime.timedelta(hours=cal_Period) # 结束时间
  194. relative_time = st - relative_delta_time
  195. relative_time = relative_time.strftime('%Y-%m-%d %H:%M:%S')
  196. end_time_str = end_time.strftime('%Y-%m-%d %H:%M:%S')
  197. df_data = dbManager.get_data(sn=sn[0], start_time=relative_time, end_time=end_time_str, data_groups=['bms'])
  198. df_bms = df_data['bms']
  199. df_bms = df_bms.drop_duplicates(['时间戳'])
  200. df_bms = df_bms.reset_index(drop=True)
  201. df_bms['时间戳'] = pd.to_datetime(df_bms['时间戳'])
  202. print('{} BMS data read Well Done!'.format(sn[0]))
  203. df_state['current'] = df_bms['总电流[A]']
  204. df_state['Timestamp'] = df_bms['时间戳']
  205. df_state['sn'] = sn[0]
  206. if len(df_state[df_state['Timestamp'] >= st]) > 0: # 无数据则不计算
  207. df_state = SignalMonitor._set_working_states(df_state) # 根据电流初步定义BMS状态
  208. if len(df_state) > 1:
  209. df_state = SignalMonitor._set_standby_states(df_state) # 根据静置时间修正standby状态
  210. df_state = SignalMonitor._set_lowpwr_states(df_state) # 根据静置持续时间设置lowpwr状态
  211. df_state_spec = df_state[df_state['Timestamp'] >= st]
  212. df_state_spec = df_state_spec.reset_index(drop=True) # 去除为准确计算BMS状态而多获取的数据
  213. df_res = SignalMonitor._get_offline_info(sn, df_state_spec, df_last_state, df_res, 'BMS') # 计算设定时间段内信号质量数据
  214. df_last_info = df_state_spec.loc[len(df_state_spec) - 1]
  215. df_last_state = df_last_state.append(df_last_info) # 记录该段时间内最后数据
  216. df_last_state = df_last_state.reset_index(drop=True)
  217. return df_res,df_state, df_last_state
  218. def get_gps_offline_stat(self,sn, st, et, df_state, df_res_gps, df_last_state_gps, cal_Period=24): # 计算一段时间内GPS信号统计数据
  219. df_state_gps = pd.DataFrame(columns=['sn', 'Timestamp', 'PackState', 'LineState', 'latitude', 'longitude'])
  220. # print("start_time is {}, limit_time is {}".format(st, limit_time))
  221. end_time = st + datetime.timedelta(hours=cal_Period) # 结束时间
  222. start_time_str = st.strftime('%Y-%m-%d %H:%M:%S')
  223. end_time_str = end_time.strftime('%Y-%m-%d %H:%M:%S')
  224. df_data = dbManager.get_data(sn=sn[0], start_time=start_time_str, end_time=end_time_str, data_groups=['gps'])
  225. df_gps = df_data['gps']
  226. df_gps = df_gps.drop_duplicates(['时间戳'])
  227. df_gps = df_gps.reset_index(drop=True)
  228. df_gps['时间戳'] = pd.to_datetime(df_gps['时间戳'])
  229. print('{} GPS data read Well Done!'.format(sn[0]))
  230. df_state_gps['Timestamp'] = df_gps['时间戳']
  231. df_state_gps['sn'] = sn[0]
  232. df_state_gps['latitude'] = df_gps['纬度']
  233. df_state_gps['longitude'] = df_gps['经度']
  234. if len(df_state_gps) > 0: # 无数据则不计算
  235. df_state_gps = SignalMonitor._set_gps_working_states(df_state, df_state_gps) # 根据同时间段内BMS状态计算GPS数据对应的BMS状态
  236. df_res_gps = SignalMonitor._get_offline_info(sn, df_state_gps, df_last_state_gps, df_res_gps, 'GPS') # 计算设定时间段内信号质量数据
  237. df_last_info = df_state_gps.loc[len(df_state_gps) - 1]
  238. df_last_state_gps = df_last_state_gps.append(df_last_info) # 记录该段时间内最后数据
  239. df_last_state_gps = df_last_state_gps.reset_index(drop=True)
  240. return df_res_gps, df_last_state_gps