Bladeren bron

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

Eric412V 2 jaren geleden
bovenliggende
commit
909715ea8a

+ 3 - 4
LIB/FRONTEND/AlgoTest/Algo1/Dockerfile

@@ -22,13 +22,12 @@ RUN pip install -i https://pypi.tuna.tsinghua.edu.cn/simple \
 #RUN rm -r /usr/bin
 #RUN rm -r /bin
 
-
-
-# 复制算法文件到 容器
+# 配置算法路径
 ARG ALGO_PATH=LIB/MIDDLE/AlgoTest/Algo1
+# 配置版本路径
 ARG ALGO_VERSION=V_1_0_0
 
-# 复制公共库文件到 容器
+# 复制文件文件到 容器
 ADD LIB/BACKEND/ /LIB/BACKEND
 ADD ${ALGO_PATH}/${ALGO_VERSION}/ /${ALGO_VERSION}/
 ADD ${ALGO_PATH}/main.py /main.py

+ 26 - 6
LIB/MIDDLE/AlgoTest/Algo1/main.py

@@ -1,16 +1,36 @@
 import pandas as pd
-from LIB.BACKEND import DBManager # 以相对路径的方式引入!!!!!
-import V_1_0_0.core as core # 以相对路径的方式引入!!!!!
-
+import time
+from LIB.BACKEND import DBManager,Log # 以相对路径的方式引入!!!!!
+from V_1_0_0 import core # 以相对路径的方式引入!!!!!
+import os
 if __name__ == '__main__':
     
-    sn = "PK10001A326000123"
+    # 获取环境变量
+    env_dist = os.environ
+    host = env_dist.get("HOST", '120.25.223.1')
+    port = env_dist.get("PORT", '4901')
+    db = env_dist.get("DB", 'ali')
+    user = env_dist.get("ROOT", 'root')
+    password = env_dist.get("PASSWORD", '123456')
+    
+    # 日志配置
+    now_str = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()).replace(":","_")
+    log_path = 'log/' + now_str
+    if not os.path.exists(log_path):
+        os.makedirs(log_path)
+    log = Log.Mylog(log_name='cal_sor', log_level = 'info')
+    log.set_file_hl(file_name='{}/info.log'.format(log_path), log_level='info', size=1024* 1024 * 100)
+    log.set_file_hl(file_name='{}/error.log'.format(log_path), log_level='error', size=1024* 1024 * 100)
+    logger = log.get_logger()
+    
+    # 准备算法数据
+    sn = "PK10001A326000123" 
     st = '2021-07-06 00:00:00'
     et = '2021-07-07 20:00:00'
-
     dbManager = DBManager.DBManager()
     df_data = dbManager.get_data(sn=sn, start_time=st, end_time=et, data_groups=['bms', 'gps', 'accum', 'system'])
-# 
     df_bms = df_data['bms']
+    # 调用核心算法
     calSor = core.CalSor();
+    # 接收算法结果
     print(calSor.calSor(df_bms,df_bms))

+ 699 - 0
LIB/MIDDLE/CellStateEstimation/BatDiag/V1_0_0/CBMSBatDiag.py

@@ -0,0 +1,699 @@
+import pandas as pd
+import numpy as np
+import datetime
+from LIB.MIDDLE.CellStateEstimation.Common.V1_0_1 import BatParam
+
+class BatDiag:
+    def __init__(self,sn,celltype,df_bms,df_diag_ram_sn,df_bms_ram_sn,df_soh,df_uniform):  #参数初始化
+
+        self.sn=sn
+        self.celltype=celltype
+        self.param=BatParam.BatParam(celltype)
+        self.df_bms=df_bms
+        self.df_uniform=df_uniform
+        self.df_soh=df_soh
+        self.df_bms_ram=df_bms_ram_sn.copy()
+        self.df_diag_ram=df_diag_ram_sn.copy()
+        df_bms['时间戳']=pd.to_datetime(df_bms['时间戳'], format='%Y-%m-%d %H:%M:%S')
+
+        if not df_bms_ram_sn.empty:
+            self.df_bms=self.df_bms[self.df_bms['时间戳'] > df_bms_ram_sn.iloc[-1]['time']]    #滤除原始数据中的重复数据
+            self.df_bms.reset_index(inplace=True,drop=True)     #重置索引
+        
+        self.packcrnt=df_bms['总电流[A]']*self.param.PackCrntDec
+        self.packvolt=df_bms['总电压[V]']
+        self.bmstime= df_bms['时间戳']
+        self.bms_soc=df_bms['SOC[%]']
+
+        self.cellvolt_name=['单体电压'+str(x) for x in range(1,self.param.CellVoltNums+1)]
+        # othertemp=['其他温度'+str(x) for x in range(1,self.param.OtherTempNums+1)]
+        self.celltemp_name=['单体温度'+str(x) for x in range(1,self.param.CellTempNums+1)]
+        # self.celltemp_name=celltemp+othertemp
+
+    
+    def diag(self):
+        if self.celltype<=50:
+            df_res1,df_res2=self._bat_diag()
+            return df_res1,df_res2    
+        else:
+            df_res1,df_res2=self._bat_diag()
+            return df_res1,df_res2
+
+    
+    #寻找当前行数据的所有温度值...................................................................................
+    def _celltemp_get(self,num):   
+        celltemp = list(self.df_bms.loc[num,self.celltemp_name])
+        return celltemp
+
+    #获取当前行所有电压数据............................................................................................
+    def _cellvolt_get(self,num): 
+        cellvolt = list(self.df_bms.loc[num,self.cellvolt_name]/1000)
+        return cellvolt
+
+    #..........................................电池诊断功能..................................................................
+    def _bat_diag(self):
+
+        column_name=['start_time', 'end_time', 'product_id', 'code', 'level', 'info','advice']
+        df_res=pd.DataFrame(columns=column_name)
+
+        end_time='0000-00-00 00:00:00'
+        ah_accum=0  #SOC卡滞初始参数
+        as_chg=0    #过流诊断初始参数
+        as_dis=0    #过流诊断初始参数
+        cellvoltvalid=1
+        voltdsc_time=0
+        voltdsc_count=0
+        voltfail_time=0
+        voltfail_count=0
+        voltloose_time=0
+        voltloose_count=0
+        voltover_time=0
+        voltunder_time=0
+        cov_time=0
+        cuv_time=0
+        cdv_time=0
+        pov_time=0
+        puv_time=0 
+        ot_time=0
+        ut_time=0
+        dt_time=0
+            
+        for i in range(len(self.df_bms)):
+        
+            #电压诊断功能.........................................................................................................................................
+            if i<1:
+                cellvolt2=self._cellvolt_get(i)
+                cellvoltmin2=min(cellvolt2)
+                cellvoltmax2=max(cellvolt2)
+                cellvoltmin_index2=cellvolt2.index(cellvoltmin2)
+                cellvoltmax_index2=cellvolt2.index(cellvoltmax2)
+                if not self.df_bms_ram.empty:
+                    time1=self.df_bms_ram.iloc[-1]['time']
+                    time2=self.bmstime[i]
+                    cellvolt1=self.df_bms_ram.iloc[-1]['cellvolt']
+                    cellvoltmin1=min(cellvolt1)
+                    cellvoltmax1=max(cellvolt1)
+                    cellvoltmin_index1=cellvolt1.index(cellvoltmin1)
+                    cellvoltmax_index1=cellvolt1.index(cellvoltmax1)
+                else:
+                    cellvolt1=cellvolt2
+                    time1=self.bmstime[i]
+                    time2=self.bmstime[i]
+                    cellvoltmin1=cellvoltmin2
+                    cellvoltmax1=cellvoltmax2
+                    cellvoltmin_index1=cellvoltmin_index2
+                    cellvoltmax_index1=cellvoltmax_index2
+            else:
+                time1=self.bmstime[i-1]
+                time2=self.bmstime[i]
+                cellvolt2=self._cellvolt_get(i)
+                cellvoltmin2=min(cellvolt2)
+                cellvoltmax2=max(cellvolt2)
+                cellvoltmin_index2=cellvolt2.index(cellvoltmin2)
+                cellvoltmax_index2=cellvolt2.index(cellvoltmax2)
+                cellvolt1=self._cellvolt_get(i-1)
+                cellvoltmin1=min(cellvolt1)
+                cellvoltmax1=max(cellvolt1)
+                cellvoltmin_index1=cellvolt1.index(cellvoltmin1)
+                cellvoltmax_index1=cellvolt1.index(cellvoltmax1)
+
+            #电压采样断线..........................................................................................................................................
+            if not 'C308' in list(self.df_diag_ram['code']):  #当前故障中没有该故障,则判断是否发生该故障
+                if (cellvoltmin2<2 and cellvoltmax2>4.5 and abs(cellvoltmax_index2-cellvoltmin_index2)==1) and (cellvoltmin1<2 and cellvoltmax1>4.5 and abs(cellvoltmax_index1-cellvoltmin_index1)==1):   #电压断线故障进入
+                    cellvoltvalid=0
+                    voltdsc_time=voltdsc_time+(time2-time1).total_seconds()
+                    if voltdsc_time>self.param.volt_time:    #持续时间
+                        time=self.bmstime[i]
+                        code='C308'
+                        faultlv=3
+                        faultinfo='电芯{}和{}电压采样断线'.format(cellvoltmin_index2+1, cellvoltmax_index2+1)
+                        faultadvice='通知用户更换电池,电池返厂维修'
+                        self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, faultadvice]
+                    else:
+                        pass
+                elif (cellvoltmin2<2 and cellvoltmax2>4.5 and abs(cellvoltmax_index2-cellvoltmin_index2)==1) and (cellvoltmin1>2.5 and cellvoltmax1<4.3):   #连续跳变
+                    cellvoltvalid=0
+                    voltdsc_count=voltdsc_count+1
+                    if voltdsc_count>=3:
+                        time=self.bmstime[i]
+                        code='C308'
+                        faultlv=3
+                        faultinfo='电芯{}和{}电压采样断线'.format(cellvoltmin_index2+1, cellvoltmax_index2+1)
+                        faultadvice='通知用户更换电池,电池返厂维修'
+                        self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, faultadvice]
+                    else:
+                        pass
+                else:
+                    voltdsc_time=0
+            else:
+                cellvoltvalid=0
+                if cellvoltmin2>2 and cellvoltmax2<4.5 and cellvoltmin1>2 and cellvoltmax1<4.5:
+                    cellvoltvalid=1
+                    time=self.bmstime[i]
+                    self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']=='C308'].index, 'end_time'] = time
+                else:
+                    pass
+            
+            #电压采样系统失效.............................................................................................................
+            if not 'C309' in list(self.df_diag_ram['code']):  #当前故障中没有该故障,则判断是否发生该故障
+                if (cellvoltmin2<1 and cellvoltmin1<1) or (cellvoltmax2>5 and cellvoltmax1>5):
+                    cellvoltvalid=0
+                    voltfail_time=voltfail_time+(time2-time1).total_seconds()
+                    if voltfail_time>self.param.volt_time:    #持续时间
+                        time=self.bmstime[i]
+                        code='C309'
+                        faultlv=3
+                        faultinfo='电芯电压采样系统失效'
+                        faultadvice='通知用户更换电池,电池返厂维修'
+                        self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, faultadvice]
+                    else:
+                        pass
+                elif (cellvoltmin2<1 and cellvoltmin1>2.5) or  (cellvoltmax2>5 and cellvoltmax1<4.5):   #连续跳变
+                    cellvoltvalid=0
+                    voltfail_count=voltfail_count+1
+                    if voltfail_count>=3:
+                        time=self.bmstime[i]
+                        code='C309'
+                        faultlv=3
+                        faultinfo='电芯电压采样系统失效'
+                        faultadvice='通知用户更换电池,电池返厂维修'
+                        self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, faultadvice]
+                    else:
+                        pass
+                else:
+                    voltfail_time=0
+            else:
+                cellvoltvalid=0
+                if cellvoltmin2>2.5 and cellvoltmax2<4.5 and cellvoltmin1>2.5 and cellvoltmax1<4.5:
+                    cellvoltvalid=1
+                    time=self.bmstime[i]
+                    self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']=='C309'].index, 'end_time'] = time
+                else:
+                    pass
+            
+            #电压采样线松动.................................................................................................................
+            if not 'C208' in list(self.df_diag_ram['code']):  #当前故障中没有该故障,则判断是否发生该故障
+                if cellvoltmin2>2 and cellvoltmax2<4.5 and cellvoltmin1>2 and cellvoltmax1<4.5:
+                    cellvolt1_std=np.std(cellvolt1)
+                    cellvolt1_mean=np.mean(cellvolt1)
+                    cellvolt1_3sigma=(np.array(cellvolt1)-cellvolt1_mean)/cellvolt1_std
+                    cellvolt2_std=np.std(cellvolt2)
+                    cellvolt2_mean=np.mean(cellvolt2)
+                    cellvolt2_3sigma=(np.array(cellvolt2)-cellvolt2_mean)/cellvolt2_std
+                    if (min(cellvolt1_3sigma)<-3 and max(cellvolt1_3sigma)>3) and (min(cellvolt2_3sigma)<-3 and max(cellvolt2_3sigma)>3):   #连续发生
+                        cellvoltvalid=0
+                        voltloose_time=voltloose_time+(time2-time1).total_seconds()
+                        if voltloose_time>self.param.volt_time:
+                            time=self.bmstime[i]
+                            code='C208'
+                            faultlv=3
+                            faultinfo='电芯电压{}和{}采样松动'.format(cellvoltmin_index2+1, cellvoltmax_index2+1)
+                            faultadvice='通知技术人员介入诊断'
+                            self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, faultadvice]
+                        else:
+                            pass
+                    elif (min(cellvolt1_3sigma)>-3 and max(cellvolt1_3sigma)<3) and (min(cellvolt2_3sigma)<-3 and max(cellvolt2_3sigma)>3): #连续跳变
+                        cellvoltvalid=0
+                        voltloose_count=voltloose_count+1
+                        if voltloose_count>=3:
+                            time=self.bmstime[i]
+                            code='C208'
+                            faultlv=3
+                            faultinfo='电芯电压{}和{}采样松动'.format(cellvoltmin_index2+1, cellvoltmax_index2+1)
+                            faultadvice='通知技术人员介入诊断'
+                            self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, faultadvice]
+                        else:
+                            pass
+                    else:
+                        voltloose_time=0
+                else:
+                    voltloose_time=0
+            else:
+                cellvoltvalid=0
+                cellvolt1_std=np.std(cellvolt1)
+                cellvolt1_mean=np.mean(cellvolt1)
+                cellvolt1_3sigma=(np.array(cellvolt1)-cellvolt1_mean)/cellvolt1_std
+                cellvolt2_std=np.std(cellvolt2)
+                cellvolt2_mean=np.mean(cellvolt2)
+                cellvolt2_3sigma=(np.array(cellvolt2)-cellvolt2_mean)/cellvolt2_std
+                if(min(cellvolt1_3sigma)>-3 or max(cellvolt1_3sigma)<3) and (min(cellvolt2_3sigma)>-3 or max(cellvolt2_3sigma)<3):
+                    cellvoltvalid=1
+                    time=self.bmstime[i]
+                    self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']=='C208'].index, 'end_time'] = time
+                else:
+                    pass
+        
+            if cellvoltvalid==1:
+                #继电器粘连.............................................................................................................................................
+                if not 'C310' in list(self.df_diag_ram['code']):  #当前故障中没有该故障,则判断是否发生该故障
+                    if cellvoltmax2>self.param.CellOvLv2 and cellvoltmax1>self.param.CellOvLv2 and self.packcrnt[i]<0:
+                        voltover_time=voltover_time+(time2-time1).total_seconds()
+                        if voltover_time>self.param.volt_time:
+                            time=self.bmstime[i]
+                            code='C310'
+                            faultlv=3
+                            faultinfo='充电继电器粘连'
+                            faultadvice='通知技术人员介入诊断'
+                            self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, faultadvice]
+                        else:
+                            pass
+                    else:
+                        voltover_time=0
+                else:
+                    if cellvoltmax2<self.param.CellOvLv2-0.05 and cellvoltmax1<self.param.CellOvLv2-0.05:
+                        time=self.bmstime[i]
+                        self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']=='C310'].index, 'end_time'] = time
+                    else:
+                        pass
+            
+                if not 'C311' in list(self.df_diag_ram['code']):  #当前故障中没有该故障,则判断是否发生该故障
+                    if cellvoltmin2<self.param.CellUvLv2 and cellvoltmin1<self.param.CellUvLv2 and self.packcrnt[i]>0:
+                        voltunder_time=voltunder_time+(time2-time1).total_seconds()
+                        if voltunder_time>self.param.volt_time:
+                            time=self.bmstime[i]
+                            code='C311'
+                            faultlv=3
+                            faultinfo='放电继电器粘连'
+                            faultadvice='通知技术人员介入诊断'
+                            self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, faultadvice]
+                        else:
+                            pass
+                    else:
+                        voltunder_time=0
+                else:
+                    if cellvoltmin2>self.param.CellUvLv2+0.05 and cellvoltmin1>self.param.CellOvLv2+0.05:
+                        time=self.bmstime[i]
+                        self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']=='C311'].index, 'end_time'] = time
+                    else:
+                        pass
+                
+                #电芯过压.............................................................................................................................................
+                if not 'C501' in list(self.df_diag_ram['code']):  #当前故障中没有该故障,则判断是否发生该故障
+                    if cellvoltmax2>self.param.CellOvLv2 and cellvoltmax1>self.param.CellOvLv2 and self.packcrnt[i]<0:  #二级过压进入
+                        cov_time=cov_time+(time2-time1).total_seconds()
+                        if cov_time>self.param.volt_time:
+                            time=self.bmstime[i]
+                            code='C501'
+                            faultlv=5
+                            faultinfo='电芯{}过压'.format(cellvolt1.index(cellvoltmax1)+1)
+                            faultadvice='联系用户立即停止充电,并通知技术运维人员'
+                            self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, faultadvice]
+                        else:
+                            pass
+                    else:
+                        cov_time=0
+                else:   #ram当前故障中有该故障,则判断是否退出该故障
+                    if cellvoltmax2<self.param.CellOvLv1-0.05 and cellvoltmax1<self.param.CellOvLv1-0.05:   #二级过压故障恢复
+                        time=self.bmstime[i]
+                        self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']=='C501'].index, 'end_time'] = time
+                    else:
+                        pass
+                
+                #欠压诊断.................................................................................................................
+                if not 'C202' in list(self.df_diag_ram['code']):  #当前故障中没有该故障,则判断是否发生该故障
+                    if cellvoltmin2<self.param.CellUvLv2 and cellvoltmin1<self.param.CellUvLv2:  #二级欠压
+                        cuv_time=cuv_time+(time2-time1).total_seconds()
+                        if cuv_time>self.param.volt_time:
+                            time=self.bmstime[i]
+                            code='C202'
+                            faultlv=2
+                            faultinfo='电芯{}欠压'.format(cellvolt1.index(cellvoltmin1)+1)
+                            faultadvice='联系用户询问用车场景,技术介入诊断'
+                            self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, faultadvice]
+                        else:
+                            pass
+                    else:
+                        cuv_time=0
+                else:
+                    if cellvoltmin2>self.param.CellUvLv1+0.1 and cellvoltmin1>self.param.CellUvLv1+0.1:
+                        time=self.bmstime[i]
+                        self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']=='C202'].index, 'end_time'] = time
+                    else:
+                        pass
+             
+                #电芯压差大.....................................................................................................................................................
+                if not 'C104' in list(self.df_diag_ram['code']):  #当前故障中没有该故障,则判断是否发生该故障
+                    if (cellvoltmax2-cellvoltmin2)>self.param.CellVoltDiffLv2 and (cellvoltmax1-cellvoltmin1)>self.param.CellVoltDiffLv2:  #二级电芯压差
+                        cdv_time=cdv_time+(time2-time1).total_seconds()
+                        if cdv_time>self.param.volt_time:
+                            time=self.bmstime[i]
+                            code='C104'
+                            faultlv=0
+                            faultinfo='电芯{}和{}压差大'.format(cellvolt1.index(cellvoltmax1)+1,cellvolt1.index(cellvoltmin1)+1)
+                            faultadvice='技术介入诊断'
+                            self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, faultadvice]
+                        else:
+                            pass
+                    else:
+                        cdv_time=0
+                else:
+                    if (cellvoltmax2-cellvoltmin2)<self.param.CellVoltDiffLv1-0.05 and (cellvoltmax1-cellvoltmin1)<self.param.CellVoltDiffLv1-0.05: #二级欠压恢复
+                        time=self.bmstime[i]
+                        self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']=='C104'].index, 'end_time'] = time
+                    else:
+                        pass
+            else:
+                cov_time=0
+                cuv_time=0
+                cdv_time=0
+            
+            #电池包诊断.....................................................................................................................................
+            if i<1:
+                if not self.df_bms_ram.empty:
+                    packvolt1=self.df_bms_ram.iloc[-1]['packvolt']
+                    packvolt2=self.packvolt[i]
+                    time1=self.df_bms_ram.iloc[-1]['time']
+                    time2=self.bmstime[i]
+                else:
+                    packvolt1=self.packvolt[i]
+                    packvolt2=self.packvolt[i]
+                    time1=self.bmstime[i]
+                    time2=self.bmstime[i]
+            else:
+                packvolt1=self.packvolt[i-1]
+                packvolt2=self.packvolt[i]
+                time1=self.bmstime[i-1]
+                time2=self.bmstime[i]
+            if packvolt1<2*self.param.CellVoltNums or packvolt2>4.5*self.param.CellVoltNums:   #电池包电压有效性
+                packvoltvalid=0
+            else:
+                packvoltvalid=1
+
+            if packvoltvalid==1:
+                if not 'C502' in list(self.df_diag_ram['code']):  #当前故障中没有该故障,则判断是否发生该故障
+                    if packvolt1>self.param.PackVoltOvLv2 and packvolt2>self.param.PackVoltOvLv2 and self.packcrnt[i]<0:   #电池包过压二级进入
+                        pov_time=pov_time+(time2-time1).total_seconds()
+                        if pov_time>self.param.volt_time:
+                            time=self.bmstime[i]
+                            code='C502'
+                            faultlv=5
+                            faultinfo='电池包过压'
+                            faultadvice='联系用户立即停止充电,并通知技术运维人员'
+                            self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, faultadvice]
+                        else:
+                            pass
+                    else:
+                        pov_time=0
+                else:
+                    if packvolt1<self.param.PackVoltOvLv1-0.05*self.param.CellVoltNums and packvolt2<self.param.PackVoltOvLv1-0.05*self.param.CellVoltNums: #电池包过压二级恢复
+                        time=self.bmstime[i]
+                        self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']=='C502'].index, 'end_time'] = time
+                    else:
+                        pass
+          
+                if not 'C203' in list(self.df_diag_ram['code']):  #当前故障中没有该故障,则判断是否发生该故障
+                    if packvolt1<self.param.PackVoltUvLv2 and packvolt2<self.param.PackVoltUvLv2:   #电池包二级欠压进入
+                        puv_time=puv_time+(time2-time1).total_seconds()
+                        if puv_time>self.param.volt_time:
+                            time=self.bmstime[i]
+                            code='C203'
+                            faultlv=2
+                            faultinfo='电池包欠压'
+                            faultadvice='联系用户询问用车场景,技术介入诊断'
+                            self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, faultadvice]
+                        else:
+                            pass
+                    else:
+                        puv_time=0
+                else:
+                    if packvolt1>self.param.PackVoltUvLv1+0.1*self.param.CellVoltNums and packvolt2>self.param.PackVoltUvLv1+0.1*self.param.CellVoltNums:   #电池包二级欠压恢复
+                        time=self.bmstime[i]
+                        self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']=='C203'].index, 'end_time'] = time
+                    else:
+                        pass
+            else:
+                pov_time=0
+                puv_time=0 
+            
+            #温度诊断功能.............................................................................................................
+            if i<1:
+                if not self.df_bms_ram.empty:
+                    celltemp1=self.df_bms_ram.iloc[-1]['celltemp']
+                    celltemp2=self._celltemp_get(i)
+                    time1=self.df_bms_ram.iloc[-1]['time']
+                    time2=self.bmstime[i]
+                else:
+                    celltemp1=self._celltemp_get(i)
+                    celltemp2=self._celltemp_get(i)
+                    time1=self.bmstime[i]
+                    time2=self.bmstime[i]
+            else:
+                celltemp1=self._celltemp_get(i-1)
+                celltemp2=self._celltemp_get(i)
+                time1=self.bmstime[i-1]
+                time2=self.bmstime[i]
+            celltempmin1=min(celltemp1)
+            celltempmin2=min(celltemp2)
+            celltempmax1=max(celltemp1)
+            celltempmax2=max(celltemp2)
+            #温度有效性判断..........................................................................
+            if celltempmax1>self.param.CellTempUpLmt or celltempmin1<self.param.CellTempLwLmt:
+                celltempvalid=0
+            else:  
+                celltempvalid=1
+           
+            if celltempvalid==1:
+                #过温判断.............................................................................................................
+                if not 'C302' in list(self.df_diag_ram['code']):  #当前故障中没有该故障,则判断是否发生该故障
+                    if celltempmax1>self.param.CellTempHighLv2 and celltempmax2>self.param.CellTempHighLv2:    #二级高温进入
+                        ot_time=ot_time+(time2-time1).total_seconds()
+                        if ot_time>self.param.temp_time:
+                            time=self.bmstime[i]
+                            code='C302'
+                            faultlv=3
+                            faultinfo='温度{}高温'.format(celltemp1.index(celltempmax1)+1)
+                            faultadvice='技术介入诊断'
+                            self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, faultadvice]
+                        else:
+                            pass
+                    else:
+                        ot_time=0
+                else:   #ram当前故障中有该故障,则判断是否退出该故障
+                    if celltempmax1<self.param.CellTempHighLv1-5 and celltempmax2<self.param.CellTempHighLv1-5:    #二级高温恢复
+                        time=self.bmstime[i]
+                        self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']=='C302'].index, 'end_time'] = time
+                    else:
+                        pass
+            
+                #欠温判断.................................................................................................................
+                if not 'C102' in list(self.df_diag_ram['code']):  #当前故障中没有该故障,则判断是否发生该故障
+                    if celltempmin1<self.param.CellTempLowLv2 and celltempmin2<self.param.CellTempLowLv2:  #二级低温进入
+                        ut_time=ut_time+(time2-time1).total_seconds()
+                        if ut_time>self.param.temp_time:
+                            time=self.bmstime[i]
+                            code='C102'
+                            faultlv=1
+                            faultinfo='温度{}低温'.format(celltemp1.index(celltempmin1)+1)
+                            faultadvice='技术介入诊断'
+                            self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, faultadvice]
+                        else:
+                            pass
+                    else:
+                        ut_time=0
+                else:   #ram当前故障中有该故障,则判断是否退出该故障
+                    if celltempmax1>self.param.CellTempLowLv1+2 and celltempmax2>self.param.CellTempLowLv1+2:    #二级高温恢复
+                        time=self.bmstime[i]
+                        self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']=='C102'].index, 'end_time'] = time
+                    else:
+                        pass
+              
+                #温差判断.............................................................................................................................
+                if not 'C103' in list(self.df_diag_ram['code']):  #当前故障中没有该故障,则判断是否发生该故障
+                    if (celltempmax1-celltempmin1)>self.param.CellTempDiffLv2 and (celltempmax2-celltempmin2)>self.param.CellTempDiffLv2:  #二级温差进入
+                        dt_time=dt_time+(time2-time1).total_seconds()
+                        if dt_time>self.param.temp_time:
+                            time=self.bmstime[i]
+                            code='C103'
+                            faultlv=1
+                            faultinfo='温度{}和{}温差大'.format(celltemp1.index(celltempmax1)+1,celltemp1.index(celltempmin1)+1)
+                            faultadvice='技术介入诊断'
+                            self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, faultadvice]
+                        else:
+                            pass
+                    else:
+                        dt_time=0
+                else:   #ram当前故障中有该故障,则判断是否退出该故障
+                    if (celltempmax1-celltempmin1)<self.param.CellTempDiffLv1-2 and (celltempmax2-celltempmin2)>self.param.CellTempDiffLv1-2:  #二级温差恢复
+                        time=self.bmstime[i]
+                        self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']=='C103'].index, 'end_time'] = time
+                    else:
+                        pass
+            
+            else:
+                ot_time=0
+                ut_time=0
+                dt_time=0
+            
+            #电流过流诊断.......................................................................................................................
+            if i>0.5:
+                step=(self.bmstime[i]-self.bmstime[i-1]).total_seconds()
+                if step<120 and self.packcrnt[i]>self.param.PackDisOc and self.packcrnt[i-1]>self.param.PackDisOc:
+                    as_dis=as_dis+(self.packcrnt[i]-self.param.PackDisOc)*step    #ah累计
+                elif step<120 and self.packcrnt[i]<self.param.PackChgOc and self.packcrnt[i-1]<self.param.PackChgOc:
+                    as_chg=as_chg+(self.param.PackDisOc-self.packcrnt[i])*step    #ah累计
+                else:
+                    as_dis=0
+                    as_chg=0
+                
+                if not 'C306' in list(self.df_diag_ram['code']):  #当前故障中没有该故障,则判断是否发生该故障
+                    if as_dis>100:
+                        time=self.bmstime[i]
+                        code='C306'
+                        faultlv=3
+                        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.packcrnt[i]<self.param.PackDisOc-10:
+                        time=self.bmstime[i]
+                        self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']=='C306'].index, 'end_time'] = time
+                    else:
+                        pass
+                
+                if not 'C305' in list(self.df_diag_ram['code']):  #当前故障中没有该故障,则判断是否发生该故障
+                    if as_chg>100:
+                        time=self.bmstime[i]
+                        code='C305'
+                        faultlv=3
+                        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.packcrnt[i]>self.param.PackChgOc+10:
+                        time=self.bmstime[i]
+                        self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']=='C305'].index, 'end_time'] = time
+                    else:
+                        pass
+            
+            #SOC卡滞、跳变诊断................................................................................................
+            if i<1:
+                bmssoc_st=float(self.bms_soc[i])
+                bmssoc_last=float(self.bms_soc[i])
+                bmssoc_now=float(self.bms_soc[i])
+            else:
+                step=(self.bmstime[i]-self.bmstime[i-1]).total_seconds()
+                if step<120:
+                    ah_accum=ah_accum-self.packcrnt[i]*step/3600    #ah累计
+                else:
+                    pass
+                #SOC卡滞............................................................................................................
+                if abs(ah_accum)>self.param.Capacity*0.1:   
+                    bmssoc_now=float(self.bms_soc[i])
+                    if not 'C106' in list(self.df_diag_ram['code']):  #当前故障中没有该故障,则判断是否发生该故障
+                        if abs(bmssoc_now-bmssoc_st)<self.param.SocClamp:   #SOC卡滞故障进入
+                            time=self.bmstime[i]
+                            code='C106'
+                            faultlv=0
+                            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.SocClamp:   #SOC卡滞故障退出
+                            time=self.bmstime[i]
+                            self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']=='C106'].index, 'end_time'] = time
+                        else:
+                            pass
+                    bmssoc_st=bmssoc_now
+                    ah_accum=0
+                else:
+                    pass
+
+                #SOC跳变....................................................................................................................
+                bmssoc_last=float(self.bms_soc[i-1])
+                bmssoc_now=float(self.bms_soc[i])
+                if not 'C107' in list(self.df_diag_ram['code']):  #当前故障中没有该故障,则判断是否发生该故障
+                    if step<70 and abs(bmssoc_now-bmssoc_last)>self.param.SocJump:  #SOC跳变进入
+                        time=self.bmstime[i]
+                        code='C107'
+                        faultlv=0
+                        faultinfo='电池SOC跳变{}%'.format(bmssoc_now-bmssoc_last)
+                        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']=='C107'].index, 'end_time'] = time
+                    else:
+                        pass
+        
+        #SOC一致性故障报警..........................................................................................................
+        if not self.df_uniform.empty:
+            cellsoc_diff=self.df_uniform.loc[0,'cellsoc_diff']
+            if not 'C201' in list(self.df_diag_ram['code']):  #当前故障中没有该故障,则判断是否发生该故障
+                if cellsoc_diff>self.param.SocDiff: #SOC一致性差故障进入
+                    time=self.bmstime[0]
+                    code='C201'
+                    faultlv=0
+                    faultinfo='电芯{}和{}SOC差过大:{}'.format(int(self.df_uniform.loc[0,'cellmin_num']),int(self.df_uniform.loc[0,'cellmax_num']),cellsoc_diff)
+                    faultadvice='技术介入诊断'
+                    self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, faultadvice]
+                else:
+                    pass
+            else:
+                if cellsoc_diff<self.param.SocDiff: #SOC一致性差故障恢复
+                    time=self.bmstime[0]
+                    self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']=='C201'].index, 'end_time'] = time
+        else:
+            cellsoc_diff=3
+
+        #容量过低和一致性故障报警................................................................................................
+        if not self.df_soh.empty:
+            soh=self.df_soh.loc[0,'soh']
+            cellsoh=eval(self.df_soh.loc[0,'cellsoh'])
+            cellsoh=np.array(cellsoh)
+            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=np.max(cellsoh)-np.min(cellsoh)
+                if not 'C204' in list(self.df_diag_ram['code']):  #当前故障中没有该故障,则判断是否发生该故障
+                    if soh<self.param.SohLow:   #soh过低故障进入
+                        time=self.bmstime[0]
+                        code='C204'
+                        faultlv=2
+                        faultinfo='电池包容量过低:电芯{}'.format(cellsoh_lowindex)
+                        faultadvice='检修电池,更换容量过低的电芯或模组'
+                        self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, faultadvice]
+                    else:
+                        pass
+                else:
+                    if soh>self.param.SohLow+2:   #soh过低故障恢复
+                        time=self.bmstime[0]
+                        self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']=='C204'].index, 'end_time'] = time
+                    else:
+                        pass
+
+                if not 'C205' in list(self.df_diag_ram['code']):  #当前故障中没有该故障,则判断是否发生该故障
+                    if cellsoh_diff>self.param.SohDiff:
+                        time=self.bmstime[0]
+                        code='C205'
+                        faultlv=2
+                        faultinfo='电池包容量一致性差:电芯{}'.format(cellsoh_lowindex)
+                        faultadvice='检修电池,更换容量过低的电芯或模组'
+                        self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, faultadvice]
+                    else:
+                        pass
+                else:
+                    if cellsoh_diff<self.param.SohDiff-2:
+                        time=self.bmstime[0]
+                        self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']=='C205'].index, 'end_time'] = time
+                    else:
+                        pass
+            else:
+                pass
+        else:
+            cellsoh_diff=5
+        
+        #ram更新.......................................................................
+        df_bms_ram=pd.DataFrame(columns=['time', 'sn', 'packvolt', 'cellvolt', 'celltemp'])
+        df_bms_ram.loc[0]=[self.bmstime[0], self.sn, packvolt2, cellvolt2, celltemp2]
+
+        return self.df_diag_ram, df_bms_ram
+

+ 164 - 0
LIB/MIDDLE/CellStateEstimation/BatDiag/main.py

@@ -0,0 +1,164 @@
+import CBMSBatDiag
+import pymysql
+import datetime
+import pandas as pd
+from LIB.BACKEND import DBManager
+from sqlalchemy import create_engine
+from urllib import parse
+import datetime, time
+from apscheduler.schedulers.blocking import BlockingScheduler
+from LIB.MIDDLE.CellStateEstimation.Common.V1_0_1 import DBDownload
+from LIB.MIDDLE.CellStateEstimation.Common.V1_0_1 import log
+
+#...................................电池包电芯安全诊断函数......................................................................................................................
+def diag_cal():
+    global SNnums, df_bms_ram
+
+    start=time.time()
+    now_time=datetime.datetime.now()
+    start_time=now_time-datetime.timedelta(seconds=310)
+    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
+    db='safety_platform'
+    user='qx_read'
+    password='Qx@123456'
+
+    #读取故障结果库中当前故障......................................................
+    param='start_time,end_time,product_id,code,level,info,advice'
+    tablename='all_fault_info_copy'
+    mysql = pymysql.connect (host=host, user=user, password=password, port=port, database=db)
+    cursor = mysql.cursor()
+    sql =  "select %s from %s where 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(','))
+    
+
+    db_res_engine = create_engine(
+        "mysql+pymysql://{}:{}@{}:{}/{}?charset=utf8".format(
+            user, parse.quote_plus(password), host, port, db
+        ))
+
+    mylog=log.Mylog('log_diag.txt','error')
+    mylog.logcfg()
+
+    for sn in SNnums:
+        try:
+            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' in sn) or ('UD' in sn): 
+                celltype=4 #CATL 50ah三元电芯
+            else:
+                print('SN:{},未找到对应电池类型!!!'.format(sn))
+                continue
+                # sys.exit()
+
+            #读取原始数据库数据........................................................................................................................................................
+            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']
+
+            #读取结果数据库数据........................................................................................................................................................
+            db='qx_cas'
+            mode=1
+            tablename1='cellstateestimation_soh'
+            tablename2='cellstateestimation_uniform_socvoltdiff'
+            # tablename3='cellstateestimation_soc'
+            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)
+                # df_soc=DBRead.getdata('time','sn','packsoc', tablename=tablename3, sn=sn)
+
+            #电池诊断................................................................................................................................................................
+            if not df_bms.empty:
+                df_diag_ram_sn=df_diag_ram[df_diag_ram['product_id']==sn]
+                df_diag_ram_sn.reset_index(inplace=True,drop=True)
+                df_bms_ram_sn=df_bms_ram[df_bms_ram['sn']==sn]
+                df_bms_ram_sn.reset_index(inplace=True,drop=True)
+                
+                df_bms=df_bms.dropna(axis=0,subset=['总电流[A]','SOH[%]','SOC[%]','总电压[V]']) #去除有空值的行
+                df_bms.reset_index(inplace=True,drop=True)     #重置索引
+
+                batquality=CBMSBatDiag.BatDiag(sn,celltype,df_bms,df_diag_ram_sn,df_bms_ram_sn,df_soh,df_uniform)
+                df_diag_res, df_bms_res=batquality.diag()   #获取电池故障结果和电池评分结果
+
+                #更新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)
+
+                #历史故障筛选并更改数据库故障结束时间.........................................................
+                if not df_diag_res.empty:
+                    df_diag_new = pd.concat([df_diag_res,df_diag_ram_sn,df_diag_ram_sn]).drop_duplicates(subset=['start_time','code'],keep=False)#此次判断中新增故障
+                    df_diag_new.reset_index(inplace=True,drop=True)  #重置索引
+                    df_diag_end=pd.concat([df_diag_res,df_diag_new,df_diag_new]).drop_duplicates(subset=['start_time','code'],keep=False)#此次判断中新增故障
+                    df_diag_end=df_diag_end[df_diag_end['end_time'] != '0000-00-00 00:00:00']
+                    df_diag_end.reset_index(inplace=True,drop=True)  #重置索引
+
+                    if not df_diag_end.empty:   #变为历史故障更改数据库
+                        for j in range(len(df_diag_end)):
+                            cursor.execute('''
+                                        update all_fault_info_copy set update_time='{}',end_time='{}', Batpos={} where product_id='{}' and end_time='0000-00-00 00:00:00' and code='{}'
+                                        '''.format(datetime.datetime.now(), df_diag_end.loc[j,'end_time'], 1 ,sn, df_diag_end.loc[j,'code']))
+                            mysql.commit()
+
+                    #新增故障筛选并存入数据库.....................................................................
+                    if not df_diag_new.empty:  #新增写入数据库
+                        df_diag_new.to_sql("all_fault_info_copy",con=db_res_engine, if_exists="append",index=False)
+
+            end=time.time()
+            print(end-start)  
+            
+        except Exception as e:
+            print(repr(e))
+            mylog.logopt(e)
+
+    cursor.close()
+    mysql.close()
+
+#...............................................主函数起定时作用.......................................................................................................................
+if __name__ == "__main__":
+    
+    excelpath=r'D:\Platform\platform_python\data_analyze_platform\USER\spf\01qixiang\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_U7255 + SNnums_6040 + SNnums_4840 + SNnums_6060
+    
+    mylog=log.Mylog('log_diag.txt','error')
+    mylog.logcfg()
+
+    #参数初始化
+    df_bms_ram=pd.DataFrame(columns=['time', 'sn', 'packvolt', 'cellvolt', 'celltemp'])
+
+    diag_cal()
+    #定时任务.......................................................................................................................................................................
+    scheduler = BlockingScheduler()
+    scheduler.add_job(diag_cal, 'interval', seconds=300)
+
+    try:  
+        scheduler.start()
+    except Exception as e:
+        scheduler.shutdown()
+        print(repr(e))
+        mylog.logopt(e)

+ 7 - 4
LIB/MIDDLE/CellStateEstimation/BatSafetyAlarm/V1_0_1/CBMSSafetyAlarm.py

@@ -110,7 +110,10 @@ class SafetyAlarm:
                     
                     #温升判断.............................................................................................................................
                     delttime=(time2-time1).total_seconds()
-                    celltemp_rate=(max(temp2-temp1)*60)/delttime    #计算最大温升速率
+                    if delttime>1:
+                        celltemp_rate=(max(temp2-temp1)*60)/delttime    #计算最大温升速率
+                    else:
+                        celltemp_rate=0
                     if celltemp_rate>self.param.TrwTempRate and self.param.CellTempLwLmt<min(temp1) and max(temp1)<self.param.CellTempUpLmt:
                         celltemprise=celltemprise+1
                     else:
@@ -215,11 +218,11 @@ class SafetyAlarm:
             trw_array=np.array([trwtemp, trwcellvolt, trwpackvolt])
 
             if np.sum(trw_array)>3.5 and np.sum(trw_array>0.5)>1.5:
-                fltcode=119
+                fltcode='C599'
                 df_res.loc[0]=[self.bmstime[len(self.bmstime)-1], end_time, self.sn, fltcode, 5, '电池发生热失控', '联系用户立即远离电池,并通知技术人员介入']
                 df_ram_alarm=pd.DataFrame(columns=['sn','time','safetywarning1','safetywarning2'])
             elif safetywarning1>2.5 and np.sum(trw_array)>1.5 and np.sum(trw_array>0.5)>1.5:
-                fltcode=119
+                fltcode='C599'
                 df_res.loc[0]=[self.bmstime[len(self.bmstime)-1], end_time, self.sn, fltcode, 5, '电池发生热失控', '联系用户立即远离电池,并通知技术人员介入']
                 df_ram_alarm=pd.DataFrame(columns=['sn','time','safetywarning1','safetywarning2'])
             else:
@@ -248,7 +251,7 @@ class SafetyAlarm:
             df_ram_alarm=self.df_ram_alarm
             df_ram_bms=self.df_ram_bms
             if (safetywarning1>2.5 or safetywarning2>2.5) and (time_now-df_ram_alarm.iloc[-1]['time']).total_seconds()>120:
-                fltcode=119
+                fltcode='C599'
                 time_now=time_now.strftime('%Y-%m-%d %H:%M:%S')
                 time_now=datetime.datetime.strptime(time_now,'%Y-%m-%d %H:%M:%S')
                 df_res.loc[0]=[time_now, end_time, self.sn, fltcode, 5, '电池发生热失控', '联系用户立即远离电池,并通知技术人员介入']

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

@@ -17,7 +17,7 @@ class Mylog:
                 Level=logging.WARNING
             else:
                 Level=logging.ERROR
-        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')
+        logging.basicConfig(filename=r'D:\Develop\User\Songpengfei\data_analyze_platform\WORK\101log\\'+self.name, level=Level,format='%(asctime)s - %(levelname)s - %(message)s')
 
 
     def logopt(self,*info):

+ 131 - 112
demo.ipynb

@@ -2,164 +2,183 @@
  "cells": [
   {
    "cell_type": "code",
-   "execution_count": 2,
-   "source": [
-    "# 获取数据\r\n",
-    "import sys\r\n",
-    "from LIB.BACKEND import DBManager\r\n",
-    "\r\n",
-    "sn = \"PK10001A326000123\"\r\n",
-    "st = '2021-07-06 00:00:00'\r\n",
-    "et = '2021-07-07 20:00:00'\r\n",
-    "\r\n",
-    "dbManager = DBManager.DBManager()\r\n",
-    "df_data = dbManager.get_data(sn=sn, start_time=st, end_time=et, data_groups=['bms', 'gps', 'accum', 'system'])\r\n",
-    "# \r\n",
-    "df_bms = df_data['bms']\r\n",
-    "df_gps = df_data['gps']\r\n",
-    "df_accum = df_data['accum']\r\n",
-    "df_system = df_data['system']"
-   ],
+   "execution_count": 6,
+   "metadata": {},
    "outputs": [
     {
-     "output_type": "stream",
      "name": "stdout",
+     "output_type": "stream",
      "text": [
-      "### start to get data PK10001A326000123 from 2021-07-06 00:00:00 to 2021-07-07 20:00:00\n",
-      "# get data from 2021-07-06 00:00:00 to 2021-07-07 00:00:00......... \n",
-      "Server Error, retry 1...... \n",
-      "# get data from 2021-07-07 00:00:00 to 2021-07-07 20:00:00......... \n",
-      "all data-getting done, bms_count is 0, gps_count is 0, system_count is 0, accum_count is 0 \n",
+      "### start to get data PK50001A100000100 from 2021-02-10 22:54:36 to 2021-02-20 22:54:36\n",
+      "# get data from 2021-02-19 22:54:36 to 2021-02-20 22:54:36......... \n",
+      "all data-getting done, bms_count is 19444, gps_count is 5960, system_count is 566, accum_count is 2391 \n",
       "\n"
      ]
     }
    ],
-   "metadata": {}
+   "source": [
+    "# 获取数据\n",
+    "import sys\n",
+    "from LIB.BACKEND import DBManager\n",
+    "\n",
+    "sn = \"PK50001A100000100\"\n",
+    "st = '2021-02-10 22:54:36'\n",
+    "et = '2021-02-20 22:54:36'\n",
+    "\n",
+    "dbManager = DBManager.DBManager()\n",
+    "df_data = dbManager.get_data(sn=sn, start_time=st, end_time=et, data_groups=['bms', 'gps', 'accum', 'system'])\n",
+    "# \n",
+    "df_bms = df_data['bms']\n",
+    "df_gps = df_data['gps']\n",
+    "df_accum = df_data['accum']\n",
+    "df_system = df_data['system']"
+   ]
   },
   {
    "cell_type": "code",
    "execution_count": null,
-   "source": [
-    "# 下载数据 \r\n",
-    "import sys\r\n",
-    "from LIB.BACKEND import Tools\r\n",
-    "\r\n",
-    "tools = Tools.Tools()\r\n",
-    "write_path = r''\r\n",
-    "sn = \"PK50001A100000680\"\r\n",
-    "\r\n",
-    "st = '2021-07-06 00:00:00'\r\n",
-    "et = '2021-07-07 20:00:00'\r\n",
-    "tools.data_download(write_path=write_path, sn=sn, start_time=st, end_time=et, data_groups=['bms'])"
+   "metadata": {},
+   "outputs": [
+    {
+     "ename": "",
+     "evalue": "",
+     "output_type": "error",
+     "traceback": [
+      "\u001b[1;31mPython 3.8.12 64-bit ('algo_dev_env': conda) 需要安装 ipykernel。\n",
+      "Run the following command to install 'ipykernel' into the Python environment. \n",
+      "Command: 'conda install -n algo_dev_env ipykernel --update-deps --force-reinstall'"
+     ]
+    }
    ],
+   "source": [
+    "import plotly.io as pio\n",
+    "pio.renderers.default = 'iframe_connected'"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
    "outputs": [],
-   "metadata": {}
+   "source": [
+    "# 下载数据 \n",
+    "import sys\n",
+    "from LIB.BACKEND import Tools\n",
+    "\n",
+    "tools = Tools.Tools()\n",
+    "write_path = r''\n",
+    "sn = \"PK50001A100000680\"\n",
+    "\n",
+    "st = '2021-07-06 00:00:00'\n",
+    "et = '2021-07-07 20:00:00'\n",
+    "tools.data_download(write_path=write_path, sn=sn, start_time=st, end_time=et, data_groups=['bms'])"
+   ]
   },
   {
    "cell_type": "code",
    "execution_count": null,
+   "metadata": {},
+   "outputs": [],
    "source": [
-    "# 数据预处理\r\n",
-    "import sys\r\n",
-    "from LIB.BACKEND import DataPreProcess\r\n",
-    "\r\n",
-    "dataPrePro = DataPreProcess.DataPreProcess()\r\n",
-    "# 时间完全相同的数据仅保留一行\r\n",
-    "df_bms_pro, df_gps_pro = dataPrePro.time_filter(df_bms, df_gps)\r\n",
-    "\r\n",
-    "# bms数据按照电流和状态分段, 然后在状态分段内部,根据时间跳变继续分段(解决段内数据丢失)\r\n",
-    "df_bms_pro = dataPrePro.data_split_by_status(df_bms_pro)\r\n",
-    "df_bms_pro = dataPrePro.data_split_by_time(df_bms_pro)\r\n",
-    "\r\n",
-    "# bms数据将两次充电间的状态合并\r\n",
-    "df_bms_pro = dataPrePro.combine_drive_stand(df_bms_pro)\r\n",
-    "# bms 数据计算行车和充电开始前后的静置时间\r\n",
-    "df_bms_pro = dataPrePro.cal_stand_time(df_bms_pro)\r\n",
-    "# gps 数据可靠性判断, 并增加里程和速度至gps数据(根据未合并的数据段判断)\r\n",
-    "df_bms_pro, df_gps_pro, res_record= dataPrePro.gps_data_judge(df_bms_pro, df_gps_pro)\r\n",
-    "# gps 数据可靠性判断, 并增加里程和速度至gps数据(根据已合并的数据段判断)\r\n",
+    "# 数据预处理\n",
+    "import sys\n",
+    "from LIB.BACKEND import DataPreProcess\n",
+    "\n",
+    "dataPrePro = DataPreProcess.DataPreProcess()\n",
+    "# 时间完全相同的数据仅保留一行\n",
+    "df_bms_pro, df_gps_pro = dataPrePro.time_filter(df_bms, df_gps)\n",
+    "\n",
+    "# bms数据按照电流和状态分段, 然后在状态分段内部,根据时间跳变继续分段(解决段内数据丢失)\n",
+    "df_bms_pro = dataPrePro.data_split_by_status(df_bms_pro)\n",
+    "df_bms_pro = dataPrePro.data_split_by_time(df_bms_pro)\n",
+    "\n",
+    "# bms数据将两次充电间的状态合并\n",
+    "df_bms_pro = dataPrePro.combine_drive_stand(df_bms_pro)\n",
+    "# bms 数据计算行车和充电开始前后的静置时间\n",
+    "df_bms_pro = dataPrePro.cal_stand_time(df_bms_pro)\n",
+    "# gps 数据可靠性判断, 并增加里程和速度至gps数据(根据未合并的数据段判断)\n",
+    "df_bms_pro, df_gps_pro, res_record= dataPrePro.gps_data_judge(df_bms_pro, df_gps_pro)\n",
+    "# gps 数据可靠性判断, 并增加里程和速度至gps数据(根据已合并的数据段判断)\n",
     "df_bms_pro, df_gps_pro, res_record= dataPrePro.data_gps_judge_after_combine(df_bms_pro, df_gps_pro)"
-   ],
-   "outputs": [],
-   "metadata": {}
+   ]
   },
   {
    "cell_type": "code",
    "execution_count": null,
+   "metadata": {},
+   "outputs": [],
    "source": [
-    "# 单cycle指标统计\r\n",
-    "import sys\r\n",
-    "from LIB.BACKEND import IndexStaByOneCycle\r\n",
-    "\r\n",
-    "indexSta = IndexStaByOneCycle.IndexStaByOneCycle()\r\n",
-    "\r\n",
-    "data_number_list = sorted(list(set(df_bms[(df_bms['data_status'].isin(['drive']))]['data_split_by_status'])))\r\n",
-    "for data_number in data_number_list[:]:\r\n",
-    "    df_sel_bms = df_bms[df_bms['data_split_by_status'] == data_number]\r\n",
-    "    df_sel_bms = df_sel_bms.reset_index(drop=True)\r\n",
-    "    df_sel_gps = df_gps[(df_gps['时间戳']>df_sel_bms.loc[0,'时间戳']) & (df_gps['时间戳']<df_sel_bms.loc[len(df_sel_bms)-1,'时间戳'])]\r\n",
-    "    df_sel_gps = df_sel_gps.reset_index(drop=True)\r\n",
-    "\r\n",
-    "    print(indexSta.odo_sta(np.array(df_sel_gps['odo'])))\r\n",
-    "    print(indexSta.capacity_sta(40, np.array(df_sel_bms['SOC[%]']), np.array(df_sel_bms['SOH[%]'])))\r\n",
-    "    print(indexSta.energy_sta(40, np.array(df_sel_bms['SOC[%]']), np.array(df_sel_bms['SOH[%]']),np.array(df_sel_bms['总电压[V]'])))\r\n",
-    "    print(indexSta.acc_time_sta(np.array(df_sel_bms['时间戳'])))\r\n",
-    "    print(indexSta.mean_temp_sta(np.array(df_sel_bms['单体温度1'])))\r\n",
-    "    print(indexSta.temp_change_rate_sta(np.array(df_sel_bms['时间戳']), np.array(df_sel_bms['单体温度1'])))\r\n",
-    "    print(indexSta.dischrg_max_pwr_sta(np.array(df_sel_bms['总电压[V]']), np.array(df_sel_bms['总电流[A]'])))\r\n",
-    "    print(indexSta.chrg_max_pwr_sta(np.array(df_sel_bms['总电压[V]']), np.array(df_sel_bms['总电流[A]'])))\r\n",
-    "    print(indexSta.speed_sta(indexSta.odo_sta(np.array(df_sel_gps['odo'])), indexSta.acc_time_sta(np.array(df_sel_gps['时间戳'])), np.array(df_sel_gps['speed'])))\r\n",
+    "# 单cycle指标统计\n",
+    "import sys\n",
+    "from LIB.BACKEND import IndexStaByOneCycle\n",
+    "\n",
+    "indexSta = IndexStaByOneCycle.IndexStaByOneCycle()\n",
+    "\n",
+    "data_number_list = sorted(list(set(df_bms[(df_bms['data_status'].isin(['drive']))]['data_split_by_status'])))\n",
+    "for data_number in data_number_list[:]:\n",
+    "    df_sel_bms = df_bms[df_bms['data_split_by_status'] == data_number]\n",
+    "    df_sel_bms = df_sel_bms.reset_index(drop=True)\n",
+    "    df_sel_gps = df_gps[(df_gps['时间戳']>df_sel_bms.loc[0,'时间戳']) & (df_gps['时间戳']<df_sel_bms.loc[len(df_sel_bms)-1,'时间戳'])]\n",
+    "    df_sel_gps = df_sel_gps.reset_index(drop=True)\n",
+    "\n",
+    "    print(indexSta.odo_sta(np.array(df_sel_gps['odo'])))\n",
+    "    print(indexSta.capacity_sta(40, np.array(df_sel_bms['SOC[%]']), np.array(df_sel_bms['SOH[%]'])))\n",
+    "    print(indexSta.energy_sta(40, np.array(df_sel_bms['SOC[%]']), np.array(df_sel_bms['SOH[%]']),np.array(df_sel_bms['总电压[V]'])))\n",
+    "    print(indexSta.acc_time_sta(np.array(df_sel_bms['时间戳'])))\n",
+    "    print(indexSta.mean_temp_sta(np.array(df_sel_bms['单体温度1'])))\n",
+    "    print(indexSta.temp_change_rate_sta(np.array(df_sel_bms['时间戳']), np.array(df_sel_bms['单体温度1'])))\n",
+    "    print(indexSta.dischrg_max_pwr_sta(np.array(df_sel_bms['总电压[V]']), np.array(df_sel_bms['总电流[A]'])))\n",
+    "    print(indexSta.chrg_max_pwr_sta(np.array(df_sel_bms['总电压[V]']), np.array(df_sel_bms['总电流[A]'])))\n",
+    "    print(indexSta.speed_sta(indexSta.odo_sta(np.array(df_sel_gps['odo'])), indexSta.acc_time_sta(np.array(df_sel_gps['时间戳'])), np.array(df_sel_gps['speed'])))\n",
     "    break"
-   ],
-   "outputs": [],
-   "metadata": {}
+   ]
   },
   {
    "cell_type": "code",
    "execution_count": 2,
-   "source": [
-    "# 生成pydoc 说明文档\r\n",
-    "!python -m pydoc -w LIB\\BACKEND\\DataPreProcess.py"
-   ],
+   "metadata": {},
    "outputs": [
     {
-     "output_type": "stream",
      "name": "stdout",
+     "output_type": "stream",
      "text": [
       "problem in LIB\\BACKEND\\DataPreProcess.py - ModuleNotFoundError: No module named 'DBManager'\n"
      ]
     }
    ],
-   "metadata": {}
+   "source": [
+    "# 生成pydoc 说明文档\n",
+    "!python -m pydoc -w LIB\\BACKEND\\DataPreProcess.py"
+   ]
   },
   {
    "cell_type": "code",
    "execution_count": 1,
-   "source": [
-    "from LIB.BACKEND import DBManager, Log\r\n",
-    "log = Log.Mylog(log_name='signal_monitor', log_level = 'info')\r\n",
-    "log.set_file_hl(file_name='info.log', log_level='info')\r\n",
-    "log.set_file_hl(file_name='error.log', log_level='error')\r\n",
-    "logger = log.get_logger()\r\n"
-   ],
+   "metadata": {},
    "outputs": [],
-   "metadata": {}
+   "source": [
+    "from LIB.BACKEND import DBManager, Log\n",
+    "log = Log.Mylog(log_name='signal_monitor', log_level = 'info')\n",
+    "log.set_file_hl(file_name='info.log', log_level='info')\n",
+    "log.set_file_hl(file_name='error.log', log_level='error')\n",
+    "logger = log.get_logger()\n"
+   ]
   },
   {
    "cell_type": "code",
    "execution_count": 6,
+   "metadata": {},
+   "outputs": [],
    "source": [
     "logger.error(\"ttt5\")"
-   ],
-   "outputs": [],
-   "metadata": {}
+   ]
   },
   {
    "cell_type": "code",
    "execution_count": null,
-   "source": [],
+   "metadata": {},
    "outputs": [],
-   "metadata": {}
+   "source": []
   }
  ],
  "metadata": {
@@ -167,23 +186,23 @@
    "hash": "b3ba2566441a7c06988d0923437866b63cedc61552a5af99d1f4fb67d367b25f"
   },
   "kernelspec": {
-   "name": "python3",
-   "display_name": "Python 3.8.8 64-bit ('base': conda)"
+   "display_name": "Python 3.8.8 64-bit ('base': conda)",
+   "name": "python3"
   },
   "language_info": {
-   "name": "python",
-   "version": "3.8.8",
-   "mimetype": "text/x-python",
    "codemirror_mode": {
     "name": "ipython",
     "version": 3
    },
-   "pygments_lexer": "ipython3",
+   "file_extension": ".py",
+   "mimetype": "text/x-python",
+   "name": "python",
    "nbconvert_exporter": "python",
-   "file_extension": ".py"
+   "pygments_lexer": "ipython3",
+   "version": "3.8.12"
   },
   "orig_nbformat": 4
  },
  "nbformat": 4,
  "nbformat_minor": 2
-}
+}