Ver Fonte

Merge branch 'dev' of http://git.fast-fun.cn:92/lmstack/data_analyze_platform into dev

shangguanlie23 há 2 anos atrás
pai
commit
cc5af78ea3

+ 33 - 25
LIB/MIDDLE/CellStateEstimation/BatSafetyAlarm/main.py

@@ -1,4 +1,6 @@
 import CBMSSafetyAlarm
+import pymysql
+from urllib import parse
 import datetime
 import pandas as pd
 import multiprocessing
@@ -9,14 +11,33 @@ from LIB.MIDDLE.CellStateEstimation.Common.V1_0_1 import log
 
 
 #...................................电池包电芯安全诊断函数......................................................................................................................
-def diag_cal(sn_list, df_diag_ram, df_bms_ram):
-    
+def diag_cal(sn_list, df_bms_ram):
+
     start=time.time()
     now_time=datetime.datetime.now()
     start_time=now_time-datetime.timedelta(seconds=70)
     start_time=start_time.strftime('%Y-%m-%d %H:%M:%S')
     end_time=now_time.strftime('%Y-%m-%d %H:%M:%S')
 
+    #数据库配置
+    host='rm-bp10j10qy42bzy0q77o.mysql.rds.aliyuncs.com'
+    port=3306
+    user='qx_algo_readonly'
+    password = parse.quote_plus('qx@123456')
+
+    #读取故障结果库中code==119且end_time='0000-00-00 00:00:00'...............................
+    db='safety_platform'
+    mysql = pymysql.connect (host=host, user=user, password=password, port=port, database=db)
+    cursor = mysql.cursor()
+    param='start_time, end_time, product_id, code, level, info,advice'
+    tablename='all_fault_info'
+    sql =  "select %s from %s where code=119 and end_time='0000-00-00 00:00:00'" %(param,tablename)
+    cursor.execute(sql)
+    res = cursor.fetchall()
+    df_diag_ram= pd.DataFrame(res,columns=param.split(','))
+    cursor.close()
+    mysql.close()
+
     for sn in sn_list:
         if 'PK500' in sn:
             celltype=1 #6040三元电芯
@@ -37,7 +58,7 @@ def diag_cal(sn_list, df_diag_ram, df_bms_ram):
         dbManager = DBManager.DBManager()
         df_data = dbManager.get_data(sn=sn, start_time=start_time, end_time=end_time, data_groups=['bms'])
         df_bms = df_data['bms']
-        # print(df_bms)
+        print(df_bms)
 
         #电池诊断................................................................................................................................................................
         if not df_bms.empty:
@@ -47,47 +68,36 @@ def diag_cal(sn_list, df_diag_ram, df_bms_ram):
                 SafetyAlarm=CBMSSafetyAlarm.SafetyAlarm(sn,celltype,df_bms, df_bms_ram_sn)
                 df_diag_res, df_bms_res=SafetyAlarm.diag() 
 
-                #更新bms的ram数据 和 diag的Ram数据
+                #更新bms的ram数据
                 sn_index=df_bms_ram.loc[df_bms_ram['sn']==sn].index
                 df_bms_ram=df_bms_ram.drop(index=sn_index)
                 df_bms_ram=df_bms_ram.append(df_bms_res)
 
-                sn_index=df_diag_ram.loc[df_diag_ram['product_id']==sn].index
-                df_diag_ram=df_diag_ram.drop(index=sn_index)
-                df_diag_ram=df_diag_ram.append(df_diag_res)
-                df_diag_ram.reset_index(inplace=True,drop=True)     #重置索引
-
                 #当前热失控故障写入数据库
                 if not df_diag_res.empty:
                     with open(r'D:\Platform\platform_python\data_analyze_platform\USER\spf\01qixiang\06BatSafetyAlarm\热失控.txt','a') as file:
                         file.write(str(tuple(df_diag_res.iloc[-1]))+'\n')
                 
-            #当前热失控已超过三天变为历史故障并写入数据库,并删除原有数据库中的当前故障和ram中的当前故障
-            elif (now_time-df_bms_ram_sn.iloc[-1]['time']).total_seconds()>3*24*3600:
-                df_diag_ram=df_diag_ram.drop(df_diag_ram['sn']==sn)    #删除ram中的当前故障
-                df_bms_ram_sn.iloc[-1]['end_time']=now_time
+            #当前热失控已超过一天变为历史故障并更改数据库
+            elif (now_time-df_diag_ram_sn.iloc[-1]['start_time']).total_seconds()>24*3600:
+                df_diag_ram_sn.iloc[-1]['end_time']=now_time
+                df_diag_ram_sn['Batpos']=1
                 with open(r'D:\Platform\platform_python\data_analyze_platform\USER\spf\01qixiang\06BatSafetyAlarm\热失控.txt','a') as file:
                         file.write(str(tuple(df_diag_res.iloc[-1]))+'\n')
 
-
-
         #故障处理........................................................................................................................................................
-
         end=time.time()
         print(end-start)
-        # print(df_soh)
-
 #...................................................主进程...........................................................................................................
 def mainprocess():
     global SNnums
-    global df_diag_ram
     global df_bms_ram
     process = 2
     pool = multiprocessing.Pool(processes = process)
 
     for i in range(process):
         sn_list = SNnums[i]
-        pool.apply_async(diag_cal, (sn_list,df_diag_ram,df_bms_ram))
+        pool.apply_async(diag_cal, (sn_list,df_bms_ram))
 
     pool.close()
     pool.join()
@@ -110,14 +120,12 @@ if __name__ == "__main__":
     SNnums_C7255=SNdata_C7255['SN号'].tolist()
     SNnums_U7255=SNdata_U7255['SN号'].tolist()
     SNnums=[SNnums_L7255 + SNnums_C7255 + SNnums_U7255, SNnums_6040 + SNnums_4840 + SNnums_6060]
-    # SNnums=['PK50201A000002201']
+    # SNnums=[[],['PK504B00100004161']]
     
     mylog=log.Mylog('log_diag.txt','error')
     mylog.logcfg()
-
-    #............................模块运行前,先读取数据库中所有结束时间为0的数据,需要从数据库中读取...................................
-    result=pd.read_excel(r'D:\Platform\platform_python\data_analyze_platform\USER\spf\01qixiang\06BatSafetyAlarm\result.xlsx')
-    df_diag_ram=result[(result['end_time']=='0000-00-00 00:00:00') & (result['code']==119)]
+    
+    #参数初始化
     df_bms_ram=pd.DataFrame(columns=['time', 'sn', 'packvolt', 'cellvolt', 'celltemp'])
 
     #定时任务.......................................................................................................................................................................

+ 2 - 1
LIB/MIDDLE/CellStateEstimation/Common/V1_0_1/log.py

@@ -17,7 +17,8 @@ class Mylog:
                 Level=logging.WARNING
             else:
                 Level=logging.ERROR
-        logging.basicConfig(filename=r'D:\Work\Code_write\data_analyze_platform\USER\lzx\SaftyCenter_CODE_V1_1_DIDI\\'+self.name, level=Level,format='%(asctime)s - %(levelname)s - %(message)s')
+        logging.basicConfig(filename=r'D:\Platform\platform_python\data_analyze_platform\USER\spf\101log\\'+self.name, level=Level,format='%(asctime)s - %(levelname)s - %(message)s')
+
 
     def logopt(self,*info):
         logging.error(info)

+ 2 - 0
LIB/MIDDLE/SaftyCenter/Common/DBDownload.py

@@ -51,6 +51,8 @@ class DBDownload:
             self.cursor.execute("select %s from %s where factory='%s'" %(str,tablename,factory))
         elif self.mode==3:
             self.cursor.execute("select %s from %s" %(str,tablename))
+        elif self.mode==4:
+            self.cursor.execute("select %s from %s where qrcode='%s' order by id desc limit 1" %(str,tablename,sn))
         res = self.cursor.fetchall()
         df_res = pd.DataFrame(res, columns=param)
         df_res = df_res.reset_index(drop=True)

+ 37 - 40
LIB/MIDDLE/SaftyCenter/diagfault/CBMSBatDiag.py → LIB/MIDDLE/SaftyCenter/DataDiag_Static/CBMSBatDiag.py

@@ -137,12 +137,12 @@ class BatDiag:
                 delttime=(time2-time1).total_seconds()
                 if delttime>20:
                     temp2=np.array(self._celltemp_get(i))
-                    celltemp_rate=(max(temp2-temp1)*60)/delttime    #计算最大温升速率
+                    celltemp_rate=round((max(temp2-temp1)*60)/delttime,2)    #计算最大温升速率
                     temp1=temp2 #更新初始温度
                     time1=time2 #更新初始时间
-                    if celltemp_rate>self.param.CellTempRate:
-                        temprate_cnt=temprate_cnt+1
-                        if not 9 in list(self.df_diag_ram['code']):  #当前故障中没有该故障,则判断是否发生该故障
+                    if not 9 in list(self.df_diag_ram['code']):#当前故障中没有该故障,则判断是否发生该故障
+                        if celltemp_rate>self.param.CellTempRate:
+                            temprate_cnt=temprate_cnt+1
                             if temprate_cnt>2:  #温升故障进入
                                 time=self.bmstime[i]
                                 code=9
@@ -153,11 +153,11 @@ class BatDiag:
                             else:
                                 pass
                         else:   #ram当前故障中有该故障,则判断是否退出该故障
-                            if celltemp_rate<self.param.CellTempRate-1: #温升故障恢复
-                                time=self.bmstime[i]
-                                self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']==9].index, 'end_time'] = time
+                           pass
                     else:
-                        pass
+                        if celltemp_rate<self.param.CellTempRate-1: #温升故障恢复
+                            time=self.bmstime[i]
+                            self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']==9].index, 'end_time'] = time
                 else:
                     pass
             
@@ -346,46 +346,43 @@ class BatDiag:
                 pass
 
             #SOC跳变....................................................................................................................
-            if step<30: 
-                bmssoc_last=float(self.bms_soc[i-1])
-                bmssoc_now=float(self.bms_soc[i])
-                if not 28 in list(self.df_diag_ram['code']):  #当前故障中没有该故障,则判断是否发生该故障
-                    if abs(bmssoc_now-bmssoc_last)>self.param.SocJump:  #SOC跳变进入
-                        time=self.bmstime[i]
-                        code=28
-                        faultlv=1
-                        faultinfo='电池SOC跳变'
-                        faultadvice='技术介入诊断,检修电池BMS软件'
-                        self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, faultadvice]
-                    else:
-                        pass
-                else:   
-                    if abs(bmssoc_now-bmssoc_st)<self.param.SocJump:    #SOC跳变故障退出
-                        time=self.bmstime[i]
-                        self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']==28].index, 'end_time'] = time
-                    else:
-                        pass
-            else:
-                pass
-
-            #SOC过低故障报警............................................................................................................
-            if not 26 in list(self.df_diag_ram['code']):  #当前故障中没有该故障,则判断是否发生该故障
-                if self.bms_soc[i-1]<self.param.SocLow and self.bms_soc[i]<self.param.SocLow:   #SOC过低故障进入
+            bmssoc_last=float(self.bms_soc[i-1])
+            bmssoc_now=float(self.bms_soc[i])
+            if not 28 in list(self.df_diag_ram['code']):  #当前故障中没有该故障,则判断是否发生该故障
+                if step<30 and abs(bmssoc_now-bmssoc_last)>self.param.SocJump:  #SOC跳变进入
                     time=self.bmstime[i]
-                    code=26
+                    code=28
                     faultlv=1
-                    faultinfo='电池包电量过低'
-                    faultadvice='联系用户,请立刻充电'
+                    faultinfo='电池SOC跳变'
+                    faultadvice='技术介入诊断,检修电池BMS软件'
                     self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, faultadvice]
                 else:
                     pass
-            else:   
-                if self.bms_soc[i-1]>self.param.SocLow and self.bms_soc[i]>self.param.SocLow:   #SOC过低故障退出
+            else:
+                if abs(bmssoc_now-bmssoc_st)<self.param.SocJump:    #SOC跳变故障退出
                     time=self.bmstime[i]
-                    self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']==26].index, 'end_time'] = time
+                    self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']==28].index, 'end_time'] = time
                 else:
                     pass
 
+            # #SOC过低故障报警............................................................................................................
+            # if not 26 in list(self.df_diag_ram['code']):  #当前故障中没有该故障,则判断是否发生该故障
+            #     if self.bms_soc[i-1]<self.param.SocLow and self.bms_soc[i]<self.param.SocLow:   #SOC过低故障进入
+            #         time=self.bmstime[i]
+            #         code=26
+            #         faultlv=1
+            #         faultinfo='电池包电量过低'
+            #         faultadvice='联系用户,请立刻充电'
+            #         self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, faultadvice]
+            #     else:
+            #         pass
+            # else:   
+            #     if self.bms_soc[i-1]>self.param.SocLow and self.bms_soc[i]>self.param.SocLow:   #SOC过低故障退出
+            #         time=self.bmstime[i]
+            #         self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']==26].index, 'end_time'] = time
+            #     else:
+            #         pass
+
             # #BMS故障报警........................................................................................................
             # if not 1 in list(self.df_diag_ram['code']):  #当前故障中没有该故障,则判断是否发生该故障
             #     if self.bmsfault1[i-1] is None or self.bmsfault1[i] is None:
@@ -434,7 +431,7 @@ class BatDiag:
             cellsoh_lowindex=np.argwhere(cellsoh<self.param.SohLow)
             cellsoh_lowindex=cellsoh_lowindex+1
             if self.celltype==1 or self.celltype==2 or self.celltype==3 or self.celltype==4: 
-                cellsoh_diff=max(cellsoh)-min(cellsoh)
+                cellsoh_diff=np.max(cellsoh)-np.min(cellsoh)
                 if not 23 in list(self.df_diag_ram['code']):  #当前故障中没有该故障,则判断是否发生该故障
                     if soh<self.param.SohLow:   #soh过低故障进入
                         time=self.bmstime[0]

+ 34 - 13
LIB/MIDDLE/SaftyCenter/DataSta/DataStatistics.py → LIB/MIDDLE/SaftyCenter/DataDiag_Static/DataStatistics.py

@@ -10,24 +10,27 @@ from apscheduler.schedulers.blocking import BlockingScheduler
 class DataSta():
     def __init__(self) -> None:
         pass
-    def SaftyWarningSta(CS_Data,df_fltinfo,start_time,end_time):
+    def SaftyWarningSta(df_fltinfo,start_time,end_time):
+        start_time=datetime.datetime.strptime(start_time, '%Y-%m-%d')
+        start_time=start_time+datetime.timedelta(days=1)
+        start_time=start_time.strftime('%Y-%m-%d')
         SftyPlt_Data_Total=len(df_fltinfo)#总报警数
-        CS_Warning_Total_Finish=CS_Data[CS_Data['状态']=='已完结']
-        CS_Warning_Total_Finish=CS_Warning_Total_Finish[CS_Warning_Total_Finish['业务分类A']=='安全平台报警']
+        CS_Warning_Total_Finish=df_fltinfo[df_fltinfo['batpos']==1]
         CS_Warning_Total_Finish_Count=len(CS_Warning_Total_Finish) #平台报警总运维数
-        SftyPlt_Data_day=len(df_fltinfo[df_fltinfo['start_time']>=start_time])#周总报警数
-        CS_Warning_day_Finish=CS_Warning_Total_Finish[CS_Warning_Total_Finish['发生时间']>=start_time]#周运维数
+        SftyPlt_Data_day=len(df_fltinfo[df_fltinfo['start_time']>=start_time])#日、周总报警数
+        CS_Warning_day_Finish=CS_Warning_Total_Finish[CS_Warning_Total_Finish['start_time']>=start_time]#日/周运维数
         CS_Warning_day_Finish_Count=len(CS_Warning_day_Finish)
-        SftyPlt_EmgcyData_day=df_fltinfo[df_fltinfo['start_time']>=start_time] #周紧急报警数
-        SftyPlt_EmgcyData_day=len(SftyPlt_EmgcyData_day[SftyPlt_EmgcyData_day['level']>3])
-        SftyPlt_EmgcyData_day_Finish=CS_Warning_day_Finish[CS_Warning_day_Finish['运维紧急程度']=='紧急']
+        SftyPlt_EmgcyData_day=df_fltinfo[df_fltinfo['start_time']>=start_time] #紧急报警数
+        SftyPlt_EmgcyData_day=SftyPlt_EmgcyData_day[SftyPlt_EmgcyData_day['level']>3]
+        SftyPlt_EmgcyData_day_Count=len(SftyPlt_EmgcyData_day[SftyPlt_EmgcyData_day['level']>3])
+        SftyPlt_EmgcyData_day_Finish=SftyPlt_EmgcyData_day[SftyPlt_EmgcyData_day['batpos']==1]
         SftyPlt_EmgcyData_day_Finish_Count=len(SftyPlt_EmgcyData_day_Finish)
-        if SftyPlt_Data_Total>0:
+        if int(SftyPlt_Data_Total)>0:
             OprationManageRate=round(float(CS_Warning_day_Finish_Count/SftyPlt_Data_day)*100,2)
         else:
             OprationManageRate=100
-        if SftyPlt_EmgcyData_day>0:
-            OprationManageEmgcyRate=round(float(SftyPlt_EmgcyData_day_Finish_Count/SftyPlt_EmgcyData_day)*100,2)
+        if int(SftyPlt_EmgcyData_day_Count)>0:
+            OprationManageEmgcyRate=round(float(SftyPlt_EmgcyData_day_Finish_Count/SftyPlt_EmgcyData_day_Count)*100,2)
         else:
             OprationManageEmgcyRate=100
         PK504FltData_Count=len(df_fltinfo[df_fltinfo['product_id'].str.contains('PK504')])
@@ -50,7 +53,7 @@ class DataSta():
         # print('自研总报警=',MGMLXFltData_Count)
         FltAlarmInfo=DataFrame(columns=['SftyPlt_Data_Total','CS_Warning_Total_Finish_Count','SftyPlt_Data_day','CS_Warning_day_Finish_Count','SftyPlt_EmgcyData_day','SftyPlt_EmgcyData_day_Finish_Count','OprationManageRate','OprationManageEmgcyRate'])
         Celltype=DataFrame(columns=['PK504','PK502','PK500','MGMCL','MGMLX'])
-        FltAlarmInfo.loc[0]=[SftyPlt_Data_Total,CS_Warning_Total_Finish_Count,SftyPlt_Data_day,CS_Warning_day_Finish_Count,SftyPlt_EmgcyData_day,SftyPlt_EmgcyData_day_Finish_Count,OprationManageRate,OprationManageEmgcyRate]
+        FltAlarmInfo.loc[0]=[SftyPlt_Data_Total,CS_Warning_Total_Finish_Count,SftyPlt_Data_day,CS_Warning_day_Finish_Count,SftyPlt_EmgcyData_day_Count,SftyPlt_EmgcyData_day_Finish_Count,OprationManageRate,OprationManageEmgcyRate]
         Celltype.loc[0]=[PK504FltData_Count,PK502FltData_Count,PK500FltData_Count,MGMCLFltData_Count,MGMLXFltData_Count]
         return FltAlarmInfo,Celltype
     def WeekInfoSta(df_fltinfo,start_time,end_time):
@@ -58,6 +61,7 @@ class DataSta():
         FaultLvlCount=DataFrame(columns=['level','count'])
         FaultLvlCount=df_fltinfo.groupby('level').count().T.head(1).T
         FaultLvlCount=FaultLvlCount.reset_index(drop=False)
+        
         return FaultLvlCount
     def SftyWrngClsfy(df_fltinfo):
         DsnSaftyCode=[]
@@ -66,7 +70,7 @@ class DataSta():
         HvSaftyCode=[]
         SysSaftyCode=[]
         CellSaftyCode=[3,5,6,7,8,9,10,11,13,14,15,16,17,19,20,21,15,16,17,19,23,24,25,26,29,30,31,51,119]
-        CtrlSatyCode=[4,12,18,20,21,22]
+        CtrlSatyCode=[4,12,18,20,21,22,57]
         StateSaftyCode=[27,28,52]
         
         DsnSaftyCodeCount=len(df_fltinfo[df_fltinfo['code'].isin(DsnSaftyCode)])
@@ -118,3 +122,20 @@ class DataSta():
         TotalRunHour=int(deltatime['runningdate'].sum())
         return MaxAccumAh,TotalAccumAh,MaxCycle,MaxRunningHour,TotalRunHour
 
+    def FltBatPosition(df_last_pos,df_fltinfo):
+        df_Diag_Ram=df_fltinfo[df_fltinfo['batpos']==0].drop_duplicates(subset=['product_id'],keep=False)
+        all_location_info=DataFrame(columns=['factory','product_id','lat','lon'])
+        df_last_pos.rename(columns={'devcode':'product_id'},inplace=True)
+        df_Diag_Ram_Pos_a=pd.concat([df_Diag_Ram,df_last_pos]).drop_duplicates(subset=['product_id'],keep='first')
+        df_Diag_Ram_Pos_b=pd.concat([df_Diag_Ram,df_last_pos]).drop_duplicates(subset=['product_id'],keep=False)
+        df_Diag_Ram_Pos=df_Diag_Ram_Pos_a.append(df_Diag_Ram_Pos_b).drop_duplicates(subset=['product_id'],keep=False)
+        df_Diag_Ram_Pos=df_Diag_Ram_Pos.reset_index(drop=True)
+        for i in range(0,len(df_Diag_Ram_Pos)):
+            df_last_pos_list=df_last_pos['product_id'].values.tolist()
+            if  str(df_Diag_Ram_Pos.loc[i,'product_id']) in df_last_pos_list:
+                pos_la_temp=df_last_pos[df_last_pos['product_id']==(df_Diag_Ram_Pos.loc[i,'product_id'])].reset_index(drop=True)
+                all_location_info.loc[i,'lat']=pos_la_temp.loc[0,'latitude']
+                all_location_info.loc[i,'lon']=pos_la_temp.loc[0,'longitude']
+                all_location_info.loc[i,'factory']='骑享'
+                all_location_info.loc[i,'product_id']=df_Diag_Ram_Pos.loc[i,'product_id']
+        return all_location_info

+ 36 - 0
LIB/MIDDLE/SaftyCenter/DataDiag_Static/DiagDataMerge.py

@@ -0,0 +1,36 @@
+import pandas as pd
+import datacompy
+
+
+class DiagDataMerge():
+    def DetaMerge(df_Diag_Ram_sn,df_Diag_Batdiag_update,df_OprtnSta,df_Diag_Ram_sn_else):
+        df_Diag_Ram_add = pd.DataFrame()
+        df_Diag_Ram_Update_change = pd.DataFrame()
+        
+        df_Diag_Cal_finish = pd.DataFrame(columns=['start_time', 'end_time', 'product_id', 'code', 'level', 'info','advice','Batpos'])
+        df_Diag_Cal_unfinish = pd.DataFrame(columns=['start_time', 'end_time', 'product_id', 'code', 'level', 'info','advice','Batpos'])
+        print('处理前',df_Diag_Cal_unfinish)
+        if not df_Diag_Batdiag_update.empty:
+            #------------------------------合并两者故障,并将同一sn号下的车辆故障放一起----------------------------------------------
+            df_Diag_Cal_finish = df_Diag_Batdiag_update[df_Diag_Batdiag_update['end_time'] != '0000-00-00 00:00:00']
+            df_Diag_Cal_unfinish = df_Diag_Batdiag_update[df_Diag_Batdiag_update['end_time'] == '0000-00-00 00:00:00']
+            df_Diag_Cal_finish['Batpos'] = [1]*len(df_Diag_Cal_finish)
+            if len(df_OprtnSta):
+                if df_OprtnSta.loc[0,'status'] !=1:#0禁用 1正常 2故障 3返修 4 损毁 5丢失已赔偿,6丢失未赔偿
+                    if df_Diag_Cal_unfinish['level'].max()>3:
+                        if df_OprtnSta.loc[0,'status'] ==3:
+                            df_Diag_Cal_unfinish['Batpos'] = [1]*len(df_Diag_Cal_unfinish)
+                        else:
+                            df_Diag_Cal_unfinish['Batpos'] = [0]*len(df_Diag_Cal_unfinish)
+                    else:
+                        df_Diag_Cal_unfinish['Batpos'] = [1]*len(df_Diag_Cal_unfinish)
+                else:
+                    df_Diag_Cal_unfinish['Batpos'] = [0]*len(df_Diag_Cal_unfinish)
+                    
+        print('处理后',df_Diag_Cal_unfinish)
+        df_Diag_Cal_Update=pd.concat([df_Diag_Cal_finish,df_Diag_Cal_unfinish])    
+        df_Diag_Ram_add = pd.concat([df_Diag_Cal_Update,df_Diag_Ram_sn,df_Diag_Ram_sn]).drop_duplicates(subset=['start_time','code'],keep=False)#此次判断中新增故障
+        df_Diag_Ram_Update_old = pd.concat([df_Diag_Cal_Update,df_Diag_Ram_add,df_Diag_Ram_add]).drop_duplicates(subset=['start_time','code'],keep=False)#此次判断中新增故障
+        df_Diag_Ram_Update_change = pd.concat([df_Diag_Ram_Update_old,df_Diag_Ram_sn,df_Diag_Ram_sn]).drop_duplicates(subset=['start_time','code','Batpos'],keep=False)#此次判断中新增故障
+        # df_Diag_Ram = pd.concat([df_Diag_Ram_sn_else,df_Diag_Cal_unfinish])    
+        return df_Diag_Ram_add,df_Diag_Ram_Update_change

+ 73 - 0
LIB/MIDDLE/SaftyCenter/DataDiag_Static/SC_CtrlSafty.py

@@ -0,0 +1,73 @@
+import sys
+import numpy as np
+import pandas as pd
+import string
+import os
+from pandas import Series
+from matplotlib import pyplot as plt
+from pandas.core.frame import DataFrame
+from pandas.core.indexes.base import Index
+from LIB.BACKEND import DBManager
+import datetime
+import time
+import string
+import re
+
+
+
+class CtrlSafty:
+    def __init__(self):
+        pass
+    def main(sn,param,bms_info,df_Diag_Ram_in):
+        df_Diag_Ram_Update_inside=DataFrame(columns=['start_time', 'end_time', 'product_id', 'code', 'level', 'info','advice'])
+        df_Diag_Ram_Update_inside=df_Diag_Ram_Update_inside.append(df_Diag_Ram_in)
+        global QuitErrCount 
+        VolStarkCount=[0 for i in range(param.CellVoltNums)]
+        VolCount=0
+        QuitErrCount=[0 for i in range(param.FaultCount)]
+
+        #--------------该电池的所有当前故障-------------
+
+
+
+
+        df_Diag_Ram_Update_inside=CtrlSafty.TempCtrlDiag(sn,bms_info,param,df_Diag_Ram_Update_inside) 
+        return df_Diag_Ram_Update_inside
+
+
+
+    def TempCtrlDiag(sn,bms_info,param,df_Diag_Ram):
+        ErrorFlg=0
+        CellTempMax=0
+        OtherTempMax=0
+
+        CellTempNum=['单体温度'+str(i) for i in range(1,param.CellTempNums+1)]
+        if 'MXMLX' in sn:
+            OtherTempNum=['其他温度1','其他温度3','其他温度4','其他温度5']
+        else:
+            OtherTempNum=['其他温度'+str(i) for i in range(1,param.OtherTempNums+1)]
+        
+        CellTempMax=bms_info[bms_info[CellTempNum]>(param.CellMaxUSBTemp-5)]
+        CellTempMax=CellTempMax[CellTempMax<(param.CellMaxUSBTemp+5)].dropna(axis=0,how='all')
+        OtherTempMax=bms_info[bms_info[OtherTempNum]>(param.OtherOTlmt-10)]
+        OtherTempMax=OtherTempMax[OtherTempMax[OtherTempNum]<(param.OtherOTlmt+5)].dropna(axis=0,how='all')
+        if len(CellTempMax) and len(OtherTempMax):
+            QuitErrCount[57]=0
+            if not 57 in df_Diag_Ram['code'].values.tolist():#如果故障发生当前故障中没有该故障,则压入该故障
+                df_Diag_Ram.loc[len(df_Diag_Ram)]=[bms_info.loc[len(bms_info)-1,'时间戳'],'0000-00-00 00:00:00',sn,57,4,'电芯温度高','立即联系用户确认电池状态']
+                ErrorFlg=1            
+            else:#如果故障发生当前故障中有该故障,则不进行操作
+                pass
+        else:
+            if 57 in df_Diag_Ram['code'].values.tolist():
+                QuitErrCount[57]=QuitErrCount[57]+1
+                if QuitErrCount[57]>3:
+                    QuitErrCount[57]=4
+                    end_time=datetime.datetime.now()
+                    end_time=end_time.strftime('%Y-%m-%d %H:%M:%S')
+                    df_Diag_Ram.loc[df_Diag_Ram[df_Diag_Ram['code']==57].index,['end_time']]=end_time
+                else:
+                    pass
+            else:
+                pass
+        return df_Diag_Ram

+ 356 - 0
LIB/MIDDLE/SaftyCenter/DataDiag_Static/SC_SamplingSafty.py

@@ -0,0 +1,356 @@
+import sys
+import numpy as np
+import pandas as pd
+import string
+import os
+from pandas import Series
+from matplotlib import pyplot as plt
+from pandas.core.frame import DataFrame
+from pandas.core.indexes.base import Index
+from LIB.BACKEND import DBManager
+import datetime
+import time
+import string
+import re
+
+
+
+class SamplingSafty:
+    def __init__(self):
+        pass
+    def main(sn,param,bms_info,df_Diag_Ram_in):
+        df_Diag_Ram_Update_inside=DataFrame(columns=['start_time', 'end_time', 'product_id', 'code', 'level', 'info','advice'])
+        df_Diag_Ram_Update_inside=df_Diag_Ram_Update_inside.append(df_Diag_Ram_in)
+        global QuitErrCount 
+        VolStarkCount=[0 for i in range(param.CellVoltNums)]
+        VolCount=0
+        QuitErrCount=[0 for i in range(param.FaultCount)]
+
+        #--------------该电池的所有当前故障-------------
+
+
+
+        for i in range(0,len(bms_info)):
+            if i==0:
+                bms_infoP=bms_info.loc[i]
+            elif len(bms_info)>=1:
+                    bms_infoP=bms_info.loc[i-1]
+            df_Diag_Ram_Update_inside,VolStarkCount,VolCount=SamplingSafty.VoltSamplingDiag(sn,bms_info.loc[i],bms_infoP,param,VolStarkCount,VolCount,df_Diag_Ram_Update_inside)   
+            df_Diag_Ram_Update_inside=SamplingSafty.TempSamplingDiag(sn,bms_info.loc[i],bms_infoP,param,df_Diag_Ram_Update_inside)
+                # FltInfo=SamplingSafty.CrntSamplingDiag(sn,bms_info.loc[i],FltInfo,param)
+        return df_Diag_Ram_Update_inside
+
+
+
+    def VoltSamplingDiag(sn,bms_infoN,bms_infoP,param,VolStarkCount,VolCount,df_Diag_Ram):
+        InVMaxBatNo=[]
+        InVMinBatNo=[]
+        StackVolNo=[]
+        OutlierVolNo=[]
+        ErrorFlg=0
+        #——————————————————————取最高最低电压————————————————————————————————
+
+        VoltageNum=['单体电压'+str(i) for i in range(1,param.CellVoltNums+1)]
+        CellVoltage=bms_infoN[VoltageNum]/1000
+        CellVoltageP=bms_infoP[VoltageNum]/1000
+        MaxVolt=CellVoltage.max()
+        MinVolt=CellVoltage.min()
+        MaxVoltNum=CellVoltage[MaxVolt==CellVoltage].index
+        MinVoltNum=CellVoltage[MinVolt==CellVoltage].index
+        InVMaxBatNo=CellVoltage[CellVoltage>=param.CellOVlmt].index
+        InVMinBatNo=CellVoltage[CellVoltage<=param.CellUVlmt].index
+        if param.CellVoltNums>2:
+            AvgVol=(CellVoltage.sum()-MaxVolt-MinVolt)/(param.CellVoltNums-2)
+        else:
+            AvgVol=CellVoltage.mean()
+        #—————————————————————————————电压无效和断线判断———————————————————————
+        if len(InVMaxBatNo):
+            if len(InVMinBatNo):
+                QuitErrCount[10]=0
+                if not 10 in df_Diag_Ram['code'].values.tolist():#如果故障发生当前故障中没有该故障,则压入该故障
+                    df_Diag_Ram.loc[len(df_Diag_Ram)]=[bms_infoN['时间戳'],'0000-00-00 00:00:00',sn,10,2,'电池电压采样断线,最高电压为{:.2f}V,电池编号为{},最低电压为{:.2f}V,电池编号为{}'.format(MaxVolt,InVMaxBatNo.values,MinVolt,InVMinBatNo.values),'返厂维修']
+                    ErrorFlg=1  
+                else:#如果故障发生当前故障中有该故障,则不进行操作
+                    pass                 
+            else:#如果没有故障,并且当前故障表中有该故障,则判断故障是否结束
+                QuitErrCount[50]=0
+                if 10 in df_Diag_Ram['code'].values.tolist():
+                    QuitErrCount[10]=QuitErrCount[10]+1
+                    if QuitErrCount[10]>3:
+                        QuitErrCount[10]=4
+                        end_time=datetime.datetime.now()
+                        end_time=end_time.strftime('%Y-%m-%d %H:%M:%S')
+                        df_Diag_Ram.loc[df_Diag_Ram[df_Diag_Ram['code']==10].index,['end_time']]=end_time
+                    else:
+                        pass
+                else:
+                    pass
+                if not 50 in df_Diag_Ram['code'].values.tolist():
+                    df_Diag_Ram.loc[len(df_Diag_Ram)]=[bms_infoN['时间戳'],'0000-00-00 00:00:00',sn,50,2,str(InVMaxBatNo.values)+'号电压大于{:.2f}V,采样无效'.format(param.CellOVlmt),'返厂维修']
+                    ErrorFlg=1
+                else:
+                    pass
+        elif len(InVMinBatNo):
+            QuitErrCount[50]=0
+            if not 50 in df_Diag_Ram['code'].values.tolist():
+                df_Diag_Ram.loc[len(df_Diag_Ram)]=[bms_infoN['时间戳'],'0000-00-00 00:00:00',sn,50,2,str(InVMinBatNo.values)+'号电压小于{:.2f}V,采样无效'.format(param.CellUVlmt),'返厂维修']
+                ErrorFlg=1
+            else:
+                pass
+        else:
+            if 50 in df_Diag_Ram['code'].values.tolist():
+                QuitErrCount[50]=QuitErrCount[50]+1
+                if QuitErrCount[50]>3:
+                    QuitErrCount[50]=4
+                    end_time=datetime.datetime.now()
+                    end_time=end_time.strftime('%Y-%m-%d %H:%M:%S')
+                    df_Diag_Ram.loc[df_Diag_Ram[df_Diag_Ram['code']==50].index,['end_time']]=end_time                   
+                else:
+                    pass
+            else:
+                pass                                      
+       #——————————————————————————————————电压卡滞和离群判断—————————————————————————
+        if ErrorFlg==0:
+            AvgVolGap=CellVoltage-AvgVol
+            OutlierVolNo=AvgVolGap[AvgVolGap>=param.AvgVolGap].index
+            if len(OutlierVolNo) and abs(bms_infoN['总电流[A]'])<2 and not 51 in df_Diag_Ram['code']:
+                VolCount=VolCount+1
+                QuitErrCount[51]=0
+                if VolCount>10:
+                    VolCount=11
+                    if not 51 in df_Diag_Ram['code'].values.tolist():#如果故障发生当前故障中没有该故障,则压入该故障
+                        df_Diag_Ram.loc[len(df_Diag_Ram)]=[bms_infoN['时间戳'],'0000-00-00 00:00:00',sn,51,2,str(OutlierVolNo.values)+'号电池电压离群','技术介入诊断']
+                        ErrorFlg=1            
+                    else:#如果故障发生当前故障中有该故障,则不进行操作
+                        pass                
+            else:
+                VolCount=0
+                if 51 in df_Diag_Ram['code'].values.tolist():
+                    QuitErrCount[51]=QuitErrCount[51]+1
+                    if QuitErrCount[51]>3:
+                        QuitErrCount[51]=4
+                        end_time=datetime.datetime.now()
+                        end_time=end_time.strftime('%Y-%m-%d %H:%M:%S')
+                        df_Diag_Ram.loc[df_Diag_Ram[df_Diag_Ram['code']==51].index,['end_time']]=end_time                
+                    else:
+                        pass
+                else:
+                    pass
+            # -------------------卡滞逻辑未加-------------------------------------
+            # if (abs(float(bms_infoN['总电流[A]']))>=10 and not 'PK504' in sn) or (abs(float(bms_infoN['总电流[A]']))>=15 and 'PK504' in sn):
+            #     StackVolNo=CellVoltage[abs(CellVoltage-CellVoltageP)<=0.0001].index
+            #     NotStackVolNo=CellVoltage[abs(CellVoltage-CellVoltageP)>0.0001].index
+            #     if len(StackVolNo) and not 52 in df_Diag_Ram['code']:
+            #         StackVolNo=[int(s) for s in StackVolNo.str.replace(r'[^0-9]','').tolist()]
+            #         NotStackVolNo=[int(s) for s in NotStackVolNo.str.replace(r'[^0-9]','').tolist()]
+            #         for i in StackVolNo:
+            #             VolStarkCount[i-1]=VolStarkCount[i-1]+1
+            #         for i in NotStackVolNo:
+            #             VolStarkCount[i-1]=0
+            #     if [s for s in VolStarkCount]>10:
+            #         StacVolNo=
+
+        return df_Diag_Ram,VolStarkCount,VolCount
+
+    def TempSamplingDiag(sn,bms_infoN,bms_infoP,param,df_Diag_Ram):
+        InVMaxBatNo=[]
+        InVMinBatNo=[]
+        StackVolNo=[]
+        OutlierVolNo=[]
+        ErrorFlg=0
+        #——————————————————————Cell取最高最低温度————————————————————————————————
+        TempNum=['单体温度'+str(i) for i in range(1,param.CellTempNums+1)]
+        CellTemp=bms_infoN[TempNum]
+        CellTempP=bms_infoP[TempNum]
+        maxCellTemp=CellTemp.max()
+        minCellTemp=CellTemp.min()
+        MaxVoltNum=CellTemp[maxCellTemp==CellTemp].index
+        MinVoltNum=CellTemp[minCellTemp==CellTemp].index
+        InVMaxTempBatNo=CellTemp[CellTemp>=param.PackOTlmt].index
+        InVMinTempBatNo=CellTemp[CellTemp<=param.PackUTlmt].index
+        if param.CellTempNums>2:
+            AvgCellTemp=(CellTemp.sum()-maxCellTemp-minCellTemp)/(param.CellTempNums-2)
+        else:
+            AvgCellTemp=CellTemp.mean()        
+        #——————————————————————温度无效,离群和断线判断———————————————————————
+        if len(InVMaxTempBatNo):
+            if len(InVMinTempBatNo):
+                QuitErrCount[53]=0
+                if not 53 in df_Diag_Ram['code'].values.tolist():#如果故障发生当前故障中没有该故障,则压入该故障
+                    df_Diag_Ram.loc[len(df_Diag_Ram)]=[bms_infoN['时间戳'],'0000-00-00 00:00:00',sn,53,2,'电池温度采样断线,最高温度为{}℃,电池编号为{},最低温度为{}℃,电池编号为{}'.format(maxCellTemp,InVMaxTempBatNo.values,minCellTemp,InVMinTempBatNo.values),'返厂维修']
+                    ErrorFlg=1 
+                else:#如果故障发生当前故障中有该故障,则不进行操作
+                    pass                 
+            else:#如果没有故障,并且当前故障表中有该故障,则判断故障是否结束
+                QuitErrCount[2]=0
+                if 53 in df_Diag_Ram['code'].values.tolist():
+                    QuitErrCount[53]=QuitErrCount[53]+1
+                    if QuitErrCount[53]>3:
+                        QuitErrCount[53]=4
+                        end_time=datetime.datetime.now()
+                        end_time=end_time.strftime('%Y-%m-%d %H:%M:%S')
+                        df_Diag_Ram.loc[df_Diag_Ram[df_Diag_Ram['code']==53].index,['end_time']]=end_time
+                    else:
+                        pass
+                else:
+                    pass
+                if not 2 in df_Diag_Ram['code'].values.tolist():
+                    df_Diag_Ram.loc[len(df_Diag_Ram)]=[bms_infoN['时间戳'],'0000-00-00 00:00:00',sn,2,2,str(InVMaxTempBatNo.values)+'号温度大于{}℃,采样无效'.format(param.PackOTlmt),'联系用户核实电池温度情况,并返厂维修']
+                    ErrorFlg=1
+                else:
+                    pass
+        elif len(InVMinTempBatNo):
+            QuitErrCount[2]=0
+            if not 2 in df_Diag_Ram['code'].values.tolist():
+                df_Diag_Ram.loc[len(df_Diag_Ram)]=[bms_infoN['时间戳'],'0000-00-00 00:00:00',sn,2,2,str(InVMinTempBatNo.values)+'号温度小于{}℃,采样无效'.format(param.PackUTlmt),'返厂维修']
+                ErrorFlg=1
+            else:
+                pass
+        else:
+            if 2 in df_Diag_Ram['code'].values.tolist():
+                QuitErrCount[2]=QuitErrCount[2]+1
+                if QuitErrCount[2]>3:
+                    QuitErrCount[2]=4
+                    end_time=datetime.datetime.now()
+                    end_time=end_time.strftime('%Y-%m-%d %H:%M:%S')
+                    df_Diag_Ram.loc[df_Diag_Ram[df_Diag_Ram['code']==2].index,['end_time']]=end_time                   
+                else:
+                    pass
+            else:
+                pass             
+        if ErrorFlg==0:
+            AvgCellTempGap=abs(CellTemp-AvgCellTemp)
+            OutlierTempNo=AvgCellTempGap[AvgCellTempGap>=param.AvgCellTempGap].index
+            if len(OutlierTempNo):
+                QuitErrCount[8]=0
+                if not 8 in df_Diag_Ram['code'].values.tolist():#如果故障发生当前故障中没有该故障,则压入该故障
+                    df_Diag_Ram.loc[len(df_Diag_Ram)]=[bms_infoN['时间戳'],'0000-00-00 00:00:00',sn,8,2,str(OutlierTempNo.values)+'号电池异常温度离群','技术介入诊断']
+                    ErrorFlg=1            
+                else:#如果故障发生当前故障中有该故障,则不进行操作
+                    pass
+            else:
+                if 8 in df_Diag_Ram['code'].values.tolist():
+                    QuitErrCount[8]=QuitErrCount[8]+1
+                    if QuitErrCount[8]>3:
+                        QuitErrCount[8]=4
+                        end_time=datetime.datetime.now()
+                        end_time=end_time.strftime('%Y-%m-%d %H:%M:%S')
+                        df_Diag_Ram.loc[df_Diag_Ram[df_Diag_Ram['code']==8].index,['end_time']]=end_time
+                    else:
+                        pass
+                else:
+                    pass
+        #——————————————————————————————————OtherTemp————————————————————————————————————
+        if param.OtherTempNums>0:
+            OtherTempNum=['其他温度'+str(i) for i in range(1,param.OtherTempNums+1)]
+            OtherTemp=bms_infoN[OtherTempNum]
+            OtherTemppP=bms_infoP[OtherTempNum]
+            maxOtherTemp=OtherTemp.max()
+            minOtherTemp=OtherTemp.min()
+            MaxVoltNum=OtherTemp[maxOtherTemp==OtherTemp].index
+            MinVoltNum=OtherTemp[minOtherTemp==OtherTemp].index
+            InVMaxOtherTempBatNo=OtherTemp[OtherTemp>=param.OtherOTlmt].index
+            InVMinOtherTempBatNo=OtherTemp[OtherTemp<=param.OtherUTlmt].index
+            if param.OtherTempNums>2:
+                AvgOtherTemp=(OtherTemp.sum()-maxOtherTemp-minOtherTemp)/(param.OtherTempNums-2)
+            else:
+                AvgOtherTemp=OtherTemp.mean()        
+            #——————————————————————温度无效,离群和断线判断———————————————————————
+            if len(InVMaxOtherTempBatNo):
+                if len(InVMinOtherTempBatNo):
+                    QuitErrCount[54]=0
+                    if not 54 in df_Diag_Ram['code'].values.tolist():#如果故障发生当前故障中没有该故障,则压入该故障
+                        df_Diag_Ram.loc[len(df_Diag_Ram)]=[bms_infoN['时间戳'],'0000-00-00 00:00:00',sn,54,2,'其他温度采样断线,最高温度为{}℃,传感器编号为{},最低温度为{}℃,传感器编号为{}'.format(maxOtherTemp,InVMaxOtherTempBatNo.values,minOtherTemp,InVMinOtherTempBatNo.values),'返厂维修']
+                        ErrorFlg=1 
+                    else:#如果故障发生当前故障中有该故障,则不进行操作
+                        pass                 
+                else:#如果没有故障,并且当前故障表中有该故障,则判断故障是否结束
+                    QuitErrCount[55]=0
+                    if 54 in df_Diag_Ram['code'].values.tolist():
+                        QuitErrCount[54]=QuitErrCount[54]+1
+                        if QuitErrCount[54]>3:
+                            QuitErrCount[54]=4
+                            end_time=datetime.datetime.now()
+                            end_time=end_time.strftime('%Y-%m-%d %H:%M:%S')
+                            df_Diag_Ram.loc[df_Diag_Ram[df_Diag_Ram['code']==54].index,['end_time']]=end_time
+                        else:
+                            pass
+                    else:
+                        pass
+                    if not 55 in df_Diag_Ram['code'].values.tolist():
+                        df_Diag_Ram.loc[len(df_Diag_Ram)]=[bms_infoN['时间戳'],'0000-00-00 00:00:00',sn,55,2,'传感器温度大于{}℃,采样无效'.format(param.OtherOTlmt),'联系用户核实电池温度情况,并返厂维修']
+                        ErrorFlg=1
+                    else:
+                        pass
+            elif len(InVMinTempBatNo):
+                QuitErrCount[55]=0
+                if not 55 in df_Diag_Ram['code'].values.tolist():
+                    df_Diag_Ram.loc[len(df_Diag_Ram)]=[bms_infoN['时间戳'],'0000-00-00 00:00:00',sn,55,2,'传感器温度小于{}℃,采样无效'.format(param.OtherUTlmt),'返厂维修']
+                    ErrorFlg=1
+                else:
+                    pass
+            else:
+                if 55 in df_Diag_Ram['code'].values.tolist():
+                    QuitErrCount[55]=QuitErrCount[55]+1
+                    if QuitErrCount[55]>3:
+                        QuitErrCount[55]=4
+                        end_time=datetime.datetime.now()
+                        end_time=end_time.strftime('%Y-%m-%d %H:%M:%S')
+                        df_Diag_Ram.loc[df_Diag_Ram[df_Diag_Ram['code']==55].index,['end_time']]=end_time                   
+                    else:
+                        pass
+                else:
+                    pass             
+            if ErrorFlg==0:
+                AvgOtherTempGap=abs(OtherTemp-AvgOtherTemp)
+                OutlierOtherTempNo=AvgOtherTempGap[AvgOtherTempGap>=param.AvgOtherTempGap].index
+                if len(OutlierOtherTempNo):
+                    QuitErrCount[56]=0
+                    if not 56 in df_Diag_Ram['code'].values.tolist():#如果故障发生当前故障中没有该故障,则压入该故障
+                        df_Diag_Ram.loc[len(df_Diag_Ram)]=[bms_infoN['时间戳'],'0000-00-00 00:00:00',sn,56,2,'传感器温度异常离群','技术介入诊断']
+                        ErrorFlg=1            
+                    else:#如果故障发生当前故障中有该故障,则不进行操作
+                        pass
+                else:
+                    if 56 in df_Diag_Ram['code'].values.tolist():
+                        QuitErrCount[56]=QuitErrCount[56]+1
+                        if QuitErrCount[56]>3:
+                            QuitErrCount[56]=4
+                            end_time=datetime.datetime.now()
+                            end_time=end_time.strftime('%Y-%m-%d %H:%M:%S')
+                            df_Diag_Ram.loc[df_Diag_Ram[df_Diag_Ram['code']==56].index,['end_time']]=end_time
+                        else:
+                            pass
+                    else:
+                        pass
+
+                if (maxOtherTemp-maxCellTemp)>param.AvgOtherTempGap and  maxOtherTemp<param.OtherOTlmt and maxCellTemp<param.PackOTlmt:
+                    QuitErrCount[56]=0
+                    if not 56 in df_Diag_Ram['code'].values.tolist():
+                        df_Diag_Ram.loc[len(df_Diag_Ram)]=[bms_infoN['时间戳'],'0000-00-00 00:00:00',sn,56,2,'传感器温度异常离群','技术立即介入诊断']
+                        ErrorFlg=1
+                else:
+                    if 56 in df_Diag_Ram['code'].values.tolist():
+                            QuitErrCount[56]=QuitErrCount[56]+1
+                            if QuitErrCount[56]>3:
+                                QuitErrCount[56]=4
+                                end_time=datetime.datetime.now()
+                                end_time=end_time.strftime('%Y-%m-%d %H:%M:%S')
+                                df_Diag_Ram.loc[df_Diag_Ram[df_Diag_Ram['code']==56].index,['end_time']]=end_time
+                                
+                if (maxCellTemp-maxOtherTemp)>param.AvgOtherTempGap and  maxOtherTemp<param.OtherOTlmt and maxCellTemp<param.PackOTlmt and not 8 in df_Diag_Ram['code']:
+                    QuitErrCount[8]=0
+                    if not 8 in df_Diag_Ram['code'].values.tolist():
+                        df_Diag_Ram.loc[len(df_Diag_Ram)]=[bms_infoN['时间戳'],'0000-00-00 00:00:00',sn,8,2,str(OutlierTempNo.values)+'号电芯温度异常离群','技术立即介入诊断']
+                        
+                        ErrorFlg=1
+                else:
+                    if 8 in df_Diag_Ram['code'].values.tolist():
+                            QuitErrCount[8]=QuitErrCount[8]+1
+                            if QuitErrCount[8]>3:
+                                QuitErrCount[8]=4
+                                end_time=datetime.datetime.now()
+                                end_time=end_time.strftime('%Y-%m-%d %H:%M:%S')
+                                df_Diag_Ram.loc[df_Diag_Ram[df_Diag_Ram['code']==8].index,['end_time']]=end_time              
+
+        return df_Diag_Ram

+ 296 - 0
LIB/MIDDLE/SaftyCenter/DataDiag_Static/main.py

@@ -0,0 +1,296 @@
+import CBMSBatDiag
+from SC_SamplingSafty import SamplingSafty
+from DataStatistics import DataSta
+from DiagDataMerge import DiagDataMerge
+from SC_CtrlSafty import CtrlSafty
+import datetime
+import pandas as pd
+from LIB.BACKEND import DBManager, Log
+from sqlalchemy import create_engine
+import time, datetime
+from apscheduler.schedulers.blocking import BlockingScheduler
+from LIB.MIDDLE.CellStateEstimation.Common.V1_0_1 import DBDownload as DBDownload
+from LIB.MIDDLE.CellStateEstimation.Common.V1_0_1 import log
+from pandas.core.frame import DataFrame
+import datacompy
+from LIB.MIDDLE.SaftyCenter.Common import QX_BatteryParam
+from LIB.MIDDLE.SaftyCenter.Common import DBDownload as DBDw
+
+#...................................电池包电芯安全诊断函数......................................................................................................................
+def diag_cal():
+    task_on=1
+    global SNnums
+    global start
+    #..................................设置时间..........................................................  
+    start=time.time()
+    end_time=datetime.datetime.now()
+    start_time=end_time-datetime.timedelta(seconds=900)#10分钟跑一次,一次取10分钟数据
+    start_time=start_time.strftime('%Y-%m-%d %H:%M:%S')
+    end_time=end_time.strftime('%Y-%m-%d %H:%M:%S')
+
+
+    
+    host='rm-bp10j10qy42bzy0q77o.mysql.rds.aliyuncs.com'
+    port=3306
+    db='safety_platform'
+    user='qx_algo_readonly'
+    password='qx@123456'
+    mode=2
+    tablename2='all_fault_info'
+    DBRead = DBDw.DBDownload(host, port, db, user, password,mode)
+    with DBRead as DBRead:
+        df_Diag_Ram = DBRead.getdata('start_time','end_time','product_id','code','level','info','advice','Batpos',tablename=tablename2,factory='骑享',sn='',timename='',st='',sp='')
+    
+
+    print('起',len(df_Diag_Ram))
+    for sn in SNnums:#SN遍历
+        print(sn)
+        if 'PK500' in sn:
+            celltype=1 #6040三元电芯
+        elif 'PK502' in sn:
+            celltype=2 #4840三元电芯
+        elif 'K504B' in sn:
+            celltype=99    #60ah林磷酸铁锂电芯
+        elif 'MGMLXN750' in sn:
+            celltype=3 #力信50ah三元电芯
+        elif 'MGMCLN750' or 'UD' in sn: 
+            celltype=4 #CATL 50ah三元电芯
+        else:
+            print('SN:{},未找到对应电池类型!!!'.format(sn))
+            continue
+            # sys.exit()
+        param=QX_BatteryParam.BatteryInfo(celltype)   
+        #读取原始数据库数据........................................................................................................................................................
+        dbManager = DBManager.DBManager()
+        df_data = dbManager.get_data(sn=sn, start_time=start_time, end_time=end_time, data_groups=['bms'])
+        df_bms = df_data['bms']
+
+        #读取结果数据库数据........................................................................................................................................................
+        host='rm-bp10j10qy42bzy0q77o.mysql.rds.aliyuncs.com'
+        port=3306
+        db='qx_cas'
+        user='qx_algo_readonly'
+        password='qx@123456'
+        mode=1
+        tablename1='cellstateestimation_soh'
+        tablename2='cellstateestimation_uniform_socvoltdiff'       
+        DBRead=DBDownload.DBDownload(host, port, db, user, password,mode)
+        with DBRead as DBRead:
+            df_soh=DBRead.getdata('time_st,sn,soh,cellsoh', tablename=tablename1, sn=sn, timename='time_sp', st=start_time, sp=end_time)
+            df_uniform=DBRead.getdata('time,sn,cellsoc_diff,cellmin_num,cellmax_num', tablename=tablename2, sn=sn, timename='time', st=start_time, sp=end_time)
+
+        #读取电池当前运营状态.....................................................................................................................................................
+        host='rm-bp10j10qy42bzy0q7.mysql.rds.aliyuncs.com'
+        port=3306
+        db='qixiang_manage'
+        user='qx_query'
+        password='@Qx_query'
+        mode=4
+        tablename1='py_battery'     
+        DBRead=DBDw.DBDownload(host, port, db, user, password,mode)
+        with DBRead as DBRead:
+            df_OprtnSta=DBRead.getdata('qrcode','status', tablename=tablename1, sn=sn, timename='', st='', sp='',factory='')#取最后一条运营状态
+
+
+
+
+
+
+        #电池诊断.....................................................................................................................................................................
+        CellFltInfo=DataFrame(columns=['start_time', 'end_time', 'product_id', 'code', 'level', 'info','advice'])
+        df_Diag_Ram_sn = df_Diag_Ram.loc[df_Diag_Ram['product_id']==sn]#历史故障
+        df_Diag_Ram_sn_else = df_Diag_Ram.loc[df_Diag_Ram['product_id']!=sn]#sn之外的故障
+        CellFltInfo = df_Diag_Ram_sn.drop('Batpos',axis=1)
+        #获取当前故障电池的历史故障信息↑↑↑↑↑↑↑↑↑↑↑.......................................................................................................................................
+        if not df_bms.empty:
+            df_Diag_Batdiag_update_xq=SamplingSafty.main(sn,param,df_bms,CellFltInfo)#学琦计算故障   
+            df_Diag_Batdiag_update_xq2=CtrlSafty.main(sn,param,df_bms,df_Diag_Batdiag_update_xq)
+            batDiag=CBMSBatDiag.BatDiag(sn,celltype,df_bms, df_soh, df_uniform, df_Diag_Batdiag_update_xq2)#鹏飞计算
+            df_Diag_Batdiag_update=batDiag.diag()
+            # df_Diag_Batdiag_update=BatDiag.diag() 
+        else:
+            df_Diag_Batdiag_update_xq=DataFrame(columns=['start_time','end_time','product_id','code','level','info','advice','Batpos'])
+            df_Diag_Batdiag_update=DataFrame(columns=['start_time','end_time','product_id','code','level','info','advice','Batpos'])
+        df_Diag_Ram_add,df_Diag_Ram_Update=DiagDataMerge.DetaMerge(df_Diag_Ram_sn,df_Diag_Batdiag_update,df_OprtnSta,df_Diag_Ram_sn_else)
+    task_on=0
+#.................................统计程序...............................
+def DaTa_Sta_Week_Task():
+    task_on=1
+    all_period_fault_info=DataFrame(columns=['factory','week','level1_count','level2_count','level3_count','level4_count','level5_count','solve_rate'])
+    #............................获取数据................................
+    toweek='Week'+time.strftime('%W')
+    host='rm-bp10j10qy42bzy0q77o.mysql.rds.aliyuncs.com'
+    port=3306
+    db='safety_platform'
+    user='qx_algo_readonly'
+    password='qx@123456'
+    mode=2
+    tablename1='all_fault_info'
+    DBRead=DBDw.DBDownload(host, port, db, user, password,mode)
+    with DBRead as DBRead:
+        df_fltinfo=DBRead.getdata('product_id','level','code','start_time','end_time','batpos',tablename=tablename1,factory='骑享',sn='',timename='',st='',sp='')#dbdownload经过了改编
+    #............................获取时间................................      
+    end_time=datetime.datetime.now()
+    # end_time=datetime.datetime.strptime(end_time,'%Y-%m-%d')
+    start_time_week=end_time-datetime.timedelta(days=7)
+    start_time_week=start_time_week.strftime('%Y-%m-%d')
+    end_time=end_time.strftime('%Y-%m-%d')
+    FltAlarmInfo,Celltype=DataSta.SaftyWarningSta(df_fltinfo,start_time_week,end_time)
+    FaultLvlCount=DataSta.WeekInfoSta(df_fltinfo,start_time_week,end_time)
+    for i in range(1,6):
+        if not FaultLvlCount[FaultLvlCount['level']==i]['product_id'].empty:
+            all_period_fault_info.loc[0,'level'+str(i)+'_count']=int(FaultLvlCount[FaultLvlCount['level']==i]['product_id'].values)
+        else:
+            all_period_fault_info.loc[0,'level'+str(i)+'_count']=int(0)
+    all_period_fault_info.loc[0,'factory']='骑享'
+    all_period_fault_info.loc[0,'week']=toweek
+    all_period_fault_info.loc[0,'solve_rate']=FltAlarmInfo.loc[0,'OprationManageRate']
+    all_period_fault_info.fillna(0,inplace=False)
+
+    task_on=0
+def DaTa_Sta_Minutes_Task():
+    task_on=1
+    #............................获取数据................................
+    host='172.16.121.236'
+    port=3306
+    db='fastfun'
+    user='readonly'
+    password='Fast1234'
+    mode=3
+    tablename1='ff_battery_accum'
+    tablename2='ff_location'
+    DBRead=DBDw.DBDownload(host, port, db, user, password,mode)
+    with DBRead as DBRead:
+        df_last_accum=DBRead.getdata('devcode','dsg_phaccum','dsg_ahaccum',tablename=tablename1,factory='',sn='',timename='',st='',sp='')#dbdownload经过了改编
+        df_last_pos=DBRead.getdata('devcode','latitude','longitude',tablename=tablename2,factory='',sn='',timename='',st='',sp='')#dbdownload经过了改编
+        
+        
+    host='rm-bp10j10qy42bzy0q77o.mysql.rds.aliyuncs.com'
+    port=3306
+    db='qx_cas'
+    user='qx_algo_readonly'
+    password='qx@123456'
+    mode=3
+    tablename2='bat_first_data_time'
+    DBRead=DBDw.DBDownload(host, port, db, user, password,mode)
+    with DBRead as DBRead:
+        df_FirstDataTime=DBRead.getdata('sn','first_data_time',tablename=tablename2,factory='',sn='',timename='',st='',sp='')#dbdownload经过了改编
+        
+        
+    host='rm-bp10j10qy42bzy0q77o.mysql.rds.aliyuncs.com'
+    port=3306
+    db='safety_platform'
+    user='qx_algo_readonly'
+    password='qx@123456'
+    mode=2
+    tablename1='all_fault_info'
+    DBRead=DBDw.DBDownload(host, port, db, user, password,mode)
+    with DBRead as DBRead:
+        df_fltinfo=DBRead.getdata('product_id','level','code','start_time','batpos',tablename=tablename1,factory='骑享',sn='',timename='',st='',sp='')#dbdownload经过了改编
+    #............................获取时间................................
+    end_time=datetime.datetime.now()
+    # end_time=datetime.datetime.strptime(end_time,'%Y-%m-%d')
+    start_time=end_time-datetime.timedelta(days=1)
+    start_time=start_time.strftime('%Y-%m-%d')
+    end_time=end_time.strftime('%Y-%m-%d')
+    #............................执行程序................................
+    FltAlarmInfo,Celltype=DataSta.SaftyWarningSta(df_fltinfo,start_time,end_time)
+    SatftyCount=DataSta.SftyWrngClsfy(df_fltinfo)
+    MaxAccumAh,TotalAccumAh,MaxCycle,MaxRunningHour,TotalRunHour=DataSta.AccumInfo(df_last_accum,df_FirstDataTime,end_time)
+    all_location_info=DataSta.FltBatPosition(df_last_pos,df_fltinfo)
+
+    all_statistic_info=DataFrame(columns=['factory','total_alarm','alarm_total_today','alarm_not_close_today','alarm_close_today','alarm_uregent_total_today','alarm_uregent_close_today','alarm_uregent_not_close_today','alarm_close_total','run_time_total','dischrg_total','odo_total','max_dischrg_one','max_runtime_one','max_cycle_one','max_odo_one','alarm_close_total','alarm_total','cell_type','cell_type_count','cell_safety_risk_count','data_safety_risk_count','status_safety_risk_count','hv_safety_risk_count','system_safety_risk_count','sample_safety_risk_count','controller_safety_risk_count','design_safety_risk_count'])
+    all_statistic_info.loc[0,'factory']='骑享'
+    all_statistic_info.loc[0,'total_alarm']=FltAlarmInfo.loc[0,'SftyPlt_Data_Total']
+    all_statistic_info.loc[0,'alarm_total_today']=FltAlarmInfo.loc[0,'SftyPlt_Data_day']
+    all_statistic_info.loc[0,'alarm_close_today']=FltAlarmInfo.loc[0,'CS_Warning_day_Finish_Count']
+    all_statistic_info.loc[0,'alarm_not_close_today']=FltAlarmInfo.loc[0,'SftyPlt_Data_day']-FltAlarmInfo.loc[0,'CS_Warning_day_Finish_Count']
+    all_statistic_info.loc[0,'alarm_uregent_total_today']=FltAlarmInfo.loc[0,'SftyPlt_EmgcyData_day']
+    all_statistic_info.loc[0,'alarm_uregent_close_today']=FltAlarmInfo.loc[0,'SftyPlt_EmgcyData_day_Finish_Count']
+    all_statistic_info.loc[0,'alarm_uregent_not_close_today']=FltAlarmInfo.loc[0,'SftyPlt_EmgcyData_day']-FltAlarmInfo.loc[0,'SftyPlt_EmgcyData_day_Finish_Count']
+    all_statistic_info.loc[0,'run_time_total']=TotalRunHour
+    all_statistic_info.loc[0,'dischrg_total']=TotalAccumAh
+    all_statistic_info.loc[0,'odo_total']=0
+    all_statistic_info.loc[0,'max_dischrg_one']=MaxAccumAh
+    all_statistic_info.loc[0,'max_runtime_one']=MaxRunningHour
+    all_statistic_info.loc[0,'max_cycle_one']=MaxCycle
+    all_statistic_info.loc[0,'max_odo_one']=0
+    all_statistic_info.loc[0,'alarm_close_total']=FltAlarmInfo.loc[0,'CS_Warning_Total_Finish_Count']
+    all_statistic_info.loc[0,'alarm_total']=FltAlarmInfo.loc[0,'SftyPlt_Data_Total']
+    CellType=Celltype.columns.tolist()
+    CellType=','.join(CellType) 
+    all_statistic_info.loc[0,'cell_type']=str(CellType)
+    CellTypeCount=Celltype.loc[0].tolist()
+    CellTypeCount=[str(x) for x in CellTypeCount]
+    CellTypeCount=','.join(CellTypeCount) 
+    all_statistic_info.loc[0,'cell_type_count']=str(CellTypeCount)
+    all_statistic_info.loc[0,'cell_safety_risk_count']=SatftyCount.loc[0,'CellSaftyCount']
+    all_statistic_info.loc[0,'data_safety_risk_count']=SatftyCount.loc[0,'DataSaftyCodeCount']
+    all_statistic_info.loc[0,'status_safety_risk_count']=SatftyCount.loc[0,'StateSaftyCodeCount']
+    all_statistic_info.loc[0,'hv_safety_risk_count']=SatftyCount.loc[0,'HvSaftyCodeCount']
+    all_statistic_info.loc[0,'system_safety_risk_count']=SatftyCount.loc[0,'SysSaftyCodeCount']
+    all_statistic_info.loc[0,'sample_safety_risk_count']=SatftyCount.loc[0,'SamplingSatyCount']
+    all_statistic_info.loc[0,'controller_safety_risk_count']=SatftyCount.loc[0,'CtrlSaftyCodeCount']
+    all_statistic_info.loc[0,'design_safety_risk_count']=SatftyCount.loc[0,'DsnSaftyCodeCount']
+    end=time.time()
+    print(end-start)
+    task_on=0
+
+
+
+#...............................................主函数.......................................................................................................................
+if __name__ == "__main__":
+    global SNnums
+    global task_on
+    
+    task_on=0
+    excelpath=r'D:\ZLWORK\code\data_analyze_platform\USER\eric\SaftyCenter_CODE_V1\sn-20210903.xlsx'
+    SNdata_6060 = pd.read_excel(excelpath, sheet_name='科易6060')
+    SNdata_6040 = pd.read_excel(excelpath, sheet_name='科易6040')
+    SNdata_4840 = pd.read_excel(excelpath, sheet_name='科易4840')
+    SNdata_L7255 = pd.read_excel(excelpath, sheet_name='格林美-力信7255')
+    SNdata_C7255 = pd.read_excel(excelpath, sheet_name='格林美-CATL7255')
+    SNdata_U7255 = pd.read_excel(excelpath, sheet_name='优旦7255')
+    SNnums_6060=SNdata_6060['SN号'].tolist()
+    SNnums_6040=SNdata_6040['SN号'].tolist()
+    SNnums_4840=SNdata_4840['SN号'].tolist()
+    SNnums_L7255=SNdata_L7255['SN号'].tolist()
+    SNnums_C7255=SNdata_C7255['SN号'].tolist()
+    SNnums_U7255=SNdata_U7255['SN号'].tolist()
+    SNnums=SNnums_L7255 + SNnums_C7255 + SNnums_6040 + SNnums_4840 + SNnums_U7255+ SNnums_6060
+    # SNnums=['MGMCLN750N215I005','PK504B10100004341','PK504B00100004172','MGMLXN750N2189014']
+    #SNnums = ['MGMLXN750N218N004'] #SNnums_6040
+    
+    mylog=log.Mylog('log_diag.txt','error')
+    mylog.logcfg()
+    #............................模块运行前,先读取数据库中所有结束时间为0的数据,需要从数据库中读取................
+    host='rm-bp10j10qy42bzy0q77o.mysql.rds.aliyuncs.com'
+    port=3306
+    db='safety_platform'
+    user='qx_algo_readonly'
+    password='qx@123456'
+    mode=2
+    tablename2='all_fault_info'
+    DBRead = DBDw.DBDownload(host, port, db, user, password,mode)
+    with DBRead as DBRead:
+        df_Diag_Ram = DBRead.getdata('start_time','end_time','product_id','code','level','info','advice','Batpos',tablename=tablename2,factory='骑享',sn='',timename='',st='',sp='')
+    # result=pd.read_csv(r'D:\Work\Code_write\data_analyze_platform\USER\01Screen_Problem\result.csv',encoding='gbk')
+
+    #定时任务.......................................................................................................................................................................
+    scheduler = BlockingScheduler()
+    diag_cal()
+    DaTa_Sta_Minutes_Task()
+    DaTa_Sta_Week_Task()  
+
+    if task_on==0:
+        scheduler.add_job(DaTa_Sta_Week_Task, 'interval', days=7, id='Week_Task')
+        scheduler.add_job(diag_cal, 'interval', seconds=900, id='diag_job')
+        scheduler.add_job(DaTa_Sta_Minutes_Task, 'interval', seconds=180, id='Hour_Task')
+
+    try:
+
+        scheduler.start()
+    except Exception as e:
+        scheduler.shutdown()
+        print(repr(e))
+        mylog.logopt(e)

+ 0 - 0
LIB/MIDDLE/SaftyCenter/diagfault/各项目sn号.xlsx → LIB/MIDDLE/SaftyCenter/DataDiag_Static/各项目sn号.xlsx


+ 0 - 0
LIB/MIDDLE/SaftyCenter/diagfault/故障表头及数据类型.xlsx → LIB/MIDDLE/SaftyCenter/DataDiag_Static/故障表头及数据类型.xlsx


+ 0 - 141
LIB/MIDDLE/SaftyCenter/DataSta/main.py

@@ -1,141 +0,0 @@
-import numpy as np
-import pandas as pd
-from LIB.MIDDLE.SaftyCenter.Common import FeiShuData
-from LIB.MIDDLE.SaftyCenter.Common import DBDownload
-import time, datetime
-from pandas.core.frame import DataFrame
-from apscheduler.schedulers.blocking import BlockingScheduler
-from DataStatistics import DataSta
-
-#............................主程序................................... 
-   
-
-
-def Week_Task():
-    all_period_fault_info=DataFrame(columns=['factory','week','level1_count','level2_count','level3_count','level4_count','level5_count','solve_rate'])
-
-    #............................获取数据................................
-    toweek='Week'+time.strftime('%W')
-    CS_Data=FeiShuData.getFeiShuDATA()
-    host='rm-bp10j10qy42bzy0q77o.mysql.rds.aliyuncs.com'
-    port=3306
-    db='safety_platform'
-    user='qx_read'
-    password='Qx@123456'
-    mode=2
-    tablename1='all_fault_info'
-    DBRead=DBDownload.DBDownload(host, port, db, user, password,mode)
-    with DBRead as DBRead:
-        df_fltinfo=DBRead.getdata('product_id','level','code','start_time',tablename=tablename1,factory='骑享',sn='',timename='',st='',sp='')#dbdownload经过了改编
-    #............................获取时间................................      
-    end_time=datetime.datetime.now()
-    # end_time=datetime.datetime.strptime(end_time,'%Y-%m-%d')
-    start_time=end_time-datetime.timedelta(days=7)
-    start_time=start_time.strftime('%Y-%m-%d')
-    end_time=end_time.strftime('%Y-%m-%d')
-    FltAlarmInfo,Celltype=DataSta.SaftyWarningSta(CS_Data,df_fltinfo,start_time,end_time)
-    FaultLvlCount=DataSta.WeekInfoSta(df_fltinfo,start_time,end_time)
-    lvl1=FaultLvlCount[FaultLvlCount['level']==1]['product_id'].values
-    lvl2=FaultLvlCount[FaultLvlCount['level']==2]['product_id'].values
-    lvl3=FaultLvlCount[FaultLvlCount['level']==3]['product_id'].values
-    lvl4=FaultLvlCount[FaultLvlCount['level']==4]['product_id'].values
-    lvl5=FaultLvlCount[FaultLvlCount['level']==5]['product_id'].values
-    all_period_fault_info.loc[0,'factory']='骑享'
-    all_period_fault_info.loc[0,'week']=toweek
-    all_period_fault_info.loc[0,'level1_count']=lvl1
-    all_period_fault_info.loc[0,'level2_count']=lvl2
-    all_period_fault_info.loc[0,'level3_count']=lvl3
-    all_period_fault_info.loc[0,'level4_count']=lvl4
-    all_period_fault_info.loc[0,'level5_count']=lvl5
-    all_period_fault_info.loc[0,'solve_rate']=FltAlarmInfo.loc[0,'OprationManageRate']
-    
-def Minutes_Task():
-    
-    #............................获取数据................................
-    host='172.16.121.236'
-    port=3306
-    db='fastfun'
-    user='readonly'
-    password='Fast1234'
-    mode=3
-    tablename1='ff_battery_accum'
-    DBRead=DBDownload.DBDownload(host, port, db, user, password,mode)
-    with DBRead as DBRead:
-        df_last_accum=DBRead.getdata('devcode','dsg_phaccum','dsg_ahaccum',tablename=tablename1,factory='',sn='',timename='',st='',sp='')#dbdownload经过了改编
-
-    host='rm-bp10j10qy42bzy0q77o.mysql.rds.aliyuncs.com'
-    port=3306
-    db='qx_cas'
-    user='qx_read'
-    password='Qx@123456'
-    mode=3
-    tablename2='bat_first_data_time'
-    DBRead=DBDownload.DBDownload(host, port, db, user, password,mode)
-    with DBRead as DBRead:
-        df_FirstDataTime=DBRead.getdata('sn','first_data_time',tablename=tablename2,factory='',sn='',timename='',st='',sp='')#dbdownload经过了改编
-    CS_Data=FeiShuData.getFeiShuDATA()
-    host='rm-bp10j10qy42bzy0q77o.mysql.rds.aliyuncs.com'
-    port=3306
-    db='safety_platform'
-    user='qx_read'
-    password='Qx@123456'
-    mode=2
-    tablename1='all_fault_info'
-    DBRead=DBDownload.DBDownload(host, port, db, user, password,mode)
-    with DBRead as DBRead:
-        df_fltinfo=DBRead.getdata('product_id','level','code','start_time',tablename=tablename1,factory='骑享',sn='',timename='',st='',sp='')#dbdownload经过了改编
-    #............................获取时间................................
-    end_time=datetime.datetime.now()
-    # end_time=datetime.datetime.strptime(end_time,'%Y-%m-%d')
-    start_time=end_time-datetime.timedelta(days=1)
-    start_time=start_time.strftime('%Y-%m-%d')
-    end_time=end_time.strftime('%Y-%m-%d')
-    #............................执行程序................................
-    FltAlarmInfo,Celltype=DataSta.SaftyWarningSta(CS_Data,df_fltinfo,start_time,end_time)
-    SatftyCount=DataSta.SftyWrngClsfy(df_fltinfo)
-    MaxAccumAh,TotalAccumAh,MaxCycle,MaxRunningHour,TotalRunHour=DataSta.AccumInfo(df_last_accum,df_FirstDataTime,end_time)
-
-    all_statistic_info=DataFrame(columns=['factory','total_alarm','alarm_total_today','alarm_not_close_today','alarm_close_today','alarm_uregent_total_today','alarm_uregent_close_today','alarm_uregent_not_close_today','alarm_close_total','run_time_total','dischrg_total','odo_total','max_dischrg_one','max_runtime_one','max_cycle_one','max_odo_one','alarm_close_total','alarm_total','cell_type','cell_type_count','cell_safety_risk_count','data_safety_risk_count','status_safety_risk_count','hv_safety_risk_count','system_safety_risk_count','sample_safety_risk_count','controller_safety_risk_count','design_safety_risk_count'])
-    all_statistic_info.loc[0,'factory']='骑享'
-    all_statistic_info.loc[0,'total_alarm']=FltAlarmInfo.loc[0,'SftyPlt_Data_Total']
-    all_statistic_info.loc[0,'alarm_total_today']=FltAlarmInfo.loc[0,'SftyPlt_Data_day']
-    all_statistic_info.loc[0,'alarm_close_today']=FltAlarmInfo.loc[0,'CS_Warning_day_Finish_Count']
-    all_statistic_info.loc[0,'alarm_not_close_today']=FltAlarmInfo.loc[0,'SftyPlt_Data_day']-FltAlarmInfo.loc[0,'CS_Warning_day_Finish_Count']
-    all_statistic_info.loc[0,'alarm_uregent_total_today']=FltAlarmInfo.loc[0,'SftyPlt_EmgcyData_day']
-    all_statistic_info.loc[0,'alarm_uregent_close_today']=FltAlarmInfo.loc[0,'SftyPlt_EmgcyData_day_Finish_Count']
-    all_statistic_info.loc[0,'alarm_uregent_not_close_today']=FltAlarmInfo.loc[0,'SftyPlt_EmgcyData_day']-FltAlarmInfo.loc[0,'SftyPlt_EmgcyData_day_Finish_Count']
-    all_statistic_info.loc[0,'run_time_total']=TotalRunHour
-    all_statistic_info.loc[0,'dischrg_total']=TotalAccumAh
-    all_statistic_info.loc[0,'odo_total']=0
-    all_statistic_info.loc[0,'max_dischrg_one']=MaxAccumAh
-    all_statistic_info.loc[0,'max_runtime_one']=MaxRunningHour
-    all_statistic_info.loc[0,'max_cycle_one']=MaxCycle
-    all_statistic_info.loc[0,'max_odo_one']=0
-    all_statistic_info.loc[0,'alarm_close_total']=FltAlarmInfo.loc[0,'CS_Warning_Total_Finish_Count']
-    all_statistic_info.loc[0,'alarm_total']=FltAlarmInfo.loc[0,'SftyPlt_Data_Total']
-    CellType=Celltype.columns.tolist()
-    CellType=','.join(CellType) 
-    all_statistic_info.loc[0,'cell_type']=str(CellType)
-    CellTypeCount=Celltype.loc[0].tolist()
-    CellTypeCount=[str(x) for x in CellTypeCount]
-    CellTypeCount=','.join(CellTypeCount) 
-    all_statistic_info.loc[0,'cell_type_count']=str(CellTypeCount)
-    all_statistic_info.loc[0,'cell_safety_risk_count']=SatftyCount.loc[0,'CellSaftyCount']
-    all_statistic_info.loc[0,'data_safety_risk_count']=SatftyCount.loc[0,'DataSaftyCodeCount']
-    all_statistic_info.loc[0,'status_safety_risk_count']=SatftyCount.loc[0,'StateSaftyCodeCount']
-    all_statistic_info.loc[0,'hv_safety_risk_count']=SatftyCount.loc[0,'HvSaftyCodeCount']
-    all_statistic_info.loc[0,'system_safety_risk_count']=SatftyCount.loc[0,'SysSaftyCodeCount']
-    all_statistic_info.loc[0,'sample_safety_risk_count']=SatftyCount.loc[0,'SamplingSatyCount']
-    all_statistic_info.loc[0,'controller_safety_risk_count']=SatftyCount.loc[0,'CtrlSaftyCodeCount']
-    all_statistic_info.loc[0,'design_safety_risk_count']=SatftyCount.loc[0,'DsnSaftyCodeCount']
-#定时任务....................................................................................................................................................................... 
-#Week_Task()
-Minutes_Task()
-scheduler = BlockingScheduler()
-scheduler.add_job(Week_Task, 'interval', days=7, id='Week_Task')
-scheduler.add_job(Minutes_Task, 'interval', seconds=300, id='Hour_Task')
-try:  
-    scheduler.start()
-except Exception as e:
-    scheduler.shutdown()
-    print(repr(e))

+ 35 - 0
LIB/MIDDLE/SaftyCenter/Low_Soc_Alarm/low_soc_alarm.py

@@ -0,0 +1,35 @@
+import numpy as np
+import pandas as pd
+from pandas.core.frame import DataFrame
+from LIB.MIDDLE.SaftyCenter.Common import QX_BatteryParam
+from LIB.BACKEND import DBManager
+import datetime,time
+
+class Low_soc_alarm():
+    def low_soc_alarm(param,df_bms,low_soc_bat_list,sn,df_OprtnSta):
+        if len(df_bms) and df_OprtnSta.loc[0,'status'] !=3:#0禁用 1正常 2故障 3返修 4 损毁 5丢失已赔偿,6丢失未赔偿:
+            VoltageNum=['单体电压'+str(i) for i in range(1,param.CellVoltNums+1)]
+            df_bms[VoltageNum]=df_bms[VoltageNum]/1000
+            CellVol=df_bms[VoltageNum]
+            PackCrnt=df_bms['总电流[A]']
+            ZeroCrntCount=len(df_bms[abs(df_bms['总电流[A]'])<=1])
+            CrntCount=len(PackCrnt)-ZeroCrntCount
+            if CrntCount>0:
+                ZeroCrntRate=(ZeroCrntCount/len(PackCrnt))*100
+            else:
+                ZeroCrntRate=100
+            if ZeroCrntRate>99.85:#静置比大于99.85%
+                ZeroSoc_Volt=np.interp(0,param.LookTab_SOC,param.LookTab_OCV)
+                FiveSoc_Volt=np.interp(10,param.LookTab_SOC,param.LookTab_OCV)
+                CellVolMean=DataFrame()
+                CellVolMean=CellVol.mean()
+                CellVolMin_Index=CellVolMean.idxmin()
+                print(ZeroSoc_Volt)
+                CellLowVolZERO=df_bms[df_bms[CellVolMin_Index] < ZeroSoc_Volt]
+                CellLowVolFive=df_bms[df_bms[CellVolMin_Index] > FiveSoc_Volt]
+                CellLowVolZeroCrnt=CellLowVolZERO[abs(CellLowVolZERO['总电流[A]'])<1]
+                CellLowVolFiveCrnt=CellLowVolFive[abs(CellLowVolFive['总电流[A]'])<1]
+                if len(CellLowVolZeroCrnt)>3 and len(CellLowVolFiveCrnt)<3:
+                    CellLowVolZeroCrnt=CellLowVolZeroCrnt.reset_index(drop=True)
+                    low_soc_bat_list.loc[len(low_soc_bat_list)]=[sn,CellLowVolZeroCrnt.loc[len(CellLowVolZeroCrnt)-1,'时间戳'],3]
+        return low_soc_bat_list

+ 86 - 0
LIB/MIDDLE/SaftyCenter/Low_Soc_Alarm/main.py

@@ -0,0 +1,86 @@
+import datetime
+import pandas as pd
+from LIB.BACKEND import DBManager, Log
+from sqlalchemy import create_engine
+import time, datetime
+from apscheduler.schedulers.blocking import BlockingScheduler
+from LIB.MIDDLE.CellStateEstimation.Common.V1_0_1 import DBDownload as DBDownload
+from LIB.MIDDLE.CellStateEstimation.Common.V1_0_1 import log
+from pandas.core.frame import DataFrame
+import datacompy
+from LIB.MIDDLE.SaftyCenter.Common import QX_BatteryParam
+from LIB.MIDDLE.SaftyCenter.Common import DBDownload as DBDw
+from low_soc_alarm import Low_soc_alarm
+def Low_Soc_Alarm():
+    end_time=datetime.datetime.now()
+    start_time=end_time-datetime.timedelta(days=1)
+    start_time=start_time.strftime('%Y-%m-%d %H:%M:%S')
+    end_time=end_time.strftime('%Y-%m-%d %H:%M:%S')
+    #-------------------------读取数据-------------------------------------------------------------------
+    excelpath=r'D:\ZLWORK\code\data_analyze_platform\USER\eric\SaftyCenter_CODE_V1\sn-20210903.xlsx'
+    SNdata_6060 = pd.read_excel(excelpath, sheet_name='科易6060')
+    SNdata_6040 = pd.read_excel(excelpath, sheet_name='科易6040')
+    SNdata_4840 = pd.read_excel(excelpath, sheet_name='科易4840')
+    SNdata_L7255 = pd.read_excel(excelpath, sheet_name='格林美-力信7255')
+    SNdata_C7255 = pd.read_excel(excelpath, sheet_name='格林美-CATL7255')
+    SNdata_U7255 = pd.read_excel(excelpath, sheet_name='优旦7255')
+    SNnums_6060=SNdata_6060['SN号'].tolist()
+    SNnums_6040=SNdata_6040['SN号'].tolist()
+    SNnums_4840=SNdata_4840['SN号'].tolist()
+    SNnums_L7255=SNdata_L7255['SN号'].tolist()
+    SNnums_C7255=SNdata_C7255['SN号'].tolist()
+    SNnums_U7255=SNdata_U7255['SN号'].tolist()
+    SNnums=SNnums_L7255 + SNnums_C7255 + SNnums_6040 + SNnums_4840 + SNnums_U7255+ SNnums_6060
+    #SNnums=['MGMCLN750N215I009']
+    #-------------------------执行循环----------------------------------------------------------------------
+    low_soc_bat_list=DataFrame(columns=['sn','time','level'])
+    for sn in SNnums:#SN遍历
+        print(sn)
+        if 'PK500' in sn:
+            celltype=1 #6040三元电芯
+        elif 'PK502' in sn:
+            celltype=2 #4840三元电芯
+        elif 'K504B' in sn:
+            celltype=99    #60ah林磷酸铁锂电芯
+        elif 'MGMLXN750' in sn:
+            celltype=3 #力信50ah三元电芯
+        elif 'MGMCLN750' or 'UD' in sn: 
+            celltype=4 #CATL 50ah三元电芯
+        else:
+            print('SN:{},未找到对应电池类型!!!'.format(sn))
+            continue
+            # sys.exit()
+        param=QX_BatteryParam.BatteryInfo(celltype)   
+        #读取原始数据库数据.....................................................................................
+        dbManager = DBManager.DBManager()
+        df_data = dbManager.get_data(sn=sn, start_time=start_time, end_time=end_time, data_groups=['bms'])
+        df_bms = df_data['bms']
+        #读取电池当前运营状态.....................................................................................................................................................
+        host='rm-bp10j10qy42bzy0q7.mysql.rds.aliyuncs.com'
+        port=3306
+        db='qixiang_manage'
+        user='qx_query'
+        password='@Qx_query'
+        mode=4
+        tablename1='py_battery'     
+        DBRead=DBDw.DBDownload(host, port, db, user, password,mode)
+        with DBRead as DBRead:
+            df_OprtnSta=DBRead.getdata('qrcode','status', tablename=tablename1, sn=sn, timename='', st='', sp='',factory='')#取最后一条运营状态
+        
+        
+        
+        #执行主程序-------------------------------------------------------------------------------------------
+        low_soc_bat_list=Low_soc_alarm.low_soc_alarm(param,df_bms,low_soc_bat_list,sn,df_OprtnSta)
+
+
+    return low_soc_bat_list
+mylog=log.Mylog('log_diag.txt','error')
+mylog.logcfg()
+
+
+try:  
+    low_soc_bat_list=Low_Soc_Alarm()
+    low_soc_bat_list.to_excel('low_soc_bat_list.xlsx')
+except Exception as e:
+    print(repr(e))
+    mylog.logopt(e)

+ 24 - 0
LIB/MIDDLE/SaftyCenter/log.py

@@ -0,0 +1,24 @@
+import logging
+import traceback
+
+class Mylog:
+
+    def __init__(self,log_name,log_level):
+        self.name=log_name
+        self.level=log_level
+    
+    def logcfg(self):
+        if len(self.level) > 0:
+            if self.level == 'debug':
+                Level=logging.DEBUG
+            elif self.level == 'info':
+                Level=logging.INFO
+            elif self.level == 'warning':
+                Level=logging.WARNING
+            else:
+                Level=logging.ERROR
+        logging.basicConfig(filename=self.name, level=Level,format='%(asctime)s - %(levelname)s - %(message)s')
+
+    def logopt(self,*info):
+        logging.error(info)
+        logging.error(traceback.format_exc())

BIN
Low_Soc_Alarm.xlsx