Browse Source

odo计算

lmstack 3 years ago
parent
commit
ab41fe34dc

+ 232 - 0
LIB/FRONTEND/SaftyCenter/CellValueDiag/deploy.py

@@ -0,0 +1,232 @@
+
+__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 time, datetime
+import dateutil.relativedelta
+import traceback
+from LIB.MIDDLE.CellStateEstimation.Common import log
+from pandas.core.frame import DataFrame
+from LIB.MIDDLE.SaftyCenter.Common import QX_BatteryParam
+from LIB.MIDDLE.SaftyCenter.CellValueDiag.V1_0_0.SC_SamplingSafty import SamplingSafty
+
+from LIB.MIDDLE.CellStateEstimation.Common import DBDownload
+from urllib import parse
+import pymysql
+import pdb
+from apscheduler.schedulers.blocking import BlockingScheduler
+import datacompy
+
+def fun():
+    global df_sn
+    global db_res_engine
+    global logger
+    global df_Diag_Ram
+    # 读取结果数据库
+    host2='rm-bp10j10qy42bzy0q77o.mysql.rds.aliyuncs.com'
+    port2=3306
+    db2='safety_platform'
+    user2='qx_read'
+    password2='Qx@123456'
+    start=time.time()
+    end_time=datetime.datetime.now()
+    start_time=end_time-datetime.timedelta(seconds=120)
+    start_time=start_time.strftime('%Y-%m-%d %H:%M:%S')
+    end_time=end_time.strftime('%Y-%m-%d %H:%M:%S')
+    logger.info("cycle start !!!!!!!!!!!!!!!!!!!!")
+
+    for i in range(0, len(df_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三元电芯
+            else:
+                logger.info("pid-{} celltype-{} SN: {} SKIP!".format(os.getpid(), "未知", sn))
+                continue
+            sn = df_sn.loc[i, 'sn']
+            
+            logger.info("pid-{} celltype-{} SN: {} START!".format(os.getpid(), celltype, sn))
+                
+                
+            param=QX_BatteryParam.BatteryInfo(celltype)     
+            # sn='PK50201A000002039'
+            # celltype=2
+            # start_time='2021-05-02 09:12:26'
+            # end_time='2021-06-03 19:12:26'
+            # # df_bms= pd.read_csv(r'D:\Platform\platform_python\data_analyze_platform\USER\01qixiang\98Download\\'+'BMS_'+sn+'.csv',encoding='GB18030')
+
+            #读取原始数据库数据........................................................................................................................................................
+            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']
+            # df_bms.to_csv(r'D:\Platform\platform_python\data_analyze_platform\USER\01qixiang\99Result\\''BMS_'+sn+'.csv',encoding='GB18030')
+
+            #读取结果数据库数据........................................................................................................................................................
+            host='rm-bp10j10qy42bzy0q77o.mysql.rds.aliyuncs.com'
+            port=3306
+            db='qx_cas'
+            user='qx_read'
+            password='Qx@123456'
+            mode=1
+            
+            # 读取结果数据库
+            host2='rm-bp10j10qy42bzy0q77o.mysql.rds.aliyuncs.com'
+            port2=3306
+            db2='safety_platform'
+            user2='qx_read'
+            password2='Qx@123456'
+            
+            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)
+
+            #电池诊断................................................................................................................................................................
+            #BatDiag=CBMSBatDiag.BatDiag(sn,celltype,df_bms, df_soh, df_uniform)
+            #df_res=BatDiag.diag()
+            #df_Diag_Ram_old=df_Diag_Ram
+            df_Diag_Ram_Update=DataFrame(columns=['start_time', 'end_time', 'product_id', 'code', 'level', 'info','advice'])
+            CellFltInfo=DataFrame(columns=['start_time', 'end_time', 'product_id', 'code', 'level', 'info','advice'])
+            if not df_bms.empty:
+                CellFltInfo=df_Diag_Ram[df_Diag_Ram['product_id']==sn]
+                df_Diag_Ram_Update=SamplingSafty.main(sn,param,df_bms,CellFltInfo)       
+            if not df_Diag_Ram_Update.empty:
+                sn_index=df_Diag_Ram[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_Ram_Update)
+                df_Diag_Ram.reset_index(inplace=True,drop=True)
+                
+
+            Diag_Ram_Dif=datacompy.Compare(df_Diag_Ram_Update,CellFltInfo,join_columns=['product_id','end_time', 'code'])
+            Diag_Ram_Dif=Diag_Ram_Dif.df1_unq_rows  
+  
+  
+            if len(Diag_Ram_Dif)>0:
+                Diag_Ram_Dif_New=Diag_Ram_Dif[Diag_Ram_Dif['end_time']=='0000-00-00 00:00:00']
+                Diag_Ram_Dif_Finish=df_Diag_Ram[df_Diag_Ram['end_time']!='0000-00-00 00:00:00']
+                if len(Diag_Ram_Dif_New)>0: # 新增
+                    Diag_Ram_Dif_New.columns = ['start_time', 'end_time', 'product_id', 'code', 'level', 'info', 'advice']
+                    Diag_Ram_Dif_New['factory'] = '骑享'
+                    Diag_Ram_Dif_New.to_sql("all_fault_info",con=db_res_engine, if_exists="append",index=False)
+                if len(Diag_Ram_Dif_Finish)>0: # 修改
+                    Diag_Ram_Dif_Finish=Diag_Ram_Dif_Finish.reset_index(drop=True)
+                    try:
+                        conn = pymysql.connect(host=host2, port=port2, user=user2, password=password2, database=db2)
+                        cursor = conn.cursor()
+                        for i in range(0,len(Diag_Ram_Dif_Finish)):
+                            cursor.execute('''
+                                        update all_fault_info set end_time={} where product_id='{}' and code={}
+                                        '''.format(Diag_Ram_Dif_Finish.loc[i,'end_time'], Diag_Ram_Dif_Finish.loc[i,'product_id'], Diag_Ram_Dif_Finish.loc[i,'code']))
+                            conn.commit()
+                        conn.close();
+                    except:
+                        logger.error(traceback.format_exc)
+                        logger.error(u"{} :{},{} 任务运行错误\n".format(sn,start_time,end_time), exc_info=True)
+                        conn.close();
+            end=time.time()
+            logger.info("pid-{} SN: {} DONE!".format(os.getpid(), sn))
+        except:
+            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 # 历史数据运行标志
+    
+
+    # 更新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")
+    res = cursor.fetchall()
+    df_sn = pd.DataFrame(res, columns=['sn', 'imei', 'add_time'])
+    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='saftyCenter_cellvaluediag', 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']
+
+
+    #定时任务.......................................................................................................................................................................
+    scheduler = BlockingScheduler()
+
+    scheduler.add_job(fun, 'interval', seconds=120, id='diag_job')
+    try:  
+        scheduler.start()
+    except Exception as e:
+        scheduler.shutdown()
+        logger.error(str(e))
+    

+ 194 - 0
LIB/FRONTEND/SaftyCenter/CellValueDiag/main.py

@@ -0,0 +1,194 @@
+import CBMSBatDiag
+import QX_BatteryParam
+from SC_SamplingSafty import SamplingSafty
+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 import DBDownload
+from LIB.MIDDLE.CellStateEstimation.Common import log
+from pandas.core.frame import DataFrame
+import datacompy
+
+
+
+#...................................电池包电芯安全诊断函数......................................................................................................................
+def diag_cal():
+    global SNnums
+    global df_Diag_Ram
+
+    start=time.time()
+    end_time=datetime.datetime.now()
+    start_time=end_time-datetime.timedelta(seconds=120)
+    start_time=start_time.strftime('%Y-%m-%d %H:%M:%S')
+    end_time=end_time.strftime('%Y-%m-%d %H:%M:%S')
+
+    for sn in SNnums:
+        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)     
+        # sn='PK50201A000002039'
+        # celltype=2
+        # start_time='2021-05-02 09:12:26'
+        # end_time='2021-06-03 19:12:26'
+        # # df_bms= pd.read_csv(r'D:\Platform\platform_python\data_analyze_platform\USER\01qixiang\98Download\\'+'BMS_'+sn+'.csv',encoding='GB18030')
+
+        #读取原始数据库数据........................................................................................................................................................
+        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']
+        # df_bms.to_csv(r'D:\Platform\platform_python\data_analyze_platform\USER\01qixiang\99Result\\''BMS_'+sn+'.csv',encoding='GB18030')
+
+        #读取结果数据库数据........................................................................................................................................................
+        host='rm-bp10j10qy42bzy0q77o.mysql.rds.aliyuncs.com'
+        port=3306
+        db='qx_cas'
+        user='qx_read'
+        password='Qx@123456'
+        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)
+
+        #电池诊断................................................................................................................................................................
+        #BatDiag=CBMSBatDiag.BatDiag(sn,celltype,df_bms, df_soh, df_uniform)
+        #df_res=BatDiag.diag()
+        #df_Diag_Ram_old=df_Diag_Ram
+        df_Diag_Ram_Update=DataFrame(columns=['start_time', 'end_time', 'product_id', 'code', 'level', 'info','advice'])
+        CellFltInfo=DataFrame(columns=['start_time', 'end_time', 'product_id', 'code', 'level', 'info','advice'])
+        if not df_bms.empty:
+            CellFltInfo=df_Diag_Ram[df_Diag_Ram['product_id']==sn]
+            df_Diag_Ram_Update=SamplingSafty.main(sn,param,df_bms,CellFltInfo)       
+        if not df_Diag_Ram_Update.empty:
+            sn_index=df_Diag_Ram[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_Ram_Update)
+            df_Diag_Ram.reset_index(inplace=True,drop=True)
+
+        Diag_Ram_Dif=datacompy.Compare(df_Diag_Ram_Update,CellFltInfo,join_columns=['product_id','end_time','code'])
+        Diag_Ram_Dif=Diag_Ram_Dif.df1_unq_rows    
+        if len(Diag_Ram_Dif)>0:
+            Diag_Ram_Dif_New=Diag_Ram_Dif[Diag_Ram_Dif['end_time']==0]
+            Diag_Ram_Dif_Finish=df_Diag_Ram[df_Diag_Ram['end_time']!=0]
+            if len(Diag_Ram_Dif_New)>0:
+                result=pd.read_csv(r'D:\Platform\platform_python\data_analyze_platform\USER\sxq\SaftyCenter_CODE_V1_1\result.csv',encoding='gbk')
+                result=result.append(Diag_Ram_Dif_New)
+                result.to_csv(r'D:\Platform\platform_python\data_analyze_platform\USER\sxq\SaftyCenter_CODE_V1_1\result.csv',index=False,encoding='GB18030')
+            if len(Diag_Ram_Dif_Finish)>0:
+                result=pd.read_csv(r'D:\Platform\platform_python\data_analyze_platform\USER\sxq\SaftyCenter_CODE_V1_1\result.csv',encoding='gbk')
+                Diag_Ram_Dif_Finish=Diag_Ram_Dif_Finish.reset_index(drop=True)
+                for i in range(0,len(Diag_Ram_Dif_Finish)):
+                    result.loc[result[result[result['product_id']==Diag_Ram_Dif_Finish.loc[i,'product_id']]['code']==Diag_Ram_Dif_Finish.loc[i,'code']].index,'end_time']=Diag_Ram_Dif_Finish.loc[i,'end_time']
+                result.to_csv(r'D:\Platform\platform_python\data_analyze_platform\USER\sxq\SaftyCenter_CODE_V1_1\result.csv',index=False,encoding='GB18030')
+        end=time.time()
+        print(end-start)
+        # print(df_soh)
+            
+#...................................电池包电芯安全诊断函数......................................................................................................................
+def shortdiag_cal():
+    global SNnums
+    global df_Diag_Ram
+    start=time.time()
+    end_time=datetime.datetime.now()
+    start_time=end_time-datetime.timedelta(days=30)
+    start_time=start_time.strftime('%Y-%m-%d %H:%M:%S')
+    end_time=end_time.strftime('%Y-%m-%d %H:%M:%S')
+
+    for sn in SNnums:
+        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()
+
+        #读取结果数据库数据........................................................................................................................................................
+        host='rm-bp10j10qy42bzy0q77o.mysql.rds.aliyuncs.com'
+        port=3306
+        db='qx_cas'
+        user='qx_read'
+        password='Qx@123456'
+        mode=2
+        tablename1='cellstateestimation_intershort'
+        DBRead=DBDownload.DBDownload(host, port, db, user, password, mode)  #mode==1取数据库最后一行数据
+        with DBRead as DBRead:
+            df_short=DBRead.getdata('time_sp','sn','short_current', tablename=tablename1, sn=sn, timename='time_sp', st=start_time, sp=end_time)  
+        
+        #电池诊断................................................................................................................................................................
+        ShortDiag=CBMSBatDiag.ShortDiag(sn,celltype, df_short)
+        df_res=ShortDiag.shortdiag()
+        # df_res.to_csv(r'D:\Platform\platform_python\data_analyze_platform\USER\01qixiang\99Result\\'+'CBMS_diag_'+sn+'.csv',encoding='GB18030')
+        
+        print(df_res)
+
+        end=time.time()
+        print(end-start)
+        # print(df_soh)
+        
+
+#...............................................主函数.......................................................................................................................
+if __name__ == "__main__":
+
+    excelpath=r'D:\Platform\platform_python\data_analyze_platform\USER\sxq\SaftyCenter_CODE_V1_1\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=['MGMLXN750N2189014']
+    
+    mylog=log.Mylog('log_diag.txt','error')
+    mylog.logcfg()
+    #............................模块运行前,先读取数据库中所有结束时间为0的数据,需要从数据库中读取................
+    result=pd.read_csv(r'D:\Platform\platform_python\data_analyze_platform\USER\sxq\SaftyCenter_CODE_V1_1\result.csv',encoding='gbk')
+    
+    df_Diag_Ram=result[result['end_time']==0]
+    print('----------------输入--------')
+    print(df_Diag_Ram)
+    #定时任务.......................................................................................................................................................................
+    scheduler = BlockingScheduler()
+    scheduler.add_job(diag_cal, 'interval', seconds=120, id='diag_job')
+    scheduler.add_job(shortdiag_cal, 'interval', days=7, id='shortdiag_job')
+
+    try:  
+        scheduler.start()
+    except Exception as e:
+        scheduler.shutdown()
+        print(repr(e))
+        mylog.logopt(e)

+ 3 - 0
LIB/FRONTEND/SaftyCenter/CellValueDiag/run.bat

@@ -0,0 +1,3 @@
+cd /d D:\deploy\python_platform\data_analyze_platform\LIB\FRONTEND\SaftyCenter\CellValueDiag
+title cal_saftyCenter_cellvalueDiag
+D:\env\py_pro\python.exe D:\deploy\python_platform\data_analyze_platform\LIB\FRONTEND\SaftyCenter\CellValueDiag\deploy.py

+ 52 - 0
LIB/FRONTEND/odo/DailyMileageEstimation/create_table.py

@@ -0,0 +1,52 @@
+'''
+定义表的结构,并在数据库中创建对应的数据表
+'''
+__author__ = 'lmstack'
+
+from sqlalchemy.ext.declarative import declarative_base
+from sqlalchemy import Column, String, create_engine, Integer, DateTime, BigInteger, FLOAT, TIMESTAMP, func, Text
+from urllib import parse
+Base = declarative_base()
+
+
+class ConsistencyDeltaSoc(Base):
+    __tablename__ = "odo_dailyMileageEstimation"
+    __table_args__ = ({'comment': '每日续驶里程'})  # 添加索引和表注释
+
+    id = Column(Integer, primary_key=True, autoincrement=True, comment="主键")
+    add_time = Column(TIMESTAMP(True), server_default=func.now(), comment='记录创建时间') # 创建时间
+    update_time = Column(TIMESTAMP(True), nullable=False, server_default=func.now(), onupdate=func.now(), comment='记录更新时间') # 更新时间
+    time = Column(TIMESTAMP(True), comment="时间")
+    sn = Column(String(64), comment="sn")
+    current = Column(FLOAT, comment="总电流")
+    voltage = Column(FLOAT, comment="总电压")
+    soc = Column(FLOAT, comment="soc")
+    
+    charging_status = Column(Integer, comment="数据状态")
+    latitude = Column(FLOAT, comment="纬度")
+    longitude = Column(FLOAT, comment="经度")
+    energy_consump = Column(FLOAT, comment="能耗")
+    voltage = Column(FLOAT, comment="总电压")
+    mileage = Column(FLOAT, comment='每日续驶里程 /km')
+
+
+    # def __init__(self, sn, current, time_stamp, pack_state, line_state):
+    #     self.sn = sn
+    #     self.current = current
+    #     self.time_stamp = time_stamp
+    #     self.pack_state = pack_state
+    #     self.line_state = line_state
+
+# 执行该文件,创建表格到对应的数据库中
+if __name__ == "__main__":
+    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
+        ))
+    Base.metadata.create_all(db_engine)

+ 116 - 0
LIB/FRONTEND/odo/DailyMileageEstimation/deploy.py

@@ -0,0 +1,116 @@
+
+__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 time, datetime
+import dateutil.relativedelta
+import traceback
+from LIB.MIDDLE.odo.DailyMileageEstimation.V1_0_2 import cal_mileage
+from urllib import parse
+import pymysql
+import pdb
+dbManager = DBManager.DBManager()
+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 # 历史数据运行标志
+    
+
+    # 更新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")
+    res = cursor.fetchall()
+    df_sn = pd.DataFrame(res, columns=['sn', 'imei', 'add_time'])
+    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='odo_dailyMileageEstimation', 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='qx_cas'
+    user='qx_read'
+    password='Qx@123456'
+    tablename='cellStateEstimation_soh'
+
+    for i in range(0, len(df_sn)):
+        try:
+            sn = df_sn.loc[i, 'sn']
+            logger.info("pid-{}  SN: {} START!".format(os.getpid(), sn))
+            dbManager = DBManager.DBManager()
+            df_data = dbManager.get_data(sn=sn, start_time=start_time, end_time=end_time, data_groups=['bms','gps'])
+            data_bms = df_data['bms']
+            data_gps = df_data['gps']
+
+            #...............每日累积里程............................................................................
+            if len(data_bms['时间戳'])>0 and len(data_gps['时间戳'])>0:
+                df_res = cal_mileage.calcul_mileage(sn,data_bms,data_gps)
+                # df_res.to_csv('Mileage_'+sn+'.csv')
+                
+                
+            # # 处理运行历史数据
+            # if (history_run_flag):
+            #     this_sn = df_first_data_time[df_first_data_time['sn']==sn]
+            #     if (len(this_sn) == 0):
+            #         start_time = pd.to_datetime(str(df_sn.loc[df_sn[df_sn['sn']==sn].index, 'add_time'].values[0])).strftime("%Y-%m-%d 00:00:00")
+            #     else:
+            #         first_data_time = df_first_data_time.loc[df_first_data_time[df_first_data_time['sn']==sn].index, 'first_data_time'].values[0]
+            #         if pd.isnull(first_data_time):
+            #             start_time = "2018-01-01 00:00:00"
+            #         else:
+            #             start_time = pd.to_datetime(str(df_first_data_time.loc[df_first_data_time[df_first_data_time['sn']==sn].index, 'first_data_time'].values[0])).strftime("%Y-%m-%d 00:00:00")
+
+            if not df_res.empty:
+                df_res.columns = ['time', 'sn', 'current', 'soc', 'charging_status', 'latitude', 'longitude', 'energy_consump', 'voltage', 'mileage']
+                df_res.to_sql("odo_dailyMileageEstimation",con=db_engine, if_exists="append",index=False)
+            logger.info("pid-{} SN: {} DONE!".format(os.getpid(), sn))
+        except:
+            logger.error(traceback.format_exc)
+            logger.error(u"{} :{},{} 任务运行错误\n".format(sn,start_time,end_time), exc_info=True)

+ 120 - 0
LIB/FRONTEND/odo/DailyMileageEstimation/deployhistory.py

@@ -0,0 +1,120 @@
+
+__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 time, datetime
+import dateutil.relativedelta
+import traceback
+from LIB.MIDDLE.odo.DailyMileageEstimation.V1_0_2 import cal_mileage
+from urllib import parse
+import pymysql
+import pdb
+dbManager = DBManager.DBManager()
+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")
+    start_time = '2021-10-01 00:00:00'
+    end_time = '2021-11-01 00:00:00'
+    history_run_flag = False # 历史数据运行标志
+    
+
+    # 更新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")
+    res = cursor.fetchall()
+    df_sn = pd.DataFrame(res, columns=['sn', 'imei', 'add_time'])
+    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='odo_dailyMileageEstimation_history', 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='qx_cas'
+    user='qx_read'
+    password='Qx@123456'
+    tablename='cellStateEstimation_soh'
+
+    for i in range(0, len(df_sn)):
+        try:
+            sn = df_sn.loc[i, 'sn']
+            logger.info("pid-{}  SN: {} START!".format(os.getpid(), sn))
+            dbManager = DBManager.DBManager()
+
+                
+                
+            # # 处理运行历史数据
+            if (history_run_flag):
+                this_sn = df_first_data_time[df_first_data_time['sn']==sn]
+                if (len(this_sn) == 0):
+                    start_time = pd.to_datetime(str(df_sn.loc[df_sn[df_sn['sn']==sn].index, 'add_time'].values[0])).strftime("%Y-%m-%d 00:00:00")
+                else:
+                    first_data_time = df_first_data_time.loc[df_first_data_time[df_first_data_time['sn']==sn].index, 'first_data_time'].values[0]
+                    if pd.isnull(first_data_time):
+                        start_time = "2018-01-01 00:00:00"
+                    else:
+                        start_time = pd.to_datetime(str(df_first_data_time.loc[df_first_data_time[df_first_data_time['sn']==sn].index, 'first_data_time'].values[0])).strftime("%Y-%m-%d 00:00:00")
+            
+            df_data = dbManager.get_data(sn=sn, start_time=start_time, end_time=end_time, data_groups=['bms','gps'])
+            data_bms = df_data['bms']
+            data_gps = df_data['gps']
+
+            #...............每日累积里程............................................................................
+            df_res = pd.DataFrame()
+            if len(data_bms['时间戳'])>0 and len(data_gps['时间戳'])>0:
+                df_res = cal_mileage.calcul_mileage(sn,data_bms,data_gps)
+                # df_res.to_csv('Mileage_'+sn+'.csv')
+                
+            if not df_res.empty:
+                df_res.columns = ['time', 'sn', 'current', 'soc', 'charging_status', 'latitude', 'longitude', 'energy_consump', 'voltage', 'mileage']
+                df_res.to_sql("odo_dailyMileageEstimation",con=db_engine, if_exists="append",index=False)
+            logger.info("pid-{} SN: {} DONE!".format(os.getpid(), sn))
+        except:
+            logger.error(traceback.format_exc)
+            logger.error(u"{} :{},{} 任务运行错误\n".format(sn,start_time,end_time), exc_info=True)

+ 41 - 0
LIB/FRONTEND/odo/DailyMileageEstimation/main_daily_mileage.py

@@ -0,0 +1,41 @@
+
+from LIB.BACKEND import DBManager
+import mileage
+from LIB.MIDDLE.CellStateEstimation.Common import log
+import datetime
+import pandas as pd
+
+dbManager = DBManager.DBManager()
+
+now_time=datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')   #type: str
+now_time=datetime.datetime.strptime(now_time,'%Y-%m-%d %H:%M:%S')     #type: datetime
+start_time=now_time-datetime.timedelta(days=1)
+end_time=str(now_time)
+start_time=str(start_time)
+
+dataSOH = pd.read_excel('sn-20210903.xlsx',sheet_name='sn-20210903')
+fileNames = dataSOH['sn']
+fileNames = list(fileNames)
+l = len(fileNames)
+
+#log信息配置
+mylog=log.Mylog('log.txt','error')
+mylog.logcfg()
+
+
+for k in range(l):
+    try:
+        sn = fileNames[k]
+        df_data = dbManager.get_data(sn=sn, start_time=start_time, end_time=end_time, data_groups=['bms','gps'])
+        data_bms = df_data['bms']
+        data_gps = df_data['gps']
+
+        #...............每日累积里程............................................................................
+        if len(data_bms['时间戳'])>0:
+            df_res = mileage.cal_mileage(sn,data_gps,data_bms)
+            df_res.to_csv('Mileage_'+sn+'.csv')
+        
+    except Exception as e:
+        print(repr(e))
+        mylog.logopt(sn,e)
+        pass

+ 3 - 0
LIB/FRONTEND/odo/DailyMileageEstimation/run.bat

@@ -0,0 +1,3 @@
+cd /d D:\deploy\python_platform\data_analyze_platform\LIB\FRONTEND\odo\DailyMileageEstimation
+title cal_dailyMileage
+D:\env\py_pro\python.exe D:\deploy\python_platform\data_analyze_platform\LIB\FRONTEND\odo\DailyMileageEstimation\deploy.py

+ 3 - 0
LIB/FRONTEND/odo/DailyMileageEstimation/run_history.bat

@@ -0,0 +1,3 @@
+cd /d D:\deploy\python_platform\data_analyze_platform\LIB\FRONTEND\odo\DailyMileageEstimation
+title cal_dailyMileage
+D:\env\py_pro\python.exe D:\deploy\python_platform\data_analyze_platform\LIB\FRONTEND\odo\DailyMileageEstimation\deployhistory.py

+ 358 - 0
LIB/MIDDLE/odo/DailyMileageEstimation/V1_0_2/cal_mileage.py

@@ -0,0 +1,358 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Sat Sep 25 23:26:27 2021
+
+@author: admin
+"""
+import pandas as pd
+import numpy as np
+from LIB.BACKEND.DataPreProcess import DataPreProcess
+import os
+import math
+import datetime
+import time
+
+#将时间戳由 "%Y-%m-%d %H:%M:%S" 切换为 sec
+def timeconvert(df_in,column_name):  
+    df=df_in.copy()
+    df.index=range(len(df))
+    time=df[column_name]
+    timeInSeries=[]
+    time2=datetime.datetime.strptime(str(time[0]),"%Y-%m-%d %H:%M:%S")
+    for k in range(len(time)):
+        time1=datetime.datetime.strptime(str(time[k]),"%Y-%m-%d %H:%M:%S")    
+        t=(time1-time2)
+        timeInSeries.append(t.days*86400+t.seconds)
+    df.loc[:,'相对时间[s]']=pd.DataFrame(timeInSeries,columns=['相对时间[s]'])
+    return df
+
+#计算累积能量
+def cal_accumKwh(df_in):
+    df_in1=df_in.copy()
+    df1=df_in1[['总电流[A]','总电压[V]','相对时间[s]']]
+    df1=df1.dropna(axis=0,how='any')
+    I=df1['总电流[A]'].values
+    V=df1['总电压[V]'].values
+    t=df1['相对时间[s]'].values
+    accumAh=[0.0]
+    for k in range(1,len(I)):
+        accumAh_temp=(t[k]-t[k-1])*((I[k]+I[k-1])/(2*3600))*(V[k]+V[k-1])/2/1000
+        accumAh.append(accumAh[-1]+accumAh_temp)
+    df1.loc[:,'累积能量[Kwh]']=accumAh
+    df_out=pd.merge(df_in1,df1[['累积能量[Kwh]']],how='left',left_index=True, right_index=True)
+    return(df_out)
+
+#将时间格式化为整数
+def str_data_to_num(str_data):
+    # 格式时间成毫秒
+    strptime = time.strptime(str_data,"%Y-%m-%d %H:%M:%S")
+    # print("strptime",strptime)
+    mktime = int(time.mktime(strptime)*1000)
+    # print("mktime",mktime)
+    return mktime
+
+def df_date_To_int(df_in):
+    df=df_in.copy()
+    for k in range(len(df)):
+        df.loc[k,'绝对时间[ms]']=str_data_to_num(df['时间戳'][k])
+    return df
+
+#根据经纬度获取两点之间的距离
+def cal_dis_meters(radius,latitude1, longitude1,latitude2, longitude2):  
+    radLat1 = (math.pi/180)*latitude1  
+    radLat2 = (math.pi/180)*latitude2  
+    radLng1 = (math.pi/180)*longitude1  
+    radLng2= (math.pi/180)*longitude2      
+    d=2*math.asin(math.sqrt(math.pow(math.sin((radLat1-radLat2)/2.0),2)+math.cos(radLat1)*math.cos(radLat2)*math.pow(math.sin((radLng1-radLng2)/2.0),2)))*radius
+    return d
+
+def cal_gps_distance(df_in):
+    #根据gps数据计算△距离1和△距离2
+    #△距离1:直接根据两次的经度和纬度计算得到的马氏距离
+    #△距离2:当两次上报经纬度的时间间隔<60sec时,如果车辆为行驶状态则使用两次的经纬度求得的马氏距离,
+    #如果车辆不为行驶状态,则为0.
+    df_gpsOnly=df_in[df_in['纬度']>0]
+    index_list=df_gpsOnly.index
+    pos_list=df_gpsOnly[['纬度','经度']].values
+    time_list=df_in['相对时间[s]'].values
+    # Energy_list=df_in['累积能量[Kwh]'].values
+    df_gpsOnly.loc[index_list[0],'△距离1']=0
+    df_gpsOnly.loc[index_list[0],'△距离2']=0
+    for k in range(1,len(pos_list)):
+        latitude1=pos_list[k-1][0]
+        longitude1=pos_list[k-1][1]
+        latitude2=pos_list[k][0]
+        longitude2=pos_list[k][1]
+        dlt_odo=cal_dis_meters(6378.137,latitude1, longitude1,latitude2, longitude2)
+        df_gpsOnly.loc[index_list[k],'△距离1']=dlt_odo    
+        if time_list[index_list[k]]-time_list[index_list[k-1]]<60:#两次上传GPS数据时间间隔小于60sec
+            if df_gpsOnly.loc[index_list[k],'data_status']=='drive' :   
+                df_gpsOnly.loc[index_list[k],'△距离2']=dlt_odo
+            elif df_gpsOnly.loc[index_list[k],'data_status']=='none' :
+                df_gpsOnly.loc[index_list[k],'△距离2']=dlt_odo
+            else:
+                df_gpsOnly.loc[index_list[k],'△距离2']=0
+    return(df_gpsOnly)
+
+
+def real_odo(df_in,avg_cost):
+    # df_handle=df_in.copy()
+    df=timeconvert(df_in,"时间戳")#计算相对时间
+    df=cal_accumKwh(df)#计算累积能量
+
+    positive_lat_index=df[df['纬度']>0].index
+    if len(positive_lat_index)>2:
+        first_index=positive_lat_index[0]
+        end_index=positive_lat_index[-1]
+        #将数据分割为有第一个GPS数据之前(part1)、
+        #有最后一个GPS数据之后(part3)以及
+        #有第一个GPS数据和最后一个GPS数据中间的数据(part3)
+        part1=df[0:first_index+1]
+        part2=df[first_index:end_index+1]
+        part3=df[end_index:-1]
+        
+        #第一部分距离计算    
+        part1.index=[i for i in range(len(part1))]
+        part1.loc[0,'△距离']=0
+        AccumEnergy1=part1['累积能量[Kwh]'].values
+        for k1 in range(1,len(part1)):
+            if (AccumEnergy1[k1]-AccumEnergy1[k1-1])>0:
+                part1.loc[k1,'△距离']=(AccumEnergy1[k1]-AccumEnergy1[k1-1])*avg_cost
+                part1.loc[k1,'方法']=4
+            else:
+                part1.loc[k1,'△距离']=0
+                part1.loc[k1,'方法']=5
+        
+        #第二部分计算
+        part2_gps=part2[part2['纬度']>0]
+        part2_gps.index=[i for i in range(len(part2_gps))]
+        times_list=part2_gps['相对时间[s]'].values
+        lat=part2_gps['纬度'].values
+        lng=part2_gps['经度'].values
+        AccumEnergy2=part2_gps['累积能量[Kwh]'].values
+        part2_gps.loc[0,'△距离']=0
+        for k2 in range(1,len(part2_gps)):
+            delta_energy=AccumEnergy2[k2]-AccumEnergy2[k2-1]
+            delta_span=cal_dis_meters(6378.137,lat[k2], lng[k2],lat[k2-1], lng[k2-1])
+            v_spd=3600*delta_span/(times_list[k2]-times_list[k2-1])        
+            if times_list[k2]-times_list[k2-1]<60 and not delta_energy<=0:
+                if v_spd>50:
+                    part2_gps.loc[k2,'△距离']=delta_energy*avg_cost
+                    part2_gps.loc[k2,'方法']=1_1
+                else:
+                    part2_gps.loc[k2,'△距离']=max(delta_span,delta_energy*avg_cost)
+                    part2_gps.loc[k2,'方法']=1_2
+            else:            
+                if delta_energy<=0:
+                    part2_gps.loc[k2,'△距离']=0
+                    part2_gps.loc[k2,'方法']=2
+                else:
+                    if v_spd>50:
+                        part2_gps.loc[k2,'△距离']=delta_energy*avg_cost
+                        part2_gps.loc[k2,'方法']=3_1
+                    else:
+                        part2_gps.loc[k2,'△距离']=max(delta_span,delta_energy*avg_cost)
+                        part2_gps.loc[k2,'方法']=3_2
+    
+                    
+        #第三部分距离计算    
+        part3.index=[i for i in range(len(part3))]
+        part3.loc[0,'△距离']=0
+        AccumEnergy3=part3['累积能量[Kwh]'].values
+        for k3 in range(1,len(part3)):
+            if (AccumEnergy3[k3]-AccumEnergy3[k3-1])>0:
+                part3.loc[k3,'△距离']=(AccumEnergy3[k3]-AccumEnergy3[k3-1])*avg_cost
+                part3.loc[k3,'方法']=4
+            else:
+                part3.loc[k3,'△距离']=0
+                part3.loc[k3,'方法']=5
+        df_out=pd.concat([part1,part2_gps[1:],part3[1:]])
+    else:
+        part1=df
+        part2=df[0:0]
+        part3=df[0:0]
+        
+        #第一部分距离计算    
+        part1.index=[i for i in range(len(part1))]
+        part1.loc[0,'△距离']=0
+        AccumEnergy1=part1['累积能量[Kwh]'].values
+        for k1 in range(1,len(part1)):
+            if (AccumEnergy1[k1]-AccumEnergy1[k1-1])>0:
+                part1.loc[k1,'△距离']=(AccumEnergy1[k1]-AccumEnergy1[k1-1])*avg_cost
+                part1.loc[k1,'方法']=4
+            else:
+                part1.loc[k1,'△距离']=0
+                part1.loc[k1,'方法']=5
+        df_out=part1.copy()
+    
+    #计算累积里程
+    df_out.loc[0,'累积里程[km]']=0
+    df_out.index=[i for i in range(len(df_out))]
+
+    for k in range(1,len(df_out)):
+        df_out.loc[k,'累积里程[km]']=df_out.loc[k-1,'累积里程[km]']+df_out.loc[k,'△距离']
+    return(df_out)
+
+def calcul_mileage(sn,data_bms,data_gps):
+
+    #合并两张表格
+    df_bms=data_bms.copy()
+    df_gps=data_gps.copy()
+    #删除纬度小于10的点
+    for k in range(1,len(df_gps)):
+        if df_gps.loc[k,'纬度']<10:
+            df_gps=df_gps.drop(k)
+    df_bms.set_index(["时间戳"], inplace=True)
+    df_gps.set_index(["时间戳"], inplace=True)
+    merge_df1=pd.merge(df_bms, df_gps,how='outer', left_index=True, right_index=True)
+    merge_df1.loc[:,'时间戳']=merge_df1.index
+    merge_df1.index=[i for i in range(len(merge_df1))]
+
+    #参数定义
+    cost_min=25 #最小能耗km/kwh
+    cost_max=50 #最高能耗km/kwh
+
+    df_input=merge_df1[['时间戳','总电流[A]', '总电压[V]','SOC[%]','充电状态','纬度', '经度']]
+    #电流电压数据修复
+    df_input=timeconvert(df_input,"时间戳")#计算相对时间
+    related_times=df_input['相对时间[s]'].values
+    lat_list=df_input['纬度'].values
+    lng_list=df_input['经度'].values
+    Vlt_list=df_input['总电压[V]'].values
+    for k in range(1,len(df_input)):
+        if math.isnan(df_input.loc[k,'总电流[A]']):
+            if related_times[k]-related_times[k-1]<5:
+                df_input.loc[k,'总电流[A]']=df_input.loc[k-1,'总电流[A]']
+                df_input.loc[k,'总电压[V]']=df_input.loc[k-1,'总电压[V]']
+                df_input.loc[k,'修复']=1
+            elif lat_list[k-1]>0:
+                delta_odo=cal_dis_meters(6378.137,lat_list[k], lng_list[k],lat_list[k-1], lng_list[k-1])
+                df_input.loc[k,'总电流[A]']=1000*3600*(delta_odo/cost_min)/70/(related_times[k]-related_times[k-1])
+                df_input.loc[k,'总电压[V]']=70
+                df_input.loc[k,'修复']=2
+            elif related_times[k]-related_times[k-1]<30:
+                df_input.loc[k,'总电流[A]']=df_input.loc[k-1,'总电流[A]']
+                df_input.loc[k,'总电压[V]']=df_input.loc[k-1,'总电压[V]']
+                df_input.loc[k,'修复']=3
+            else:
+                df_input=df_input.drop(k)
+
+    df_input.index=[i for i in range(len(df_input))]
+    df_input['日期']=[df_input.loc[i,'时间戳'][0:10] for i in range(len(df_input))]     
+    date_list=np.unique(df_input['日期'].values)
+
+    list_result=[]
+    input_res=pd.DataFrame()
+    res = pd.DataFrame()
+    df_input_copy=df_input.copy()
+    for date_str in date_list:
+        df_input_copy=df_input[df_input['日期']==date_str]
+        data_len=len(df_input_copy)
+        time_list=df_input_copy['时间戳'].values
+        #初始化参数
+        start_time=datetime.datetime.strptime(time_list[0], "%Y-%m-%d %H:%M:%S")
+        last_time=time_list[0]
+        reset_time=start_time
+        start_index=0
+        end_index=1
+        cal_count=0
+        df_deltaData_last=df_input_copy[0:0]
+        #初始化输出
+        df_result=pd.DataFrame()
+        
+        df_result.loc[0,'时间']=start_time
+        df_result.loc[0,'时间']=str(df_result.loc[0,'时间'])
+        df_result.loc[0,'时间'] =df_result.loc[0,'时间'].rpartition(':')[0]
+        
+        df_result.loc[0,'累积里程[km]']=0
+        df_result.loc[0,'能耗[km/kwh]']=cost_min
+        process_store=[]
+        avg_cost=25
+        cross_odo=0
+        for k in range(1,data_len):
+            
+            target_Time=start_time+datetime.timedelta(minutes=5)
+            timenow=datetime.datetime.strptime(time_list[k], "%Y-%m-%d %H:%M:%S")
+            if target_Time>=timenow:
+                delta_time=(target_Time-timenow).seconds
+                cal_flag=0
+                if delta_time<60:
+                    end_index=k
+                    cal_flag=1
+            else:        
+                end_index=k
+                cal_flag=1
+            
+            if cal_flag==1:
+                cal_count=cal_count+1
+                
+                df_deltaData=df_input_copy[max(start_index-100,0):end_index+1]
+                # avg_cost=df_result.loc[cal_count-1,'能耗[km/kwh]']
+                avg_cost=cost_min
+                df_span=real_odo(df_deltaData,avg_cost)
+                st_str=df_span['时间戳'].values[0]
+                st_time=datetime.datetime.strptime(st_str, "%Y-%m-%d %H:%M:%S")
+                last_time_s=datetime.datetime.strptime(last_time, "%Y-%m-%d %H:%M:%S")
+                if last_time_s>=st_time:
+                    last_time=last_time
+                    cross_odo=cross_odo
+                else:
+                    last_time=start_time
+                    cross_odo=0
+                delta_odo=df_span['累积里程[km]'].values[-1]-df_span[df_span['时间戳']==str(last_time)]['累积里程[km]'].values[0]
+                delta_energy=df_span['累积能量[Kwh]'].values[-1]-df_span[df_span['时间戳']==str(last_time)]['累积能量[Kwh]'].values[0]
+                df_result.loc[cal_count,'时间']=timenow
+                df_result.loc[cal_count,'时间']=str(df_result.loc[cal_count,'时间'])
+                df_result.loc[cal_count,'时间'] = df_result.loc[cal_count,'时间'].rpartition(':')[0]
+                
+                df_result.loc[cal_count,'累积里程[km]']=df_result.loc[cal_count-1,'累积里程[km]']+delta_odo-cross_odo
+                if delta_energy>0:
+                    df_result.loc[cal_count,'能耗[km/kwh]']=min(max(delta_odo/delta_energy,cost_min),cost_max)
+                else:
+                    df_result.loc[cal_count,'能耗[km/kwh]']=cost_min
+                
+                # df_span[df_span['纬度']>0][-1:]
+                if len(df_span[df_span['纬度']>0])>0:
+                    last_gps=df_span[df_span['纬度']>0][-1:]
+                    idx=last_gps.index.values[0]
+                    last_time=df_span.loc[idx,'时间戳']        
+                    cross_odo=df_span['累积里程[km]'].values[-1]-df_span.loc[idx,'累积里程[km]']
+                else:
+                    last_time=df_span['时间戳'].values[-1]        
+                    cross_odo=0
+                
+                start_index=end_index
+                start_time=timenow
+                cal_flag=0
+    
+        res=res.append(df_result)
+        input_res=input_res.append(df_input_copy)
+
+    l= len(input_res['时间戳'])
+    for k in range(l):
+        input_res.loc[k,'时间戳'] =input_res.loc[k,'时间戳'].rpartition(':')[0]
+
+    res.index=[i for i in range(len(res))]
+    res['日期']=[res.loc[i,'时间'][0:10] for i in range(len(res))]     
+
+    merge_res=pd.DataFrame()
+    for date_str in date_list:
+        input_res_copy=input_res[input_res['日期']==date_str]
+        input_res_copy=input_res_copy.drop_duplicates('时间戳')
+        res_copy=res[res['日期']==date_str]
+        df_merge=pd.DataFrame()
+        df_merge=pd.merge(input_res_copy,res_copy,left_on='时间戳',right_on='时间',how='right')
+        merge_res=merge_res.append(df_merge)
+
+    merge_res['sn']=sn
+    merge_res=merge_res[['时间戳','sn','总电流[A]','总电压[V]','SOC[%]','充电状态','纬度','经度','能耗[km/kwh]','累积里程[km]']]
+    merge_res=merge_res.rename(columns={'累积里程[km]':'每日累积里程[km]'})
+
+    merge_res.to_csv('fgh7.csv')
+
+    return merge_res
+
+
+
+
+

+ 40 - 0
LIB/MIDDLE/odo/DailyMileageEstimation/V1_0_2/main_daily_mileage.py

@@ -0,0 +1,40 @@
+from LIB.BACKEND import DBManager
+import cal_mileage
+from LIB.MIDDLE.CellStateEstimation.Common import log
+import datetime
+import pandas as pd
+
+dbManager = DBManager.DBManager()
+
+now_time=datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')   #type: str
+now_time=datetime.datetime.strptime(now_time,'%Y-%m-%d %H:%M:%S')     #type: datetime
+start_time=now_time-datetime.timedelta(days=1)
+end_time=str(now_time)
+start_time=str(start_time)
+
+dataSOH = pd.read_excel('sn-20210903.xlsx',sheet_name='sn-20210903')
+fileNames = dataSOH['sn']
+fileNames = list(fileNames)
+l = len(fileNames)
+
+#log信息配置
+mylog=log.Mylog('log.txt','error')
+mylog.logcfg()
+
+
+for k in range(l):
+    try:
+        sn = fileNames[k]
+        df_data = dbManager.get_data(sn=sn, start_time=start_time, end_time=end_time, data_groups=['bms','gps'])
+        data_bms = df_data['bms']
+        data_gps = df_data['gps']
+
+        #...............每日累积里程............................................................................
+        if len(data_bms['时间戳'])>0 and len(data_gps['时间戳'])>0:
+            df_res = cal_mileage.calcul_mileage(sn,data_gps,data_bms)
+            df_res.to_csv('Mileage_'+sn+'.csv')
+        
+    except Exception as e:
+        print(repr(e))
+        mylog.logopt(sn,e)
+        pass

+ 37 - 0
LIB/MIDDLE/odo/DailyMileageEstimation/V1_0_2/main_mileage.py

@@ -0,0 +1,37 @@
+
+from LIB.BACKEND import DBManager
+import cal_mileage
+from LIB.MIDDLE.CellStateEstimation.Common import log
+import datetime
+import pandas as pd
+
+dbManager = DBManager.DBManager()
+
+dataSOH = pd.read_excel('sn-20210903.xlsx',sheet_name='sn-20210903')
+fileNames = dataSOH['sn']
+fileNames = list(fileNames)
+l = len(fileNames)
+
+#log信息配置
+mylog=log.Mylog('log.txt','error')
+mylog.logcfg()
+
+month='202110'
+
+for k in range(l):
+    try:
+        sn = fileNames[k]
+
+        df_data = dbManager.get_data(sn=sn, start_time='2021-10-01 00:00:00', end_time='2021-11-01 00:00:00', data_groups=['bms','gps'])
+        data_bms = df_data['bms']
+        data_gps = df_data['gps']
+
+        #...............每日累积里程............................................................................
+        if len(data_bms['时间戳'])>0 and len(data_gps['时间戳'])>0:
+            df_res = cal_mileage.calcul_mileage(sn,data_bms,data_gps)
+            df_res.to_csv('Mileage_'+sn+'_'+month+'.csv')
+        
+    except Exception as e:
+        print(repr(e))
+        mylog.logopt(sn,e)
+        pass

BIN
LIB/MIDDLE/odo/DailyMileageEstimation/V1_0_2/每日里程表单.xlsx