CBMSSafetyAlarm.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. import pandas as pd
  2. import numpy as np
  3. import datetime
  4. from LIB.MIDDLE.CellStateEstimation.Common.V1_0_1 import BatParam
  5. class SafetyAlarm:
  6. def __init__(self,sn,celltype,df_bms,df_bms_ram_sn,df_alarm_ram_sn): #参数初始化
  7. self.sn=sn
  8. self.celltype=celltype
  9. self.param=BatParam.BatParam(celltype)
  10. self.df_bms=df_bms
  11. self.df_ram_bms=df_bms_ram_sn.copy()
  12. df_bms['时间戳']=pd.to_datetime(df_bms['时间戳'], format='%Y-%m-%d %H:%M:%S')
  13. self.df_ram_alarm=df_alarm_ram_sn.copy()
  14. if (not df_bms_ram_sn.empty) and (not self.df_bms.empty):
  15. self.df_bms=self.df_bms[self.df_bms['时间戳'] > df_bms_ram_sn.iloc[-1]['time']] #滤除原始数据中的重复数据
  16. self.df_bms.reset_index(inplace=True,drop=True) #重置索引
  17. self.packcrnt=df_bms['总电流[A]']*self.param.PackCrntDec
  18. self.packvolt=df_bms['总电压[V]']
  19. self.bmstime= df_bms['时间戳']
  20. self.cellvolt_name=['单体电压'+str(x) for x in range(1,self.param.CellVoltNums+1)]
  21. # othertemp=['其他温度'+str(x) for x in range(1,self.param.OtherTempNums+1)]
  22. self.celltemp_name=['单体温度'+str(x) for x in range(1,self.param.CellTempNums+1)]
  23. # self.celltemp_name=celltemp+othertemp
  24. def safety_alarm_diag(self):
  25. if self.celltype<=50:
  26. df_res=self._alarm_diag()
  27. return df_res
  28. else:
  29. df_res=self._alarm_diag()
  30. return df_res
  31. #定义滑动滤波函数.............................................................................................
  32. def _np_move_avg(self,a, n, mode="same"):
  33. return (np.convolve(a, np.ones((n,)) / n, mode=mode))
  34. #寻找当前行数据的所有温度值...................................................................................
  35. def _celltemp_get(self,num):
  36. celltemp = np.array(self.df_bms.loc[num,self.celltemp_name])
  37. return celltemp
  38. #获取当前行所有电压数据............................................................................................
  39. def _cellvolt_get(self,num):
  40. cellvolt = np.array(self.df_bms.loc[num,self.cellvolt_name]/1000)
  41. return cellvolt
  42. #..........................................三元电池诊断功能..................................................................
  43. def _alarm_diag(self):
  44. df_res=pd.DataFrame(columns=['start_time', 'end_time', 'product_id', 'code', 'level', 'info','advice'])
  45. end_time='0000-00-00 00:00:00'
  46. time_now=datetime.datetime.now()
  47. celltemprise=0
  48. celltemphigh=0
  49. cellvoltfall=0
  50. packvoltfall=0
  51. if not self.df_ram_alarm.empty:
  52. safetywarning1=self.df_ram_alarm.iloc[-1]['safetywarning1']
  53. safetywarning2=self.df_ram_alarm.iloc[-1]['safetywarning2']
  54. else:
  55. safetywarning1=0
  56. safetywarning2=0
  57. if not self.df_bms.empty:
  58. for i in range(len(self.df_bms)):
  59. #温度诊断功能.............................................................................................................
  60. if i<1:
  61. if not self.df_ram_bms.empty:
  62. temp1=self.df_ram_bms.iloc[-1]['celltemp']
  63. temp2=self._celltemp_get(i)
  64. time1=self.df_ram_bms.iloc[-1]['time']
  65. time2=self.bmstime[i]
  66. else:
  67. temp1=self._celltemp_get(i)
  68. temp2=self._celltemp_get(i)
  69. time1=self.bmstime[i]-datetime.timedelta(seconds=10)
  70. time2=self.bmstime[i]
  71. else:
  72. temp1=self._celltemp_get(i-1)
  73. temp2=self._celltemp_get(i)
  74. time1=self.bmstime[i-1]
  75. time2=self.bmstime[i]
  76. temp1=temp1[np.where((temp1<self.param.CellTempUpLmt) & (temp1>self.param.CellTempLwLmt))]
  77. temp2=temp2[np.where((temp2<self.param.CellTempUpLmt) & (temp2>self.param.CellTempLwLmt))]
  78. #温度有效性判断...........................................................................
  79. if len(temp1)>0.5 and len(temp2)>0.5 and len(temp1)==len(temp2):
  80. celltempvalid=1
  81. else: #不作处理
  82. celltempvalid=0
  83. if celltempvalid==1:
  84. celltempmax=max(temp2)
  85. #过温判断............................................................................................................................
  86. if celltempmax>self.param.TrwTempHigh:
  87. celltemphigh=1
  88. else:
  89. pass
  90. #温升判断.............................................................................................................................
  91. delttime=(time2-time1).total_seconds()
  92. if delttime>1:
  93. celltemp_rate=(max(temp2-temp1)*60)/delttime #计算最大温升速率
  94. else:
  95. celltemp_rate=0
  96. if celltemp_rate>self.param.TrwTempRate and self.param.CellTempLwLmt<min(temp1) and max(temp1)<self.param.CellTempUpLmt:
  97. celltemprise=celltemprise+1
  98. else:
  99. pass
  100. else:
  101. pass
  102. #电压诊断功能.........................................................................................................................................
  103. if i<1:
  104. cellvolt2=self._cellvolt_get(i)
  105. time2=self.bmstime[i]
  106. if not self.df_ram_bms.empty:
  107. cellvolt1=self.df_ram_bms.iloc[-1]['cellvolt']
  108. time1=self.df_ram_bms.iloc[-1]['time']
  109. else:
  110. cellvolt1=cellvolt2
  111. time1=time2
  112. else:
  113. cellvolt2=self._cellvolt_get(i)
  114. cellvolt1=self._cellvolt_get(i-1)
  115. time2=self.bmstime[i]
  116. time1=self.bmstime[i-1]
  117. #电压有效性..........................................................................................................................................
  118. cellvoltmin2=min(cellvolt2)
  119. cellvoltmax2=max(cellvolt2)
  120. cellvoltmin_index2=list(cellvolt2).index(cellvoltmin2)
  121. cellvoltmax_index2=list(cellvolt2).index(cellvoltmax2)
  122. cellvoltmin1=min(cellvolt1)
  123. cellvoltmax1=max(cellvolt1)
  124. cellvoltmin_index1=list(cellvolt1).index(cellvoltmin1)
  125. cellvoltmax_index1=list(cellvolt1).index(cellvoltmax1)
  126. if (cellvoltmin2<2 and cellvoltmax2>4.5 and abs(cellvoltmax_index2-cellvoltmin_index2)==1) or (cellvoltmin1<2 and cellvoltmax1>4.5 and abs(cellvoltmax_index1-cellvoltmin_index1)==1): #电压断线故障进入
  127. cellvoltvalid=0
  128. else:
  129. cellvolt1=cellvolt1[np.where((cellvolt1>0.01) & (cellvolt1<4.5))]
  130. cellvolt2=cellvolt2[np.where((cellvolt2>0.01) & (cellvolt2<4.5))]
  131. if len(cellvolt1)>1 and len(cellvolt2)>1 and len(cellvolt1)==len(cellvolt2):
  132. cellvoltvalid=1
  133. else:
  134. cellvoltvalid=0
  135. if cellvoltvalid==1:
  136. #单体电压跌落诊断...........................................................................................................................
  137. delttime=(time2-time1).total_seconds()
  138. if delttime<360:
  139. if self.packcrnt[i]<0.5 and max(cellvolt1-cellvolt2)>self.param.TrwCellVoltFall:
  140. cellvoltfall=cellvoltfall+1
  141. elif self.packcrnt[i]>0.5 and max(cellvolt1-cellvolt2)-self.packcrnt[i]*0.01>self.param.TrwCellVoltFall:
  142. cellvoltfall=cellvoltfall+1
  143. else:
  144. pass
  145. else:
  146. pass
  147. else:
  148. pass
  149. #电池包诊断.....................................................................................................................................
  150. packvolt2=self.packvolt[i]
  151. #电池包电压有效性............................................................................................................................
  152. if self.param.CellVoltNums<packvolt2<self.param.CellVoltNums*4.5:
  153. packvoltvalid=1
  154. else:
  155. packvoltvalid=0
  156. if packvoltvalid==1:
  157. if i<1:
  158. if not self.df_ram_bms.empty:
  159. time1=self.df_ram_bms.iloc[-1]['time']
  160. time2=self.bmstime[i]
  161. delttime=(time2-time1).total_seconds()
  162. packvolt1=self.df_ram_bms.iloc[-1]['packvolt']
  163. if delttime<360:
  164. if self.packcrnt[i]<5 and (packvolt1-packvolt2)>self.param.TrwPackVoltFall and self.param.CellVoltNums<packvolt1<self.param.CellVoltNums*4.5:
  165. packvoltfall=packvoltfall+1
  166. else:
  167. pass
  168. else:
  169. pass
  170. else:
  171. pass
  172. else:
  173. packvolt1=self.packvolt[i-1]
  174. if self.packcrnt[i]<5 and (packvolt1-packvolt2)>self.param.TrwPackVoltFall and self.param.CellVoltNums<packvolt1<self.param.CellVoltNums*4.5:
  175. packvoltfall=packvoltfall+1
  176. else:
  177. pass
  178. else:
  179. pass
  180. #热失控故障判断........................................................................................................................
  181. df_bms_ram=pd.DataFrame(columns=['time', 'sn', 'packvolt', 'cellvolt', 'celltemp'])
  182. df_bms_ram.loc[0]=[self.bmstime[0], self.sn, packvolt2, cellvolt2, temp2]
  183. df_ram_alarm=self.df_ram_alarm
  184. trwtemp=max(celltemprise,celltemphigh)
  185. trwcellvolt=cellvoltfall
  186. trwpackvolt=packvoltfall
  187. trw_array=np.array([trwtemp, trwcellvolt, trwpackvolt])
  188. if np.sum(trw_array)>3.5 and np.sum(trw_array>0.5)>1.5:
  189. fltcode='C599'
  190. df_res.loc[0]=[self.bmstime[len(self.bmstime)-1], end_time, self.sn, fltcode, 5, '电池发生热失控', '联系用户立即远离电池,并通知技术人员介入']
  191. df_ram_alarm=pd.DataFrame(columns=['sn','time','safetywarning1','safetywarning2'])
  192. elif safetywarning1>2.5 and np.sum(trw_array)>1.5 and np.sum(trw_array>0.5)>1.5:
  193. fltcode='C599'
  194. df_res.loc[0]=[self.bmstime[len(self.bmstime)-1], end_time, self.sn, fltcode, 5, '电池发生热失控', '联系用户立即远离电池,并通知技术人员介入']
  195. df_ram_alarm=pd.DataFrame(columns=['sn','time','safetywarning1','safetywarning2'])
  196. else:
  197. df_res=pd.DataFrame()
  198. #更新df_ram_alarm信息
  199. if np.sum(trw_array)>1.5 and np.sum(trw_array>0.5)>1.5:
  200. safetywarning1=3
  201. df_ram_alarm.loc[0]=[self.sn,time2,safetywarning1,safetywarning2]
  202. else:
  203. safetywarning1=0
  204. df_ram_alarm=pd.DataFrame(columns=['sn','time','safetywarning1','safetywarning2'])
  205. if max(cellvolt2)>5 or min(cellvolt2)<1:
  206. safetywarning2=3
  207. df_ram_alarm.loc[0]=[self.sn,time2,safetywarning1,safetywarning2]
  208. elif max(cellvolt2)<4.5 and min(cellvolt2)>2.5:
  209. safetywarning2=0
  210. if safetywarning1==0:
  211. df_ram_alarm=pd.DataFrame(columns=['sn','time','safetywarning1','safetywarning2'])
  212. else:
  213. df_ram_alarm.loc[0]=[self.sn,time2,safetywarning1,safetywarning2]
  214. else:
  215. df_ram_alarm.loc[0]=[self.sn,time2,safetywarning1,safetywarning2]
  216. return df_res, df_bms_ram, df_ram_alarm
  217. else:
  218. df_ram_alarm=self.df_ram_alarm
  219. df_ram_bms=self.df_ram_bms
  220. if (safetywarning1>2.5 or safetywarning2>2.5) and (time_now-df_ram_alarm.iloc[-1]['time']).total_seconds()>120:
  221. fltcode='C599'
  222. time_now=time_now.strftime('%Y-%m-%d %H:%M:%S')
  223. time_now=datetime.datetime.strptime(time_now,'%Y-%m-%d %H:%M:%S')
  224. df_res.loc[0]=[time_now, end_time, self.sn, fltcode, 5, '电池发生热失控', '联系用户立即远离电池,并通知技术人员介入']
  225. df_ram_alarm=pd.DataFrame(columns=['sn','time','safetywarning1','safetywarning2'])
  226. else:
  227. df_res=pd.DataFrame()
  228. return df_res, df_ram_bms, df_ram_alarm