Browse Source

增加平峰项目

Eric412V 2 years ago
parent
commit
76476e0d76

+ 191 - 0
LIB/MIDDLE/PingFeng/main.py

@@ -0,0 +1,191 @@
+
+__author__ = 'lmstack'
+#coding=utf-8
+import os
+import datetime
+import pandas as pd
+from LIB.BACKEND import DBManager, Log
+from sqlalchemy import create_engine
+from sqlalchemy.orm import sessionmaker
+import soc_version_20220812
+import time, datetime
+import traceback
+from LIB.MIDDLE.CellStateEstimation.Common import log
+from LIB.MIDDLE.CellStateEstimation.BatDiag.V1_0_0 import CBMSBatDiag
+
+from LIB.MIDDLE.CellStateEstimation.Common.V1_0_1 import DBDownload
+from urllib import parse
+import pymysql
+import pdb
+from apscheduler.schedulers.blocking import BlockingScheduler
+import datacompy
+import logging
+import multiprocessing
+#...................................电池包SOC计算......................................................................................................................
+
+def SOC_cal():
+
+    start=time.time()
+    now_time=datetime.datetime.now()
+    start_time=now_time-datetime.timedelta(seconds=300)
+    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'
+
+
+    db_res_engine = create_engine(
+        "mysql+pymysql://{}:{}@{}:{}/{}?charset=utf8".format(
+            user, parse.quote_plus(password), host, port, db
+        ))
+
+
+    for i in range(0, len(df_sn)):
+        factory = "骑享"
+        sn = df_sn.loc[i, 'sn']
+        try:
+            if df_sn.loc[i, 'imei'][5:9] == 'N640':
+                celltype=1 #6040三元电芯
+            elif df_sn.loc[i, 'imei'][5:9] == 'N440':
+                celltype=2 #4840三元电芯
+            elif df_sn.loc[i, 'imei'][5:9] == 'L660':
+                celltype=99 # 6060锂电芯
+            elif df_sn.loc[i, 'imei'][3:5] == 'LX' and df_sn.loc[i, 'imei'][5:9] == 'N750':    
+                celltype=3 #力信 50ah三元电芯
+            elif df_sn.loc[i, 'imei'][3:5] == 'CL' and df_sn.loc[i, 'imei'][5:9] == 'N750': 
+                celltype=4 #CATL 50ah三元电芯
+            elif df_sn.loc[i, 'imei'][3:9] == 'CLL128':    
+                celltype=100 # 重卡
+                factory = "金茂换电"
+            elif df_sn.loc[i, 'imei'][0:6] == 'SPFPFL':   
+                celltype=200#储能电站
+                factory = "平峰"
+            else:
+                logger.info("pid-{} celltype-{} SN: {} SKIP!".format(os.getpid(), "未知", sn))
+                continue
+
+            logger.info("pid-{} celltype-{} SN: {} START!".format(os.getpid(), celltype, sn))
+
+            #读取原始数据库数据........................................................................................................................................................
+            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']
+
+
+            #电池诊断................................................................................................................................................................
+            if not df_bms.empty:
+                SOC_result=soc_version_20220812.soc_test(sn,df_bms)
+                SOC_result.columns=['sn','soc','time']
+                SOC_result.reset_index(inplace=True,drop=True) 
+                print(SOC_result)
+                    #新增故障筛选并存入数据库.....................................................................
+                if not SOC_result.empty:  #新增写入数据库
+                    SOC_result.to_sql('pingfeng_soc_cal',con=db_res_engine, if_exists='append',index=False)
+
+            end=time.time()
+            print(end-start)  
+            
+        except Exception as e:
+            logger.warning(e)
+            logger.error(traceback.format_exc)
+            logger.error(u"{} :{},{} 任务运行错误\n".format(sn,start_time,end_time), exc_info=True)
+
+
+if __name__ == "__main__":
+    
+    # 时间设置
+    # now_time = datetime.datetime.now()
+    # pre_time = now_time + dateutil.relativedelta.relativedelta(days=-1)# 前一日
+    # end_time=datetime.datetime.strftime(now_time,"%Y-%m-%d 00:00:00")
+    # start_time=datetime.datetime.strftime(pre_time,"%Y-%m-%d 00:00:00")
+    
+    history_run_flag = False # 历史数据运行标志
+    
+    def get_sn():
+        global df_sn
+        # # 更新sn列表
+        host='rm-bp10j10qy42bzy0q7.mysql.rds.aliyuncs.com'
+        port=3306
+        db='qixiang_oss'
+        user='qixiang_oss'
+        password='Qixiang2021'
+        conn = pymysql.connect(host=host, port=port, user=user, password=password, database=db)
+        cursor = conn.cursor()
+        cursor.execute("select sn, imei, add_time from app_device where status in (1,2,3)")
+        res = cursor.fetchall()
+        df_sn = pd.DataFrame(res, columns=['sn', 'imei', 'add_time'])
+        df_sn = df_sn[df_sn['sn'].str.contains('SPFPFL')]
+        #df_sn = df_sn[df_sn['sn'].str.contains('PK500A20100000941')]
+        
+        df_sn = df_sn.reset_index(drop=True)
+        #conn.close();
+
+    
+    # # 数据库配置
+    # host = 'rm-bp10j10qy42bzy0q77o.mysql.rds.aliyuncs.com'
+    # port = 3306
+    # user = 'qx_cas'
+    # password = parse.quote_plus('Qx@123456')
+    # database = 'qx_cas'
+
+    # db_engine = create_engine(
+    #     "mysql+pymysql://{}:{}@{}:{}/{}?charset=utf8".format(
+    #         user, password, host, port, database
+    #     ))
+    # DbSession = sessionmaker(bind=db_engine)
+    
+    # # 运行历史数据配置
+    
+    # df_first_data_time = pd.read_sql("select * from bat_first_data_time", db_engine)
+
+    
+    # 日志配置
+    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='batDiag', 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()
+
+    logger.info("pid is {}".format(os.getpid()))
+    
+    # # 算法参数
+    # host='rm-bp10j10qy42bzy0q77o.mysql.rds.aliyuncs.com'
+    # port=3306
+    # db='safety_platform'
+    # user='qx_read'
+    # password=parse.quote_plus('Qx@123456')
+    # tablename='all_fault_info'
+    # db_res_engine = create_engine(
+    #     "mysql+pymysql://{}:{}@{}:{}/{}?charset=utf8".format(
+    #         user, password, host, port, db
+    #     ))
+
+        
+    #............................模块运行前,先读取数据库中所有结束时间为0的数据,需要从数据库中读取................
+    # print("select start_time, end_time, product_id, code, level, info, advice, factory from {}".format(tablename))
+
+    # result=pd.read_sql("select start_time, end_time, product_id, code, level, info, advice from all_fault_info where factory = '{}'".format('骑享'), db_res_engine)
+    # result = result[['start_time', 'end_time', 'product_id', 'code', 'level', 'info', 'advice']]
+    # 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'])
+    get_sn()
+    SOC_cal()
+    #定时任务.......................................................................................................................................................................
+    scheduler = BlockingScheduler()
+    scheduler.add_job(get_sn, 'interval', days=1, id='get_sn')
+    scheduler.add_job(SOC_cal, 'interval', seconds=300, id='SOC_cal')
+    
+    try:  
+        scheduler.start()
+    except Exception as e:
+        scheduler.shutdown()
+        logger.error(str(e))
+    

+ 216 - 0
LIB/MIDDLE/PingFeng/soc_version_20220812.py

@@ -0,0 +1,216 @@
+import numpy as np
+import datetime
+from scipy import interpolate
+import logging
+import pandas as pd
+
+# 电压范围3.0 - 3.5
+
+SocCurve = [0.00, 0.05, 0.10, 0.15, 0.20, 0.25, 0.30, 0.35, 0.40, 0.45, 0.50, 0.55, 0.60, 0.65, 0.70, 0.75, 0.80, 0.85,
+            0.90, 0.95, 1.00]
+DisOcvCurve = [2.8977, 3.1587, 3.2040, 3.2269, 3.2521, 3.2691, 3.2846, 3.2865, 3.2871, 3.2880, 3.2886, 3.2971, 3.3190,
+               3.3277, 3.3277, 3.3280, 3.3286, 3.3289, 3.3296, 3.3311, 3.3795]  # 磷酸铁锂
+
+SocLook = interpolate.interp1d(DisOcvCurve, SocCurve, kind='slinear')
+ChgNearFullVol = 3.5  # v
+DisNearFullVol = 3.0  # v
+
+logger = logging.getLogger(__file__)
+
+
+def str_to_date(date_string, format='%Y-%m-%d %H:%M:%S', alternative=None):
+    try:
+        return datetime.datetime.strptime(date_string, format)
+    except Exception as e:
+        pass
+    return alternative
+
+
+# 安时积分法
+def AhCalculate(soc, cur, deltaTime, capacity):
+    try:
+        soc = soc + cur * deltaTime / capacity / 3600
+    except Exception as exc:
+        logger.warning(exc)
+    return soc
+
+
+# 判断充放电状态
+def ChgStatus(cur, chg_time, dis_time, shelve_time):
+    flag = False
+    if cur > 1:
+        chg_time += 1
+    if cur < -1:
+        dis_time += 1
+        flag = True
+    if cur == 0:
+        shelve_time += 1
+        chg_time = 0
+        dis_time = 0
+    return chg_time, dis_time, shelve_time, flag
+
+
+# 电芯容量校正
+def CapacityCalculate(soc, soc_zero, cumulative_capacity, t_capacity):
+    s = soc - soc_zero
+    c = cumulative_capacity - t_capacity
+    try:
+        capacity = c / s
+    except Exception as exc:
+        logger.warning(exc)
+        capacity = 120
+    return capacity
+
+
+# 累积容量计算
+def CumulativeCapacity(capacity, cur, deltaTime):
+    capacity = capacity + cur * deltaTime / 3600
+    return capacity
+
+
+# 电池包容量计算
+def PackCapacityCalculate(soc_arr, capacity):
+    pack_capacity = np.min(soc_arr * capacity) + np.min(capacity - soc_arr * capacity)
+    return pack_capacity
+
+
+# 满电校正
+def ChgFullFunc(soc, vol):
+    for index in range(120):
+        if vol[index] > ChgNearFullVol:
+            soc[index] = 1
+    return soc
+
+
+# 满放校正
+def DisFullFunc(soc, vol):
+    for index in range(120):
+        if vol[index] < DisNearFullVol:
+            soc[index] = 0
+    return soc
+
+
+# 电池包soc计算
+def PackSocCalculate(soc_arr, pack_capacity, capacity):
+    try:
+        pack_soc = np.min(soc_arr * capacity) / pack_capacity
+        if pack_soc > 1:
+            pack_soc = 1
+        if pack_soc < 0:
+            pack_soc = 0
+        return pack_soc
+    except Exception as exc:
+        logger.warning(exc)
+
+
+SOC_DATA = []
+
+
+# 执行函数,最后返回的是dataframe形式,有对应的上传时间和soc,应该要关联设备id,这块没有加
+def soc_test(sn, data):
+    try:
+        global SOC_DATA
+        capacity = 120  # ah
+        chg_time = 0
+        dis_time = 0
+        shelve_time = 0
+        c_capacity = 0
+        soc_zero = []
+        if SOC_DATA:
+            for ram in SOC_DATA:
+                if ram['sn'] == sn:
+                    capacity = ram['capacity']
+                    chg_time = ram['chg_time']
+                    dis_time = ram['dis_time']
+                    shelve_time = ram['shelve_time']
+                    c_capacity = ram['c_capacity']
+                    soc_zero = ram['soc_zero']
+
+        vol_array = data[
+            ['单体电压1', '单体电压2', '单体电压3', '单体电压4', '单体电压5', '单体电压6', '单体电压7', '单体电压8', '单体电压9', '单体电压10', '单体电压11', '单体电压12',
+             '单体电压13', '单体电压14', '单体电压15', '单体电压16', '单体电压17', '单体电压18', '单体电压19', '单体电压20', '单体电压21', '单体电压22', '单体电压23',
+             '单体电压24', '单体电压25', '单体电压26', '单体电压27', '单体电压28', '单体电压29', '单体电压30', '单体电压31', '单体电压32', '单体电压33', '单体电压34',
+             '单体电压35', '单体电压36', '单体电压37', '单体电压38', '单体电压39', '单体电压40', '单体电压41', '单体电压42', '单体电压43', '单体电压44', '单体电压45',
+             '单体电压46', '单体电压47', '单体电压48', '单体电压49', '单体电压50', '单体电压51', '单体电压52', '单体电压53', '单体电压54', '单体电压55', '单体电压56',
+             '单体电压57', '单体电压58', '单体电压59', '单体电压60', '单体电压61', '单体电压62', '单体电压63', '单体电压64', '单体电压65', '单体电压66', '单体电压67',
+             '单体电压68', '单体电压69', '单体电压70', '单体电压71', '单体电压72', '单体电压73', '单体电压74', '单体电压75', '单体电压76', '单体电压77', '单体电压78',
+             '单体电压79', '单体电压80', '单体电压81', '单体电压82', '单体电压83', '单体电压84', '单体电压85', '单体电压86', '单体电压87', '单体电压88', '单体电压89',
+             '单体电压90', '单体电压91', '单体电压92', '单体电压93', '单体电压94', '单体电压95', '单体电压96', '单体电压97', '单体电压98', '单体电压99', '单体电压100',
+             '单体电压101', '单体电压102', '单体电压103', '单体电压104', '单体电压105', '单体电压106', '单体电压107', '单体电压108', '单体电压109', '单体电压110',
+             '单体电压111', '单体电压112', '单体电压113', '单体电压114', '单体电压115', '单体电压116', '单体电压117', '单体电压118', '单体电压119',
+             '单体电压120']].values
+        vol_array = vol_array.astype(float)
+        cur_array = data['总电流[A]'].values
+        upload_time = data['时间戳'].values
+        pack_soc_arr = np.zeros(len(cur_array))
+        vol_array_zero = vol_array[0] / 1000
+        vol_array_zero[vol_array_zero > 3.3795] = 3.37
+        if ~len(soc_zero):
+            soc_zero = SocLook(vol_array_zero)
+        pack_capacity = PackCapacityCalculate(soc_zero, capacity)
+        pack_soc_arr[0] = PackSocCalculate(soc_zero, pack_capacity, capacity)
+
+        for index in range(len(data) - 1):
+            if abs(cur_array[index]) >= 100:
+                if index > 1:
+                    vol_array[index] = vol_array[index - 1]
+                    cur_array[index] = cur_array[index - 1]
+            if index == 0:
+                upload_time[index + 1] = str_to_date(upload_time[index + 1])
+                upload_time[index] = str_to_date(upload_time[index])
+            else:
+                upload_time[index + 1] = str_to_date(upload_time[index + 1])
+
+            deltaTime = upload_time[index + 1] - upload_time[index]
+            # deltaTime = str_to_date(upload_time[index + 1]) - str_to_date(upload_time[index])
+            deltaTime = float(deltaTime.seconds)
+
+            soc = AhCalculate(soc_zero, cur_array[index], deltaTime, pack_capacity)
+
+            chg_time, dis_time, shelve_time, flag = ChgStatus(cur_array[index], chg_time, dis_time, shelve_time)
+
+            if chg_time > 600:
+                soc = ChgFullFunc(soc, vol_array[index])
+
+            if dis_time > 600:
+                soc = DisFullFunc(soc, vol_array[index])
+
+            if shelve_time > 1800:
+                if vol_array[index][0] > 3.328 or vol_array[index][0] < 3.285:
+                    soc_zero = SocLook(vol_array[index])
+
+            if flag:
+                if np.min(vol_array[index]) >= 3.0:
+                    c_capacity = CumulativeCapacity(c_capacity, cur_array[index], deltaTime)
+
+            if not flag and c_capacity != 0:
+                capacity = c_capacity
+
+            pack_soc = PackSocCalculate(soc, pack_capacity, capacity)
+            pack_soc_arr[index + 1] = pack_soc
+        ram_result = {'sn': sn, 'capacity': capacity, 'chg_time': chg_time, 'dis_time': dis_time, 'shelve_time': shelve_time,
+                  'soc_zero': soc_zero, 'c_capacity': c_capacity}
+        sn_list = []
+        if SOC_DATA:
+            for ram in SOC_DATA:
+                sn_list.append(ram['sn'])
+                if ram['sn'] == sn:
+                    ram['capacity'] = capacity
+                    ram['chg_time'] = chg_time
+                    ram['dis_time'] = dis_time
+                    ram['shelve_time'] = shelve_time
+                    ram['soc_zero'] = soc_zero
+                    ram['c_capacity'] = c_capacity
+            if sn not in sn_list:
+                SOC_DATA.append(ram_result)
+        else:
+            SOC_DATA.append(ram_result)
+        pack_soc_arr = pack_soc_arr * 100
+        result = {'SN': sn, 'SOC': pack_soc_arr[-1], 'UploadTime': upload_time[-1]}
+        result = pd.DataFrame(result, index=[0])
+        # pack_soc_frame = pd.DataFrame(pack_soc_arr, columns=['SOC'])
+        # result = pack_soc_frame.assign(UploadTime=upload_time)
+        return result
+    except Exception as exc:
+        logger.warning(exc)
+

+ 25 - 25
LIB/MIDDLE/SaftyCenter/Low_Soc_Alarm/low_soc_alarm.py

@@ -7,29 +7,29 @@ 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]
+        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