Browse Source

重新跟踪

lmstack 3 years ago
parent
commit
65a87ae160

+ 18 - 0
.gitignore

@@ -0,0 +1,18 @@
+*.txt
+./USER
+/FILES
+/USER
+/.vscode/
+/*/__pycache__/*.*
+/*/*/__pycache__/*.pyc
+/*.ipynb
+/*.csv
+*.doc
+*.ppt
+*.tmp
+!/demo.ipynb
+/手册
+!.gitignore
+# *.*
+/CONFIGURE/PathSetting.py
+*.log

+ 366 - 0
LIB/BACKEND/DBManager.py

@@ -0,0 +1,366 @@
+'''
+暂时采用http方式获取历史数据。
+
+预留:后期若改用通过访问数据库的形式进行数据的获取,则本文件负责数据库的连接,sql指令的执行,数据获取等功能。
+'''
+__author__ = 'Wang Liming'
+
+import time
+import datetime
+import time
+import pandas as pd
+import numpy as np
+import json
+import requests
+import pymysql
+import pdb
+
+
+class DBManager():
+
+    def __init__(self, host='', port='', auth='', db='', username='', password=''):
+        self.host = host
+        self.port = port
+        self.auth = auth
+        self.db = db
+        self.username = username
+        self.password = password
+        pass
+
+    def __enter__(self):
+        self.connect()
+        return self
+
+    def __exit__(self):
+        self.close()
+
+    def connect(self):
+        conn_success_flag = 0
+        while not conn_success_flag:
+            try:
+                self.conn = pymysql.connect(host=self.host, port=self.port, user=self.user, password=self.password, database=self.db)
+            except Exception as e:
+                conn_success_flag = 0
+                print("数据库连接失败 :{}".format(e))
+                time.sleep(5)
+            else:
+                conn_success_flag = 1
+                self.cursor = self.conn.cursor()
+    def close(self):
+        try:
+            self.conn.close()
+        except Exception as e:
+            print(e)
+        else:
+            print('数据库已断开连接')
+
+    def add(table, keyvalue):
+        fields_str = ''
+        values_str = ''
+        for k,v in keyvalue.items():
+
+            fields_str += k+' '
+        sql = 'insert into table {} ({}) values ({})'.format(table, fields_str, values_str)
+
+
+    # 以下各个函数实现 通过http方式获取数据
+    @staticmethod
+    def _get_var_name(cellnum,Tempnum,Othernum):
+        temp = []
+        for i in range(cellnum):
+            temp.append('单体电压'+str(i+1))
+        for i in range(Tempnum):
+            temp.append('单体温度'+str(i+1))
+        for i in range(Othernum):
+            temp.append('其他温度'+str(i+1))
+        return temp
+
+    @staticmethod
+    def _download_json_data(url):
+        '''
+        返回json数据的生成器,一次一行
+        '''
+
+        i = 0
+        while 1:
+            try:
+                r = requests.get(url, stream=True, timeout=100,  headers={'Connection':'close'})
+                break
+            except requests.exceptions.RequestException as e:
+                if (i == 0):
+                    print()
+                print('\r' + 'Server Error, retry {}......'.format(str(i)), end=" ")
+                time.sleep(5)
+                i+=1
+        # print(r.content)
+        # pdb.set_trace()    
+        for line in r.iter_lines():
+            if line:
+                yield json.loads(line)
+
+    @staticmethod
+    def _convert_to_dataframe_bms(data, mode=0):
+        CellU = []
+        CellT = []
+        OtherT = []
+        CellU_Num = 0
+        CellT_Num = 0
+        OtherT_Num = 0
+        CellU_Num = len(data['ffBatteryStatus']['cellVoltageList'])
+        CellT_Num = len(data['ffBatteryStatus']['cellTempList'])
+
+        try:
+            OtherT_Num = len(data['ffBatteryStatus']['otherTempList'])
+        except:
+            OtherT_Num = 0
+        for i in range(CellU_Num):
+            CellU.append(data['ffBatteryStatus']['cellVoltageList'][i]*1000)
+        for i in range(CellT_Num):
+            CellU.append(data['ffBatteryStatus']['cellTempList'][i])
+        for i in range(OtherT_Num):
+            CellU.append(data['ffBatteryStatus']['otherTempList'][i])
+        if mode == 0:
+            data_len = 15
+            
+            data_block = np.array([data['info']['obdTime'],data['ffBatteryStatus']['rssi'],data['ffBatteryStatus']['errorLevel'],data['ffBatteryStatus']['errorCode']
+                    ,data['ffBatteryStatus']['current'],data['ffBatteryStatus']['voltageInner'],data['ffBatteryStatus']['voltageOutter'],
+                    data['ffBatteryStatus']['totalOutputState'],data['ffBatteryStatus']['lockedState'],
+                    data['ffBatteryStatus']['chargeState'],data['ffBatteryStatus']['heatState'],data['ffBatteryStatus']['cellVoltageDiff']
+                    ,data['ffBatteryStatus']['soc'],data['ffBatteryStatus']['soh'],data['ffBatteryStatus']['cellVolBalance']]).reshape(1,data_len)
+        elif mode == 1:
+            data_len = 11
+            
+            data_block = np.array([data['info']['obdTime'],data['ffBatteryStatus']['rssi']
+            ,data['ffBatteryStatus'].get('errorLevel'),data['ffBatteryStatus'].get('errorCode'),data['ffBatteryStatus']['switchState']
+            ,data['ffBatteryStatus']['current'],data['ffBatteryStatus']['voltageInner'],data['ffBatteryStatus']['chargeState'],
+            data['ffBatteryStatus']['cellVoltageDiff'],data['ffBatteryStatus']['soc'],data['ffBatteryStatus']['soh']]).reshape(1,data_len)
+        data_block = np.append(data_block,CellU)
+        data_block = np.append(data_block,CellT)
+        data_block = np.append(data_block,OtherT)
+        data_block = data_block.reshape(1,len(data_block))
+        return data_block,CellU_Num,CellT_Num,OtherT_Num
+
+    @staticmethod
+    def _convert_to_dataframe_gps(data, mode=0):
+        if mode == 0:
+            if data['info']['subType'] == 1:
+                data_block = np.array([data['info']['obdTime'],data['ffGps']['locationType'], data['ffGps']['satellites'],
+                                       data['ffGps']['latitude'],data['ffGps']['longitude'],data['ffGps']['speed'], 
+                                       data['ffGps']['altitude'], data['ffGps']['direction']]).reshape(1,8)
+                df = pd.DataFrame(
+                    columns=['时间戳','定位类型', '卫星数','纬度','经度','速度[km/h]','海拔','航向'],data=data_block)
+            elif data['info']['subType'] == 2:
+                df = pd.DataFrame(
+                    columns=['时间戳','定位类型', '卫星数','纬度','经度','速度[km/h]','海拔','航向'])
+        if mode == 1:
+                data_block = np.array([data['info']['obdTime'],data['ffGps']['locationType'],data['ffGps']['latitude'],data['ffGps']['longitude']
+                    ,data['ffGps']['speed'], data['ffGps']['isValid']]).reshape(1,6)
+                df = pd.DataFrame(
+                    columns=['时间戳','定位类型', '纬度','经度','速度[km/h]','有效位'],data=data_block)
+        return df
+
+    
+    @staticmethod
+    def _convert_to_dataframe_system(data, mode=0):
+        if mode == 0:
+            
+            data_block = np.array([data['info']['obdTime'],data['ffSystemInfo']['heatTargetTemp'], data['ffSystemInfo']['heatTimeout'],
+                                    time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(int(data['ffSystemInfo']['rentalStartTime'])/1000)),
+                                    data['ffSystemInfo']['rentalPeriodDays'],data['ffSystemInfo']['bmsInterval'], 
+                                    data['ffSystemInfo']['gpsInterval']]).reshape(1,7)
+            df = pd.DataFrame(
+                columns=['时间戳','加热目标温度', '加热超时','租赁开始时间','租赁天数','bms上传周期','gps上传周期'],data=data_block)
+        if mode == 1:
+                df = pd.DataFrame()
+
+        return df
+    
+    @staticmethod
+    def _convert_to_dataframe_accum(data, mode=0):
+        if mode == 0:
+            
+            data_block = np.array([data['info']['obdTime'],data['ffBatteryAccum']['SOH_AlgUnexTime'], data['ffBatteryAccum']['CHG_AHaccum'],
+                                    data['ffBatteryAccum']['CHG_PHaccum'], data['ffBatteryAccum']['DSG_AHaccum'],
+                                    data['ffBatteryAccum']['DSG_PHaccum'],data['ffBatteryAccum']['OverTemp_CHG_AHaccum'], 
+                                    data['ffBatteryAccum']['OverTemp_CHG_PHaccum']]).reshape(1,8)
+            df = pd.DataFrame(
+                columns=['时间戳','SOH未标定时间', '累计充电电量','累计充电能量','累计放电电量','累计放电能量',
+                                               '累计高温充电电量', '累计高温充电能量'],data=data_block)
+
+        if mode == 1:
+                data_block = np.array([data['info']['obdTime'], data['ffBatteryAccum']['CHG_AHaccum'],
+                                    data['ffBatteryAccum']['CHG_PHaccum'], data['ffBatteryAccum']['DSG_AHaccum'],
+                                    data['ffBatteryAccum']['DSG_PHaccum'],data['ffBatteryAccum']['totalMileage']]).reshape(1,6)
+                df = pd.DataFrame(
+                    columns=['时间戳','累计充电电量','累计充电能量','累计放电电量','累计放电能量', '累积里程'],data=data_block)
+        return df
+    
+    @staticmethod
+    def _get_data(urls,type_name,mode=0):
+        if type_name == 'bms':
+            if mode == 0:
+                name_const = ['时间戳','GSM信号','故障等级','故障代码','总电流[A]','总电压[V]', '外电压', '总输出状态', '上锁状态', '充电状态','加热状态',
+                              '单体压差', 'SOC[%]','SOH[%]','单体均衡状态']
+            elif mode == 1:
+                name_const = ['时间戳','GSM信号','故障等级', '故障代码','开关状态', '总电流[A]','总电压[V]','充电状态', '单体压差', 'SOC[%]','SOH[%]']
+            i=0
+            CellUNum = 0
+            CellTNum = 0
+            OtherTNumm = 0
+            st = time.time()
+            for line in DBManager._download_json_data(urls):
+                et = time.time()
+                if i==0:
+                    data_blocks,CellUNum,CellTNum,OtherTNumm = DBManager._convert_to_dataframe_bms(line, mode)
+                    i+=1
+                    continue
+                try:
+                    data_block,CellUNum,CellTNum,OtherTNumm = DBManager._convert_to_dataframe_bms(line, mode)
+                except:
+                    continue
+                try:
+                    data_blocks = np.concatenate((data_blocks,data_block),axis=0)
+                except Exception as e: 
+                    if 'all the input array dimensions except for the concatenation axis must match exactly' in str(e):
+                        pass
+                    else:
+                        raise e
+  
+                # print('\r'+str(i),end=" ")
+                # print(data_block)
+                # print(urls)
+                # print(time.time()-et)
+                i+=1
+            name_var = DBManager._get_var_name(CellUNum,CellTNum,OtherTNumm)
+            name_const.extend(name_var)
+            columns_name = name_const
+            if i==0:
+                data_blocks = []
+            df_all = pd.DataFrame(columns=columns_name,data=data_blocks)
+            if not df_all.empty:
+                df_all.loc[:,'时间戳'] = df_all.loc[:,'时间戳'].apply(lambda x:time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(int(x)/1000)))
+            return df_all
+        elif type_name =='gps':
+            if mode == 0:
+                df_all = pd.DataFrame(columns=['时间戳','定位类型', '卫星数','纬度','经度','速度[km/h]','海拔','航向'])
+            elif mode == 1:
+                df_all = pd.DataFrame(columns=['时间戳','定位类型', '纬度','经度','速度[km/h]','有效位'])
+            
+            for line in DBManager._download_json_data(urls):
+                df_add = DBManager._convert_to_dataframe_gps(line, mode)
+                df_all = df_all.append(df_add,ignore_index=True)
+            if not df_all.empty:
+                df_all.loc[:,'时间戳'] = df_all.loc[:,'时间戳'].apply(lambda x:time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(int(x)/1000)))
+            return df_all
+        elif type_name =='system':
+            if mode == 0:
+                df_all = pd.DataFrame(columns=['时间戳','加热目标温度', '加热超时','租赁开始时间','租赁天数','bms上传周期','gps上传周期'])
+            elif mode == 1:
+                df_all = pd.DataFrame()
+            for line in DBManager._download_json_data(urls):
+                df_add = DBManager._convert_to_dataframe_system(line, mode)
+                df_all = df_all.append(df_add,ignore_index=True)
+            if not df_all.empty:
+                df_all.loc[:,'时间戳'] = df_all.loc[:,'时间戳'].apply(lambda x:time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(int(x)/1000)))
+            return df_all
+        
+        elif type_name =='accum':
+            if mode == 0:
+                df_all = pd.DataFrame(columns=['时间戳','SOH未标定时间', '累计充电电量','累计充电能量','累计放电电量','累计放电能量',
+                                               '累计高温充电电量', '累计高温充电能量'])
+            elif mode == 1:
+                df_all = pd.DataFrame(columns=['时间戳','累计充电电量','累计充电能量','累计放电电量','累计放电能量', '累积里程'])
+            for line in DBManager._download_json_data(urls):
+                df_add = DBManager._convert_to_dataframe_accum(line, mode)
+                df_all = df_all.append(df_add,ignore_index=True)
+            if not df_all.empty:
+                df_all.loc[:,'时间戳'] = df_all.loc[:,'时间戳'].apply(lambda x:time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(int(x)/1000)))
+            return df_all
+    def get_data(self, url='http://172.16.126.13/store/load?dataType={}&limit=0&sn={}', sn='', start_time='', end_time='', 
+                 data_groups=['bms', 'gps']):
+        '''
+        获取指定 sn 和起止日期的bms和gps数据.
+        添加了重试机制。
+
+        --------------输入参数------------
+        url:数据获取url, 可采用默认值
+        sn: str, 电池sn号
+        start_time: str, 开始时间
+        end_time: str, 结束时间
+        data_groups:  选择需要获取的数据组,可填入多个字符串(默认只获取bms和gps数据)
+                    bms: bms数据
+                    gps:gps数据
+                    system:system数据
+                    accum:accum数据
+        
+
+        --------------输出参数------------
+        df_data: {'bms':dataframe, 'gps':dataframe, 'system':dataframe, ;accum':dataframe}
+        '''
+        
+        if len(set(data_groups) - (set(data_groups) and set(['bms', 'gps', 'system', 'accum']))) > 0:
+            raise Exception("data_groups 参数错误")
+        
+        
+        # mode: 0:正常取数; 1:7255 取数
+        if sn[0:2] == 'UD' or sn[0:2] == 'MG':
+            mode = 1
+        else:
+            mode = 0
+        bms_all_data = pd.DataFrame()
+        gps_all_data = pd.DataFrame()
+        system_all_data = pd.DataFrame()
+        accum_all_data = pd.DataFrame()
+        maxnum = (datetime.datetime.strptime(end_time, "%Y-%m-%d %H:%M:%S") - datetime.datetime.strptime(start_time, "%Y-%m-%d %H:%M:%S")).days +1
+        print("### start to get data {} from {} to {}".format(sn, start_time, end_time))
+        # 为避免chunkEncodingError错误,数据每天获取一次,然后将每天的数据合并,得到最终的数据
+        for j in  range(int(maxnum)):
+            timefrom = datetime.datetime.strptime(start_time, "%Y-%m-%d %H:%M:%S")+ datetime.timedelta(days=j)
+            timeto = datetime.datetime.strptime(start_time, "%Y-%m-%d %H:%M:%S")+ datetime.timedelta(days=j+1)
+            #滴滴的数据sub=0
+            if timefrom.strftime('%Y-%m-%d %H:%M:%S') >= end_time:
+                break
+            elif timeto.strftime('%Y-%m-%d %H:%M:%S') > end_time:
+                timeto = datetime.datetime.strptime(end_time, '%Y-%m-%d %H:%M:%S')
+            #print('{}_{}_----getting data----'.format(sn, timefrom))
+            bms_data = pd.DataFrame()
+            gps_data = pd.DataFrame()
+            system_data = pd.DataFrame()
+            accum_data = pd.DataFrame()
+            while True:
+                try:
+                    print('\r' + "# get data from {} to {}.........".format(str(timefrom), str(timeto)), end=" ")
+                    for data_group in data_groups:
+                        if data_group == 'bms':
+                            file_url = url.format(12, sn) + "&from="+timefrom.strftime('%Y-%m-%d %H:%M:%S')+"&to="+timeto.strftime('%Y-%m-%d %H:%M:%S')
+                            bms_data = DBManager._get_data(file_url,'bms',mode)
+                        if data_group == 'gps':
+                            file_url = url.format(16, sn) + "&from="+timefrom.strftime('%Y-%m-%d %H:%M:%S')+"&to="+timeto.strftime('%Y-%m-%d %H:%M:%S')
+                            gps_data = DBManager._get_data(file_url,'gps',mode)
+                        if data_group == 'system':
+                            file_url = url.format(13, sn) + "&from="+timefrom.strftime('%Y-%m-%d %H:%M:%S')+"&to="+timeto.strftime('%Y-%m-%d %H:%M:%S')
+                            system_data = DBManager._get_data(file_url,'system',mode)
+                        if data_group == 'accum':
+                            file_url = url.format(23, sn) + "&from="+timefrom.strftime('%Y-%m-%d %H:%M:%S')+"&to="+timeto.strftime('%Y-%m-%d %H:%M:%S')
+                            accum_data = DBManager._get_data(file_url,'accum',mode)
+                except Exception as e:
+                    if 'Connection broken' in str(e):
+                        continue
+                    else:
+                        raise Exception
+                else:
+                    bms_all_data = pd.concat([bms_all_data, bms_data], ignore_index=True)
+                    gps_all_data = pd.concat([gps_all_data, gps_data], ignore_index=True)
+                    system_all_data = pd.concat([system_all_data, system_data], ignore_index=True)
+                    accum_all_data = pd.concat([accum_all_data, accum_data], ignore_index=True)
+
+                    break
+
+        bms_all_data = bms_all_data.reset_index(drop=True)
+        gps_all_data = gps_all_data.reset_index(drop=True)
+        system_all_data = system_all_data.reset_index(drop=True)
+        accum_all_data = accum_all_data.reset_index(drop=True)
+        print('\nall data-getting done, bms_count is {}, gps_count is {}, system_count is {}, accum_count is {} \n'.format(
+            str(len(bms_all_data)), str(len(gps_all_data)), str(len(system_all_data)), str(len(accum_all_data))))
+        return {'bms':bms_all_data, 'gps':gps_all_data, 'system':system_all_data, 'accum':accum_all_data}
+

+ 488 - 0
LIB/BACKEND/DataPreProcess.py

@@ -0,0 +1,488 @@
+'''
+数据预处理类
+
+'''
+__author__ = 'Wang Liming'
+
+
+import CONFIGURE.PathSetting as PathSetting
+import sys
+sys.path.append(PathSetting.backend_path)
+from os import defpath
+import pandas as pd
+import numpy as np
+import pdb
+from numba import jit
+import Tools
+
+class DataPreProcess:
+    def __init__(self):
+        self.tools = Tools.Tools()
+        pass
+
+    # def data_split(self, dfin, drive_interval_threshold=120, charge_interval_threshold=300, 
+    #                            drive_stand_threshold=120, charge_stand_threshold=300,
+    #                            default_time_threshold = 300, drive_time_threshold=300, charge_time_threshold=300, 
+    #                            stand_time_threshold = 1800):
+    #     '''
+    #     数据分段函数,会调用_data_split_by_status和_data_split_by_time函数。
+    #     其中_data_split_by_status 将数据分为charge、drive、stand、和none段;
+    #     _data_split_by_time 将每个段内的数据,根据时间跳变继续分段。
+
+    #     '''
+    def time_filter(self, df_bms, df_gps):
+        df_bms.drop_duplicates(subset=['时间戳'], keep='first', inplace=True)
+        df_gps.drop_duplicates(subset=['时间戳'], keep='first', inplace=True)
+        df_bms = df_bms.reset_index(drop=True)
+        df_gps = df_gps.reset_index(drop=True)
+        return df_bms, df_gps
+
+    def data_split_by_status(self, dfin, drive_interval_threshold=120, charge_interval_threshold=300, 
+                                    drive_stand_threshold=120, charge_stand_threshold=300):
+        '''
+        # 数据预处理分段, 将原始数据段分为 charge、drive、stand、none段
+        # 状态判断
+        # 1、drive:(状态为2或3 且 存在电流>0 ) 或 (电流持续为0 且 持续时间<阈值 且 上一段数据为行车)
+        # 2、charge:(状态为2或3 且 不存在电流>0 ) 或 (电流持续为0 且 持续时间<阈值 且 上一段数据为充电)
+        # 3、stand:(电流持续为0 且 是数据段的第一段) 或 (电流持续为0 且 持续时间>阈值)
+        # 4、none: 其他
+
+        --------------输入参数-------------:
+        drive_interval_threshold: 行车段拼接阈值,如果两段行车的间隔时间小于该值,则两段行车合并。
+        charge_interval_threshold: 充电段拼接阈值,如果两段充电的间隔时间小于该值,则两段充电合并。
+        drive_stand_threshold: 静置段合并至行车段阈值,如果静置时间小于该值,则合并到上一段的行车中。
+        charge_stand_threshold: 静置段合并至充电段阈值,如果静置时间小于该值,则合并到上一段的充电中。
+
+        --------------输出-----------------:
+        在原始数据后面,增加data_split_by_crnt, data_split_by_status, data_status 三列
+        data_split_by_crnt: 按电流分段的序号
+        data_split_by_status:按电流和状态分段的序号
+        data_status: 状态标识
+        '''
+        # 首先根据电流是否为0 ,将数据分段
+        df = dfin.copy()
+        df['时间戳'] = pd.to_datetime(df['时间戳'])
+        
+        crnt_zero_or_not = df['总电流[A]']==0
+        last_crnt_flag = crnt_zero_or_not[0]
+        temp = 1
+        group_id = [temp]
+        for cur_crnt_flag in crnt_zero_or_not[1:]:
+            if last_crnt_flag ^ cur_crnt_flag:
+                temp = temp + 1
+            last_crnt_flag = cur_crnt_flag
+            group_id.append(temp)
+        df['data_split_by_crnt'] = group_id
+
+        # 然后判断每个段内的 充电状态及电流=0持续时长,决定当前状态
+        temp = 1
+        last_status = ""
+        status_id = []
+        status_list = []
+        data_number_list = sorted(list(set(df['data_split_by_crnt'])))
+
+        for data_number in data_number_list:
+            df_sel = df[df['data_split_by_crnt'] == data_number]
+            origin_index = list(df_sel.index)
+            df_sel = df_sel.reset_index(drop=True)
+            temp_2 = 0
+            # 如果当前数据段的电流非0,则可能分为charge、drive或none段
+            if df_sel.loc[0,'总电流[A]'] != 0:
+                # 电流 分段中可能存在状态变化的时刻, 内部根据状态进行分段.
+                # 该数据段内部,根据bms状态信号进行二次分段
+                status_drive_or_not = df_sel['充电状态']==3
+                last_status_flag = status_drive_or_not[0]
+                temp_2 = 0
+                group_id_2 = [temp_2]
+                for cur_status_flag in status_drive_or_not[1:]:
+                    if last_status_flag ^ cur_status_flag:
+                        temp_2 = temp_2 + 1
+                    last_status_flag = cur_status_flag
+                    group_id_2.append(temp_2)
+                
+                # 遍历二次状态分段
+                temp_2 = 0
+                last_status_2 = last_status
+                df_sel['index'] = group_id_2
+                data_number_list_2 = sorted(list(set(group_id_2)))
+                for data_number_2 in data_number_list_2:
+                    
+                    df_sel_2 = df_sel[df_sel['index'] == data_number_2]
+                    df_sel_2 = df_sel_2.reset_index(drop=True)
+                    
+                    # 根据bms状态 及 电流符号决定是charge还是drive
+                    # 如果状态为2或3, 且电流均<=0 则记为充电
+                    if df_sel_2.loc[0, '充电状态'] in [2, 3] and len(df_sel_2[df_sel_2['总电流[A]'] > 0]) == 0: 
+                        cur_status = 'charge'
+                    # 如果状态为2或3,且存在电流>0 则记为行车
+                    elif df_sel_2.loc[0, '充电状态'] in [2, 3] and len(df_sel_2[df_sel_2['总电流[A]'] > 0]) > 0: 
+                        cur_status = 'drive'
+                    # 否则 记为none
+                    else:
+                        cur_status = 'none'
+                    status_list.extend([cur_status] * len(df_sel_2))
+                    
+                    # 状态id号与前面电流为0的相同状态进行合并, 均判断应不应该与上一段合并    
+                    if origin_index[0] == 0: # 如果是所有数据的起始段数据,则直接赋值id号
+                        status_id.extend([temp + temp_2]*len(df_sel_2))
+                    
+                    else: # 判断是否与上一段数据合并
+                        deltaT = (df.loc[origin_index[0], '时间戳'] - df.loc[origin_index[0]-1, '时间戳']).total_seconds()
+                        # 如果 状态一致, 且 间隔时间小于阈值,则合并
+                        if last_status_2 == 'drive' and cur_status == last_status_2 and deltaT < drive_interval_threshold: 
+                            temp_2 = temp_2 - 1  
+                            status_id.extend([temp + temp_2]*len(df_sel_2)) 
+                        # 如果状态一致, 且 间隔时间小于阈值,则合并
+                        elif last_status_2 == 'charge' and cur_status == last_status_2 and deltaT < charge_interval_threshold: 
+                            temp_2 = temp_2 - 1  
+                            status_id.extend([temp + temp_2]*len(df_sel_2)) 
+                        else:
+                            status_id.extend([temp + temp_2]*len(df_sel_2))
+                    temp_2 = temp_2 + 1
+                    last_status_2 = status_list[-1]
+                temp_2 = temp_2 - 1
+            else:
+                # 如果当前数据段的电流为0,则可能分为stand,charge、drive或none段
+                if origin_index[0] == 0: # 如果是数据的起始,则无论长短,都认为是stand
+                    status_id.extend([temp]*len(df_sel))
+                    status_list.extend(['stand'] * len(df_sel))
+                else: # 不是数据的起始
+                    cur_deltaT = (df.loc[origin_index[-1], '时间戳'] - df.loc[origin_index[0], '时间戳']).total_seconds()
+                    if last_status == 'charge': # 如果上一个状态为充电
+                        if cur_deltaT < charge_stand_threshold: # 如果本次电流为0的持续时间小于 阈值,则合并
+                            status_list.extend(['charge'] * len(df_sel))
+                            temp = temp - 1  
+                            status_id.extend([temp]*len(df_sel))
+                        else: # 否则超过了阈值,记为stand
+                            status_id.extend([temp]*len(df_sel))
+                            status_list.extend(['stand'] * len(df_sel))
+                    elif last_status == 'drive': # 如果上一个状态为行车
+                        if cur_deltaT < drive_stand_threshold: # 如果本次电流为0的持续时间小于 阈值,则合并
+                            status_list.extend(['drive'] * len(df_sel))
+                            temp = temp - 1  
+                            status_id.extend([temp]*len(df_sel))
+                        else: # 否则超过了阈值,记为stand
+                            status_id.extend([temp]*len(df_sel))
+                            status_list.extend(['stand'] * len(df_sel))
+                    elif last_status == 'none': # 如果上一个状态未知
+                        status_id.extend([temp] * len(df_sel))
+                        status_list.extend(['stand'] * len(df_sel))
+            temp = temp + temp_2 + 1
+            last_status = status_list[-1] # 上一组状态
+        df['data_split_by_status'] = status_id
+        df['data_status'] = status_list
+        return df
+    def data_split_by_time(self, dfin, default_time_threshold = 300, drive_time_threshold=300, charge_time_threshold=300, 
+                                        stand_time_threshold = 1800):
+        '''
+        # 该函数用来解决数据丢失问题导致的分段序号异常,
+        # 将经过data_split_by_status分段后的数据,每个段内两行数据的时间跳变如果超过阈值,则继续分为两段
+
+        --------------输入参数-------------:
+        dfin:  调用data_split_by_status之后的函数
+        default_time_threshold: 默认时间阈值,如果状态内部时间跳变大于该值,则划分为两段
+        drive_time_threshold: 行车时间阈值,如果行车状态内部时间跳变大于该值,则划分为两段
+        charge_time_threshold: 充电时间阈值,如果充电状态内部时间跳变大于该值,则划分为两段
+        stand_time_threshold:静置时间阈值,如果静置状态内部时间跳变大于该值,则划分为两段
+
+        --------------输出-----------------:
+        在输入数据后面,增加data_split_by_status_time 一列
+        data_split_by_status_time: 按照状态和时间分段后的序号
+        '''  
+        data_id = []
+        temp = 1
+        data_number_list = sorted(list(set(dfin['data_split_by_status'])))
+        for data_number in data_number_list:
+            # if data_number == 1203:
+            #     pdb.set_trace()
+            status = list(dfin[dfin['data_split_by_status']==data_number]['data_status'])[0]
+            cur_indexes = dfin[dfin['data_split_by_status']==data_number].index
+            
+            time_array = np.array(dfin[dfin['data_split_by_status']==data_number]['时间戳'])
+            time_diff = np.diff(time_array)
+            time_diff = time_diff.astype(np.int64)
+            time_interval = default_time_threshold
+            if status == 'drive':
+                time_interval = drive_time_threshold
+            elif status == 'charge':
+                time_interval = charge_time_threshold
+            elif status == 'stand':
+                time_interval = stand_time_threshold
+            time_diff_index = (np.argwhere(((time_diff/1e9) > time_interval)==True))[:,0]
+            time_diff_origin_index = cur_indexes[time_diff_index]+1
+            if len(time_diff_index) == 0:
+                data_id.extend([temp] * len(cur_indexes))
+                temp += 1
+            else:
+                last_index = cur_indexes[0]
+                for index, cur_index in enumerate(time_diff_origin_index):
+                    if index == len(time_diff_origin_index)-1: # 如果是最后一个index,则
+                        data_id.extend([temp]* (cur_index-last_index))
+                        last_index = cur_index
+                        temp += 1
+                        data_id.extend([temp]* (cur_indexes[-1]-last_index+1))
+                    else:
+                        data_id.extend([temp]* (cur_index-last_index))
+                    last_index = cur_index
+                    temp += 1
+        dfin['data_split_by_status_time'] = data_id
+        return dfin
+    def combine_drive_stand(self, dfin):
+        '''
+        合并放电和静置段:将两次充电之间的所有数据段合并为一段, 状态分为 charge 和not charge
+        ---------------输入----------
+        dfin: 调用data_split_by_status()后输出的bms数据
+
+        ---------------输出----------
+        在输入数据后面,增加data_split_by_status_after_combine, data_status_after_combine 两列
+        data_split_by_status_after_combine: 将两次充电间的数据合并后的段序号
+        data_status_after_combine: 每段数据的状态标识
+        '''
+        df = dfin.copy()
+        data_split_by_status_1 = []
+        data_status_1 = []
+        number = 1
+        first_flag = True
+        data_number_list = sorted(list(set(df['data_split_by_status_time'])))
+        for data_number in data_number_list:
+            status = list(df[df['data_split_by_status_time']==data_number]['data_status'])
+            cur_status = status[0]
+            if first_flag:
+                first_flag = False
+            elif (last_status not in ['charge'] and cur_status in ['charge']) or (last_status in ['charge'] and cur_status not in ['charge']):
+                number += 1
+
+            data_split_by_status_1.extend([number]*len(status))
+            if cur_status in ['charge']:
+                data_status_1.extend(['charge']*len(status))
+            else:
+                data_status_1.extend(['not charge']*len(status))
+
+            last_status = cur_status
+        df['data_split_by_status_after_combine'] = data_split_by_status_1
+        df['data_status_after_combine'] = data_status_1
+
+        return df
+
+    def cal_stand_time(self, dfin):
+        '''
+        # 计算静置时间
+        # 将每次行车或充电的前后静置时间,赋值给stand_time 列, 单位为分钟
+
+        ----------------输入参数---------
+        dfin: 调用data_split_by_status()后输出的bms数据
+
+        ----------------输出参数----------
+        在输入数据后面,增加stand_time列
+        stand_time : 在行车段或充电段的起止两个位置处,表明开始前和结束后的静置时长,单位为分钟
+
+        '''
+        df = dfin.copy()
+        stand_time = []
+        first_flag = True
+        data_number_list = sorted(list(set(df['data_split_by_status_time'])))
+        for index, data_number in enumerate(data_number_list):
+            status = list(df[df['data_split_by_status_time']==data_number]['data_status'])
+            time =  list(df[df['data_split_by_status_time']==data_number]['时间戳'])
+            cur_status = status[0]
+            cur_delta_time = (time[-1]-time[0]).total_seconds() / 60.0 # 分钟
+            if len(status) >= 2:
+                if first_flag:
+                    first_flag = False
+                    if index < len(data_number_list)-1:
+                        if cur_status in ['charge', 'drive']:
+                            next_status = list(df[df['data_split_by_status_time']==data_number_list[index+1]]['data_status'])[0]
+                            stand_time.extend([None]*(len(status)-1))
+                            if next_status == 'stand':
+                                next_time =  list(df[df['data_split_by_status_time']==data_number_list[index+1]]['时间戳'])
+                                stand_time.extend([(next_time[-1]-next_time[0]).total_seconds() / 60.0])
+                            else:
+                                stand_time.extend([0])
+                        else:
+                            stand_time.extend([None]*len(status))
+                    else:
+                        stand_time.extend([None]*len(status))      
+                else:
+                    if cur_status in ['charge', 'drive']:
+                        if last_status == 'stand':
+                            stand_time.extend([last_delta_time])
+                        else:
+                            stand_time.extend([0])
+                        stand_time.extend([None]*(len(status)-2))
+                        if index < len(data_number_list)-1:
+                            next_status = list(df[df['data_split_by_status_time']==data_number_list[index+1]]['data_status'])[0]
+                            if next_status == 'stand':
+                                next_time =  list(df[df['data_split_by_status_time']==data_number_list[index+1]]['时间戳'])
+                                stand_time.extend([(next_time[-1]-next_time[0]).total_seconds() / 60.0])
+                            else:
+                                stand_time.extend([0])
+                        else:
+                            stand_time.extend([None])
+                    else:
+                        stand_time.extend([None]*len(status))
+                        
+            else:
+                stand_time.extend([None])
+            last_status = cur_status
+            last_delta_time = cur_delta_time
+        df['stand_time'] = stand_time
+        return df
+
+    # 输入GPS数据,返回本段数据的累积里程,及平均时速(如果两点之间)
+    @jit
+    def _cal_odo_speed(self, lat_list, long_list, time_list):
+        '''
+        输入:经度列表, 纬度列表, 时间列表;
+        输出:每两个经纬度坐标之间的距离,以及速度 的数组
+        '''
+        dis_array = []
+        speed_array = []
+ 
+        for i in range(len(lat_list)-1):
+            dis = self.tools.cal_distance(lat_list[i],long_list[i], lat_list[i+1],long_list[i+1])
+            dis_array.append(dis)
+            deltaT = abs(time_list[i] - time_list[i+1]).total_seconds()
+            speed_array.append(dis * 3600.0/deltaT)
+        return np.array(dis_array), np.array(speed_array)
+
+    def gps_data_judge(self, df_bms, df_gps, time_diff_thre=300, odo_sum_thre=200, drive_spd_thre=80, parking_spd_thre=2):
+        '''
+        GPS数据可靠性判断函数(基于combine前的分段)
+
+        GPS数据出现以下情况时,判定为不可靠:
+        1)如果该段对应的地理位置数据 少于2 个,则认为不可靠
+        2)如果截取的GPS数据的起止时间,与BMS数据段的起止时间相差超过阈值,则认为不可靠
+        3)如果行车段 累积里程超过阈值,车速超过阈值
+        4) 如果非行车段 车速超过阈值
+
+        --------------输入参数--------------:
+        time_diff_thre: 时间差阈值
+        odo_sum_thre: 累积里程阈值
+        drive_spd_thre: 行车车速阈值
+        parking_spd_thre: 非行车状态车速阈值
+
+        --------------输出参数--------------:
+        df_bms 增加一列gps_rely, 表明对应的GPS数据是否可靠。
+                1:可靠
+                <0: 表示不可靠的原因
+        df_gps 增加两列odo, speed, 分别表示前后两点间的距离和速度
+        '''
+        df_gps['时间戳'] = pd.to_datetime(df_gps['时间戳'])
+        res_record = {'drive':0, 'charge':0, 'stand':0, 'none':0, 'total':0}
+        rely_list = []
+        df_gps['odo'] = [None] * len(df_gps)
+        df_gps['speed'] = [None] * len(df_gps)
+        data_number_list = sorted(list(set(df_bms['data_split_by_status_time'])))
+        for data_number in data_number_list[:]:
+            df_sel = df_bms[df_bms['data_split_by_status_time'] == data_number]
+            df_sel = df_sel.reset_index(drop=True)
+            df_sel_gps = df_gps[(df_gps['时间戳']>=df_sel.loc[0,'时间戳']) & (df_gps['时间戳']<=df_sel.loc[len(df_sel)-1,'时间戳'])]
+            origin_index = list(df_sel_gps.index)
+            df_sel_gps = df_sel_gps.reset_index(drop=True)
+            # 如果当前段数据对应的地理位置数据少于2个
+            if len(df_sel_gps) <= 1:
+                rely_list.extend([-1]*len(df_sel))
+                res_record[str(df_sel.loc[0, 'data_status'])] = res_record[str(df_sel.loc[0, 'data_status'])] + 1
+                continue
+            # 如果GPS 起止时间段和BMS数据相差超过阈值
+            if abs(df_sel_gps.loc[0, '时间戳'] - df_sel.loc[0,'时间戳']).total_seconds() > time_diff_thre or \
+               abs(df_sel_gps.loc[len(df_sel_gps)-1, '时间戳'] - df_sel.loc[len(df_sel)-1,'时间戳']).total_seconds() > time_diff_thre:
+                rely_list.extend([-2]*len(df_sel))
+                res_record[str(df_sel.loc[0, 'data_status'])] = res_record[str(df_sel.loc[0, 'data_status'])] + 1
+                continue
+
+            # 计算该段数据每两点之间的里程以及速度
+            dis_array, speed_array = self._cal_odo_speed(df_sel_gps['纬度'], df_sel_gps['经度'], df_sel_gps['时间戳'])
+            # 如果 累积里程异常 或 平均车速异常 或两点间车速异常
+            avg_speed = np.sum(dis_array) *3600.0 / abs(df_sel_gps.loc[0, '时间戳'] - df_sel_gps.loc[len(df_sel_gps)-1, '时间戳']).total_seconds()
+            if np.sum(dis_array) > odo_sum_thre or avg_speed > drive_spd_thre or (speed_array > drive_spd_thre).any():
+                rely_list.extend([-3]*len(df_sel))
+                res_record[str(df_sel.loc[0, 'data_status'])] = res_record[str(df_sel.loc[0, 'data_status'])] + 1
+                continue
+            
+            # 如果停车,且 平均时速超过阈值,则不可靠
+            if (str(df_sel.loc[0, 'data_status']) == 'charge' or str(df_sel.loc[0, 'data_status']) == 'stand') and avg_speed > parking_spd_thre :
+                rely_list.extend([-4]*len(df_sel))
+                res_record[str(df_sel.loc[0, 'data_status'])] = res_record[str(df_sel.loc[0, 'data_status'])] + 1
+                continue
+            # 剩下的记录为可靠
+            rely_list.extend([1]*len(df_sel))
+            df_gps.loc[origin_index[1:], 'odo'] = dis_array
+            df_gps.loc[origin_index[1:], 'speed'] = speed_array
+        df_bms['gps_rely'] = rely_list
+        res_record['total'] = (res_record['drive'] + res_record['charge'] + res_record['stand'] + res_record['none'] )/df_bms['data_split_by_status_time'].max()
+        if len(set(df_bms[df_bms['data_status']=='drive']['data_split_by_status_time'])) > 0:
+            res_record['drive'] = (res_record['drive'])/len(set(df_bms[df_bms['data_status']=='drive']['data_split_by_status_time']))
+        if len(set(df_bms[df_bms['data_status']=='charge']['data_split_by_status_time'])) > 0:
+            res_record['charge'] = (res_record['charge'])/len(set(df_bms[df_bms['data_status']=='charge']['data_split_by_status_time']))
+        if len(set(df_bms[df_bms['data_status']=='stand']['data_split_by_status_time'])) > 0:
+            res_record['stand'] = (res_record['stand'])/len(set(df_bms[df_bms['data_status']=='stand']['data_split_by_status_time']))
+        if len(set(df_bms[df_bms['data_status']=='none']['data_split_by_status_time'])) > 0:
+            res_record['none'] = (res_record['none'])/len(set(df_bms[df_bms['data_status']=='none']['data_split_by_status_time']))
+        return df_bms, df_gps, res_record
+
+
+    def data_gps_judge_after_combine(self, df_bms, df_gps, time_diff_thre=600, odo_sum_thre=200, drive_spd_thre=80, parking_spd_thre=2):
+        '''
+        GPS数据可靠性判断函数2 (基于combine后的分段) 判别方式同data_gps_judge
+        '''
+        df_gps['时间戳'] = pd.to_datetime(df_gps['时间戳'])
+        res_record = {'not charge':0, 'charge':0, 'total':0} # 不可靠的比例
+
+        rely_list = []
+        df_gps['odo_after_combine'] = [None] * len(df_gps)
+        df_gps['speed_after_combine'] = [None] * len(df_gps)
+ 
+        data_number_list = sorted(list(set(df_bms['data_split_by_status_after_combine'])))
+        for data_number in data_number_list[:]:
+            df_sel = df_bms[df_bms['data_split_by_status_after_combine'] == data_number]
+            df_sel = df_sel.reset_index(drop=True)
+
+            # 尝试采用drive段的开始和结束时间选择GPS数据,因为stand时GPS数据可能存在丢失,影响里程的计算
+            df_sel_drive = df_sel[df_sel['data_status']=='drive'] # 
+            df_sel_drive = df_sel_drive.reset_index(drop=True)
+            if df_sel_drive.empty:
+                df_sel_1 = df_sel
+            else:
+                df_sel_1 = df_sel_drive
+            df_sel_gps = df_gps[(df_gps['时间戳']>=df_sel_1.loc[0,'时间戳']) & (df_gps['时间戳']<=df_sel_1.loc[len(df_sel_1)-1,'时间戳'])]
+            origin_index = list(df_sel_gps.index)
+            df_sel_gps = df_sel_gps.reset_index(drop=True)
+            # 如果当前段数据对应的地理位置数据少于2个
+            if len(df_sel_gps) <= 1:
+                rely_list.extend([-1]*len(df_sel))
+                res_record[str(df_sel.loc[0, 'data_status_after_combine'])] = res_record[str(df_sel.loc[0, 'data_status_after_combine'])] + 1
+                continue
+            # 如果GPS 起止时间段和BMS数据相差超过阈值
+            if abs(df_sel_gps.loc[0, '时间戳'] - df_sel_1.loc[0,'时间戳']).total_seconds() > time_diff_thre or \
+                abs(df_sel_gps.loc[len(df_sel_gps)-1, '时间戳'] - df_sel_1.loc[len(df_sel_1)-1,'时间戳']).total_seconds() > time_diff_thre:
+                rely_list.extend([-2]*len(df_sel))
+                res_record[str(df_sel.loc[0, 'data_status_after_combine'])] = res_record[str(df_sel.loc[0, 'data_status_after_combine'])] + 1
+                continue
+
+            # 计算该段数据每两点之间的里程以及速度
+            dis_array, speed_array = self._cal_odo_speed(df_sel_gps['纬度'], df_sel_gps['经度'], df_sel_gps['时间戳'])
+            # 如果 累积里程异常 或 平均车速异常 或两点间车速异常
+            avg_speed = np.sum(dis_array) *3600.0 / abs(df_sel_gps.loc[0, '时间戳'] - df_sel_gps.loc[len(df_sel_gps)-1, '时间戳']).total_seconds()
+            if np.sum(dis_array) > odo_sum_thre or avg_speed > drive_spd_thre or (speed_array > drive_spd_thre).any():
+                rely_list.extend([-3]*len(df_sel))
+                res_record[str(df_sel.loc[0, 'data_status_after_combine'])] = res_record[str(df_sel.loc[0, 'data_status_after_combine'])] + 1
+                continue
+            
+            # 如果充电,且 平均时速超过阈值,则不可靠
+            if str(df_sel.loc[0, 'data_status_after_combine']) == 'charge' and avg_speed > parking_spd_thre:
+                rely_list.extend([-4]*len(df_sel))
+                res_record[str(df_sel.loc[0, 'data_status_after_combine'])] = res_record[str(df_sel.loc[0, 'data_status_after_combine'])] + 1
+                continue
+            # 剩下的记录为可靠
+            rely_list.extend([1]*len(df_sel))
+            df_gps.loc[origin_index[1:], 'odo_after_combine'] = dis_array
+            df_gps.loc[origin_index[1:], 'speed_after_combine'] = speed_array
+        df_bms['gps_rely_after_combine'] = rely_list
+        res_record['total'] = (res_record['not charge'] + res_record['charge'])/df_bms['data_split_by_status_after_combine'].max()
+        if len(set(df_bms[df_bms['data_status_after_combine']=='not charge']['data_split_by_status_after_combine'])) > 0:
+            res_record['not charge'] = (res_record['not charge'])/len(set(df_bms[df_bms['data_status_after_combine']=='not charge']['data_split_by_status_after_combine']))
+        if len(set(df_bms[df_bms['data_status_after_combine']=='charge']['data_split_by_status_after_combine'])) > 0 :
+            res_record['charge'] = (res_record['charge'])/len(set(df_bms[df_bms['data_status_after_combine']=='charge']['data_split_by_status_after_combine']))
+        return df_bms, df_gps, res_record
+        

+ 47 - 0
LIB/BACKEND/Log.py

@@ -0,0 +1,47 @@
+'''
+Log类
+
+'''
+__author__ = 'Wang Liming'
+
+
+import logging
+import os
+
+class Mylog:
+
+    def __init__(self, log_name='this_log', log_level = ''):
+        self.logger = logging.getLogger(log_name)
+        self._set_log_level(logging.INFO)
+        if len(log_level) > 0:
+            self._set_log_level(log_level)
+
+    def get_logger(self):
+        return self.logger
+    
+    def set_file_hl(self, file_name='all.log', log_level='info'):
+        fh = logging.FileHandler(filename=file_name)
+        fh_formatter = logging.Formatter('%(asctime)s:%(created)f:%(name)s:%(module)s:%(funcName)s:%(levelname)s:%(message)s')
+        fh.setFormatter(fh_formatter)
+        if len(log_level) > 0:
+            self._set_log_level(log_level)
+        self.logger.addHandler(fh)
+
+    def set_stream_hl(self, log_level='info'):
+        sh = logging.StreamHandler()
+        sh_formatter = logging.Formatter('%(asctime)s:%(created)f:%(name)s:%(module)s:%(funcName)s:%(levelname)s:%(message)s')
+        sh.setFormatter(sh_formatter)
+        if len(log_level) > 0:
+            self._set_log_level(log_level)
+        self.logger.addHandler(sh)  
+
+    def _set_log_level(self, log_level):
+        if log_level == 'debug':
+            self.logger.setLevel(logging.DEBUG)
+        if log_level == 'info':
+            self.logger.setLevel(logging.INFO)
+        if log_level == 'warning':
+            self.logger.setLevel(logging.WARNING)
+        if log_level == 'error':
+            self.logger.setLevel(logging.ERROR)
+

+ 73 - 0
LIB/BACKEND/Tools.py

@@ -0,0 +1,73 @@
+'''
+工具类
+
+'''
+__author__ = 'Wang Liming'
+
+
+import CONFIGURE.PathSetting as PathSetting
+import sys
+sys.path.append(PathSetting.backend_path)
+import DBManager
+import pandas as pd
+import numpy as np
+import math
+from numba import jit
+import os
+import datetime
+import pdb
+import warnings
+warnings.filterwarnings('ignore')
+
+class Tools():
+
+    def __init__(self):
+        pass
+
+    # 数据下载
+    def data_download(self, write_path='', sn='', start_time='', end_time='', data_groups=['bms', 'gps']):
+        '''
+        数据下载函数
+        --------------输入参数------------
+        write_path: 文件保存路径,不需要指定文件名
+        sn: str, 电池sn号
+        start_time: str, 开始时间
+        end_time: str, 结束时间
+        gps_switch: True:获取gps数据; False:不获取gps数据
+        mode: 0:正常取数; 1:7255 取数
+
+        --------------输出参数------------
+        bms_data: 获取到的bms数据
+        gps_data: 获取到的gps数据
+        '''
+        dbManager = DBManager.DBManager()
+        print('downloading......')
+        df_data = dbManager.get_data(sn=sn, start_time=start_time, end_time=end_time, data_groups=data_groups)
+        for data_group in data_groups:
+            df_data[data_group].to_csv(os.path.join(write_path, '{}_{}_from_{}_to_{}.csv'.format(data_group, sn, start_time[0:10], end_time[0:10])), index=False, encoding='GB2312')
+        print('downloading success!')
+
+    # 根据经纬度计算距离
+    @jit
+    def cal_distance(self, latitude1, longitude1,latitude2, longitude2,radius=6371):  
+        '''
+        输入两个地点的经纬度,输出两点间的距离
+        '''
+        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
+
+    # 输入GPS数据, 返回本段数据中GPS 位置相距最远的距离
+    # @jit
+    # def cal_max_dis(self, lat, long):
+    #     count = len(lat)
+    #     dis_mat=np.zeros([count,count])
+    #     for i in range(count):
+    #         for j in range(i,count):
+    #             dis_mat[i][j]=self.cal_distance(lat[i],long[i], lat[j],long[j])
+                
+    #     max_dis = dis_mat.max()
+    #     return max_dis

+ 102 - 0
LIB/FRONTEND/SignalMonitor/create_table.py

@@ -0,0 +1,102 @@
+'''
+定义表的结构,并在数据库中创建对应的数据表
+'''
+__author__ = 'Wang Liming'
+
+from sqlalchemy.ext.declarative import declarative_base
+from sqlalchemy import Column, String, create_engine, Integer, DateTime, BigInteger, FLOAT
+
+Base = declarative_base()
+
+
+class BmsLastDataDay(Base):
+    __tablename__ = "bms_last_data_day"
+    __table_args__ = ({'comment': '电池信号监控---每天最后一条bms数据'})  # 添加索引和表注释
+
+    id = Column(Integer, primary_key=True, autoincrement=True, comment="主键")
+    sn = Column(String(64), comment="sn")
+    current = Column(FLOAT, comment="电流")
+    time_stamp = Column(Integer, comment="时间戳")
+    pack_state = Column(Integer, comment="电池状态")
+    line_state = Column(Integer, comment="信号状态")
+
+
+    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
+
+class GpsLastDataDay(Base):
+    __tablename__ = "gps_last_data_day"
+    __table_args__ = ({'comment': '电池信号监控---每天最后一条gps数据'})  # 添加索引和表注释
+
+    id = Column(Integer, primary_key=True, autoincrement=True, comment="主键")
+    sn = Column(String(64), comment="sn")
+    time_stamp = Column(Integer, comment="时间戳")
+    pack_state = Column(Integer, comment="电池状态")
+    line_state = Column(Integer, comment="信号状态")
+
+
+    def __init__(self, sn, time_stamp, pack_state, line_state):
+        self.sn = sn
+        self.time_stamp = time_stamp
+        self.pack_state = pack_state
+        self.line_state = line_state
+
+class GpsSignalMonitor(Base):
+    __tablename__ = "gps_signal_monitor"
+    __table_args__ = ({'comment': 'gps信号监控'})  # 添加索引和表注释
+
+    id = Column(Integer, primary_key=True, autoincrement=True, comment="主键")
+    sn = Column(String(64), comment="sn")
+    start_time = Column(DateTime, comment="开始时间")
+    end_time = Column(DateTime, comment="结束时间")
+    offline_time = Column(DateTime, comment="离线时间")
+    pack_state = Column(Integer, comment="电池状态")
+    line_state = Column(Integer, comment="信号状态")
+
+
+    def __init__(self, sn, start_time, end_time, off_line_time, pack_state, line_state):
+        self.sn = sn
+        self.start_time = start_time
+        self.end_time = end_time
+        self.off_line_time = off_line_time
+        self.pack_state = pack_state
+        self.line_state = line_state
+
+class BmsSignalMonitor(Base):
+    __tablename__ = "bms_signal_monitor"
+    __table_args__ = ({'comment': 'bms信号监控'})  # 添加索引和表注释
+
+    id = Column(Integer, primary_key=True, autoincrement=True, comment="主键")
+    sn = Column(String(64), comment="sn")
+    start_time = Column(DateTime, comment="开始时间")
+    end_time = Column(DateTime, comment="结束时间")
+    offline_time = Column(DateTime, comment="离线时间")
+    pack_state = Column(Integer, comment="电池状态")
+    line_state = Column(Integer, comment="信号状态")
+
+
+    def __init__(self, sn, start_time, end_time, off_line_time, pack_state, line_state):
+        self.sn = sn
+        self.start_time = start_time
+        self.end_time = end_time
+        self.off_line_time = off_line_time
+        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 = '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)

+ 95 - 0
LIB/FRONTEND/SignalMonitor/main.py

@@ -0,0 +1,95 @@
+#coding=utf-8
+import os
+import datetime
+import pandas as pd
+from LIB.BACKEND import DBManager, Log
+from LIB.MIDDLE import SignalMonitor
+from sqlalchemy import create_engine
+from sqlalchemy.orm import sessionmaker
+import time, datetime
+import traceback
+
+dbManager = DBManager.DBManager()
+if __name__ == "__main__":
+    try:
+        # 数据库配置
+        host = 'rm-bp10j10qy42bzy0q77o.mysql.rds.aliyuncs.com'
+        port = 3306
+        user = 'qx_cas'
+        password = 'Qx@123456'
+        database = 'qx_cas'
+
+        db_engine = create_engine(
+            "mysql+pymysql://{}:{}@{}:{}/{}?charset=utf8".format(
+                user, password, host, port, database
+            ))
+
+        db_engine = create_engine("mysql+pymysql://qx_cas:Qx@123456@rm-bp10j10qy42bzy0q77o.mysql.rds.aliyuncs.com/qx_cas?charset=utf8")
+        DbSession = sessionmaker(bind=db_engine)
+        
+        # 日志配置
+        log = Log.Mylog(log_name='signal_monitor', log_level = 'info')
+        log.set_file_hl(file_name='info.log', log_level='info')
+        log.set_file_hl(file_name='error.log', log_level='error')
+        logger = log.get_logger()
+
+        logger.info("pid is + {}".format(os.getpid))
+
+        # 读取sn列表
+        df_sn = pd.read_csv('sn_list.csv')
+        df_sn = df_sn.reset_index(drop=True)
+        df_sn['StartTime'] = pd.to_datetime(df_sn['StartTime'])
+        df_sn['EndTime'] = pd.to_datetime(df_sn['EndTime'])
+        df_sn['ExitTime'] = pd.to_datetime(df_sn['ExitTime'])
+        signalMonitor = SignalMonitor.SignalMonitor()
+        
+        cal_period = 24    # 计算间隔,单位h
+        for i in range(0, len(df_sn['sn'])):    # 遍历SN号
+            sn = [df_sn.loc[i,'sn']]
+            if not (sn[0][0:2] == 'PK' or sn[0][0:2] == 'MG' or sn[0][0:2] == 'UD'):
+                continue
+            st = df_sn.loc[i, 'StartTime']
+            if df_sn.loc[i, 'Service'] == 0:
+                et = df_sn.loc[i, 'ExitTime']
+            elif pd.isnull(df_sn.loc[i, 'EndTime']):
+                otherStyleTime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time()))
+                et = pd.to_datetime(otherStyleTime)
+            else:
+                et = df_sn.loc[i, 'EndTime']
+            df_last_state = pd.DataFrame(
+                columns=['sn', 'current', 'Timestamp', 'PackState', 'LineState'])    # 每日最后BMS数据
+            df_last_state_gps = pd.DataFrame(
+                columns=['sn', 'Timestamp', 'PackState', 'LineState'])    # 每日最后GPS数据
+            while st < et:
+                df_res = pd.DataFrame(columns=[
+                                    'sn', 'PackState', 'LineState', 'StartTime', 'EndTime', 'OfflineTime'])    # 初始化BMS信号统计数据
+                df_res_gps = pd.DataFrame(columns=[
+                                        'sn', 'PackState', 'LineState', 'StartTime', 'EndTime', 'OfflineTime'])    # 初始化GPS信号统计数据
+                df_res, df_state, df_last_state = signalMonitor.get_bms_offline_stat(
+                    sn, st, et, df_res, df_last_state, cal_period)    # 计算每日BMS信号统计数据
+                df_res_gps, df_last_state_gps = signalMonitor.get_gps_offline_stat(
+                    sn, st, et, df_state, df_res_gps, df_last_state_gps, cal_period)    # 计算每日GPS信号统计数据
+            
+                # 数据入库
+                df_tosql = df_res_gps.copy()
+                df_tosql.columns = ['sn', 'pack_state', 'line_state', 'start_time', 'end_time', 'offline_time']
+                df_tosql.loc[df_tosql.index[-1:]].to_sql("gps_signal_monitor",con=db_engine, if_exists="append",index=False)
+
+                df_tosql = df_res.copy()
+                df_tosql.columns = ['sn', 'pack_state', 'line_state', 'start_time', 'end_time', 'offline_time']
+                df_tosql.loc[df_res.index[-1:]].to_sql("bms_signal_monitor",con=db_engine, if_exists="append",index=False)
+                st = st + datetime.timedelta(hours=cal_period)
+
+            # 数据入库
+            df_tosql = df_last_state.copy()
+            df_tosql.columns = ['sn', 'current', 'time_stamp', 'pack_state', 'line_state']
+            df_tosql.to_sql("bms_last_data_day",con=db_engine, if_exists="append",index=False)
+
+            df_tosql = df_last_state.copy()
+            df_tosql.columns = ['sn', 'time_stamp', 'pack_state', 'line_state']
+            df_tosql.to_sql("gps_last_data_day",con=db_engine, if_exists="append",index=False)
+
+            logger.info("{} {} Success!".format(sn, str(st)))
+    except Exception as e:
+        logger.error(traceback.format_exc)
+        logger.error(u"任务运行错误", exc_info=True)

+ 1655 - 0
LIB/FRONTEND/SignalMonitor/sn_list.csv

@@ -0,0 +1,1655 @@
+,sn,StartTime,EndTime,Service,ExitTime
+2,GY606000000000001,2021/4/6 18:41,2021/5/25 16:03,1,
+5,MGMCLN750N215H001,2021/5/23 17:16,,1,
+6,MGMCLN750N215H002,2021/5/23 16:16,2021/7/19 10:19,1,
+7,MGMCLN750N215H004,2021/6/19 11:18,,1,
+8,MGMCLN750N215H005,2021/6/15 11:05,,1,
+9,MGMCLN750N215H006,2021/6/7 18:24,2021/7/15 17:22,1,
+10,MGMCLN750N215H007,2021/6/2 10:07,2021/6/3 14:49,0,2021/7/27
+11,MGMCLN750N215H008,2021/5/28 14:50,,1,
+12,MGMCLN750N215H009,2021/6/17 9:06,,1,
+13,MGMCLN750N215H011,2021/7/19 19:15,,1,
+14,MGMCLN750N215H013,2021/5/25 18:10,,1,
+15,MGMCLN750N215H014,2021/6/4 15:51,,1,
+16,MGMCLN750N215H015,2021/6/4 20:41,2021/6/25 12:11,1,
+17,MGMCLN750N215H016,2021/6/2 15:21,,1,
+18,MGMCLN750N215I001,2021/5/25 19:26,,1,
+19,MGMCLN750N215I002,2021/6/26 11:45,,1,
+20,MGMCLN750N215I003,2021/6/2 15:38,,1,
+21,MGMCLN750N215I004,2021/6/4 15:34,,1,
+22,MGMCLN750N215I005,2021/6/12 20:34,2021/7/12 16:09,1,
+23,MGMCLN750N215I006,2021/7/23 15:44,,1,
+24,MGMCLN750N215I007,2021/6/23 13:29,2021/7/25 12:38,1,
+25,MGMCLN750N215I008,2021/6/19 16:53,,1,
+26,MGMCLN750N215I009,2021/6/26 21:01,,1,
+27,MGMCLN750N215I010,2021/5/24 17:01,,1,
+28,MGMCLN750N215I012,2021/7/3 13:13,,1,
+29,MGMCLN750N215I013,2021/6/29 10:04,,1,
+30,MGMCLN750N215I014,2021/5/28 13:34,,1,
+31,MGMCLN750N215I015,2021/6/30 15:14,,1,
+32,MGMCLN750N215I016,2021/5/28 22:06,2021/7/14 9:39,1,
+33,MGMCLN750N215I017,2021/6/23 16:54,2021/7/23 17:34,1,
+34,MGMCLN750N215I018,2021/5/26 20:15,2021/6/4 9:59,1,
+35,MGMCLN750N215I019,2021/5/23 14:31,,1,
+36,MGMCLN750N215I020,2021/6/2 12:02,2021/6/22 19:07,1,
+37,MGMCLN750N215I022,2021/5/23 15:09,,1,
+38,MGMCLN750N215I023,2021/6/28 19:26,,1,
+39,MGMCLN750N215I024,2021/7/25 14:51,,1,
+40,MGMCLN750N215I025,2021/6/4 9:00,,1,
+41,MGMCLN750N215I026,2021/5/31 19:16,,1,
+42,MGMCLN750N215I027,2021/6/9 12:00,2021/7/19 17:18,1,
+43,MGMCLN750N215I028,2021/6/4 9:22,,1,
+44,MGMCLN750N215I029,2021/5/24 17:32,,1,
+45,MGMCLN750N215I030,2021/6/9 11:31,2021/6/9 12:00,1,
+46,MGMCLN750N215I031,2021/7/2 16:05,,1,
+47,MGMCLN750N215I032,2021/6/10 13:57,2021/7/23 18:07,1,
+48,MGMCLN750N215I033,2021/6/2 9:42,,1,
+49,MGMCLN750N215I035,2021/6/9 8:29,,1,
+50,MGMCLN750N215I036,2021/6/22 13:02,,1,
+51,MGMCLN750N215I037,2021/7/18 22:02,,1,
+52,MGMCLN750N215I038,2021/6/11 8:29,,1,
+53,MGMCLN750N215I040,2021/7/2 15:59,,1,
+54,MGMCLN750N215I041,2021/6/2 13:47,,1,
+55,MGMCLN750N215I043,2021/6/27 18:17,,1,
+56,MGMCLN750N215I044,2021/6/21 16:37,,1,
+57,MGMCLN750N215I045,2021/6/15 9:29,2021/6/15 9:53,1,
+58,MGMCLN750N215I046,2021/6/4 9:59,2021/6/29 20:57,1,
+59,MGMCLN750N215I048,2021/7/6 8:43,,1,
+60,MGMCLN750N215I049,2021/6/27 15:55,,1,
+61,MGMCLN750N215I050,2021/6/26 12:48,,1,
+62,MGMCLN750N215I051,2021/6/3 13:31,,1,
+63,MGMCLN750N215I052,2021/7/23 18:46,,1,
+64,MGMCLN750N215I053,2021/6/23 19:28,2021/7/23 18:07,1,
+65,MGMCLN750N215I054,2021/6/23 9:44,2021/6/26 17:57,1,
+66,MGMCLN750N215I055,2021/6/3 11:37,,1,
+67,MGMCLN750N215I058,2021/6/1 10:30,,1,
+68,MGMCLN750N215I059,2021/7/5 12:06,,1,
+69,MGMCLN750N215I061,2021/6/20 20:39,,1,
+70,MGMCLN750N215I062,2021/5/29 18:57,2021/6/29 12:13,1,
+71,MGMCLN750N215I064,2021/5/28 23:45,2021/5/29 20:03,0,2021/7/27
+72,MGMCLN750N215I065,2021/6/25 13:32,,1,
+73,MGMCLN750N215I066,2021/6/16 17:47,2021/7/13 17:00,1,
+74,MGMCLN750N215I067,2021/6/15 20:10,,1,
+75,MGMCLN750N215I068,2021/6/3 20:48,,1,
+76,MGMCLN750N215I069,2021/7/4 15:51,,1,
+77,MGMCLN750N215I071,2021/6/15 12:56,2021/7/21 15:15,1,
+78,MGMCLN750N215I072,2021/7/7 18:09,2021/7/8 19:02,1,
+79,MGMCLN750N215I074,2021/7/7 14:55,2021/7/8 9:04,1,
+80,MGMCLN750N215I075,2021/7/3 18:44,,1,
+81,MGMCLN750N215I076,2021/7/7 18:28,2021/7/8 18:36,1,
+82,MGMCLN750N215I077,2021/5/26 10:20,,1,
+83,MGMCLN750N215I078,2021/6/21 19:44,2021/7/18 22:02,1,
+84,MGMCLN750N215I079,2021/5/28 18:08,,1,
+85,MGMCLN750N215I081,2021/6/8 18:15,2021/7/3 15:13,1,
+86,MGMCLN750N215I082,2021/7/1 12:03,,1,
+87,MGMCLN750N215I083,2021/5/27 10:54,,1,
+88,MGMCLN750N215I084,2021/5/29 16:34,2021/6/21 20:55,1,
+89,MGMCLN750N215I085,2021/6/3 16:59,2021/6/27 18:17,1,
+90,MGMCLN750N215I086,2021/6/24 14:52,2021/6/29 13:59,1,
+91,MGMCLN750N215I087,2021/7/4 17:46,,1,
+92,MGMCLN750N215I088,2021/6/22 21:15,2021/7/23 9:44,1,
+93,MGMCLN750N215I089,2021/6/12 16:54,,1,
+94,MGMCLN750N215I090,2021/7/16 12:22,,1,
+95,MGMCLN750N215I091,2021/6/22 22:05,2021/7/22 14:08,1,
+96,MGMCLN750N215I092,2021/7/22 14:48,,1,
+97,MGMCLN750N215I093,2021/7/13 9:01,,1,
+98,MGMCLN750N215I094,2021/7/22 14:03,2021/7/22 14:46,1,
+99,MGMCLN750N215I095,2021/6/29 13:55,,1,
+100,MGMCLN750N215I096,2021/7/7 14:02,,1,
+101,MGMCLN750N215I097,2021/7/19 11:28,,1,
+102,MGMCLN750N215I099,2021/6/23 18:25,2021/7/13 16:18,1,
+103,MGMCLN750N215I102,2021/7/23 21:37,,1,
+104,MGMCLN750N215I104,2021/7/20 19:43,,1,
+105,MGMCLN750N215I105,2021/6/1 18:46,,1,
+106,MGMCLN750N215I106,2021/6/9 19:21,,1,
+107,MGMCLN750N215I108,2021/5/29 17:44,2021/6/27 10:48,1,
+108,MGMCLN750N215I110,2021/5/26 11:28,,1,
+109,MGMCLN750N215I113,2021/5/31 20:44,2021/6/9 13:29,0,2021/6/22
+110,MGMCLN750N215I114,2021/6/20 17:29,,1,
+111,MGMCLN750N215I115,2021/6/30 14:14,,1,
+112,MGMCLN750N215I116,2021/6/15 21:57,,1,
+113,MGMCLN750N215I117,2021/6/26 17:57,2021/6/29 15:57,1,
+114,MGMCLN750N215I118,2021/7/24 9:28,,1,
+115,MGMCLN750N215I119,2021/5/29 21:25,,1,
+116,MGMCLN750N215I120,2021/6/23 16:07,,1,
+117,MGMCLN750N215I122,2021/6/7 15:18,,1,
+118,MGMCLN750N215I123,2021/7/22 13:58,,1,
+119,MGMCLN750N215I125,2021/6/23 14:43,2021/6/27 13:54,1,
+120,MGMCLN750N215I127,2021/5/26 10:35,,1,
+121,MGMCLN750N215I128,2021/6/24 13:20,,1,
+122,MGMCLN750N215I129,2021/6/25 15:43,,1,
+123,MGMCLN750N215I130,2021/5/27 14:40,,1,
+124,MGMCLN750N215I131,2021/6/13 20:56,2021/7/8 11:55,1,
+125,MGMCLN750N215I132,2021/6/27 13:54,,1,
+126,MGMCLN750N215I133,2021/6/30 14:46,,1,
+127,MGMCLN750N215I134,2021/7/9 14:17,,1,
+128,MGMCLN750N215L001,2021/6/25 19:38,,1,
+129,MGMCLN750N215L002,2021/6/24 18:24,,1,
+130,MGMCLN750N215L005,2021/5/30 15:21,,1,
+131,MGMCLN750N215L006,2021/5/30 15:17,,1,
+132,MGMCLN750N215L007,2021/7/21 18:30,2021/7/23 19:53,1,
+133,MGMCLN750N215L008,2021/7/7 12:33,,1,
+134,MGMCLN750N215N001,2021/6/8 21:28,,1,
+135,MGMCLN750N215N002,2021/6/14 19:54,,1,
+136,MGMCLN750N215N003,2021/6/19 12:20,,1,
+137,MGMCLN750N215N004,2021/7/4 19:30,,1,
+138,MGMCLN750N215N005,2021/6/14 14:54,,1,
+139,MGMCLN750N215N006,2021/6/9 21:33,2021/6/14 14:54,1,
+140,MGMCLN750N215N008,2021/6/7 16:05,2021/7/6 18:22,1,
+141,MGMCLN750N215N009,2021/6/18 20:52,,1,
+142,MGMCLN750N215N010,2021/6/12 17:07,2021/7/10 18:15,1,
+143,MGMCLN750N215N011,2021/7/2 13:50,,1,
+144,MGMCLN750N215N013,2021/7/15 11:14,2021/7/23 14:40,1,
+145,MGMCLN750N215N015,2021/7/15 15:35,,1,
+146,MGMCLN750N215N016,2021/6/8 14:10,2021/6/10 12:40,1,
+147,MGMCLN750N215N017,2021/6/22 7:37,,1,
+148,MGMCLN750N215N018,2021/6/21 15:37,,1,
+149,MGMCLN750N215N019,2021/6/24 16:16,2021/7/24 16:14,1,
+150,MGMCLN750N215N020,2021/6/21 14:12,,1,
+151,MGMCLN750N215N021,2021/6/27 17:01,,1,
+152,MGMCLN750N215N022,2021/6/30 19:12,,1,
+153,MGMCLN750N215N023,2021/6/10 19:55,,1,
+154,MGMCLN750N215N024,2021/6/5 19:16,2021/7/6 12:36,1,
+155,MGMCLN750N215N025,2021/6/12 19:51,2021/6/26 20:15,1,
+156,MGMCLN750N215N026,2021/7/19 20:14,,1,
+157,MGMCLN750N215N027,2021/6/9 13:29,,1,
+158,MGMCLN750N215N028,2021/6/2 9:26,,1,
+159,MGMCLN750N215N030,2021/6/1 18:07,2021/7/1 8:50,1,
+160,MGMCLN750N215N031,2021/6/23 15:02,,1,
+161,MGMCLN750N215N032,2021/6/11 8:31,,1,
+162,MGMCLN750N215N033,2021/5/31 18:18,2021/7/5 20:37,1,
+163,MGMCLN750N215N034,2021/7/15 16:46,,1,
+164,MGMCLN750N215N035,2021/7/18 16:09,,1,
+165,MGMCLN750N215N037,2021/6/1 14:36,2021/6/30 14:51,1,
+166,MGMCLN750N215N038,2021/5/30 11:37,,1,
+167,MGMCLN750N215N039,2021/6/6 17:12,,1,
+168,MGMCLN750N215N040,2021/6/22 10:18,2021/6/26 15:55,1,
+169,MGMCLN750N215N041,2021/6/24 20:38,,1,
+170,MGMCLN750N215N042,2021/7/4 10:07,,1,
+171,MGMCLN750N215N043,2021/6/17 15:43,2021/7/19 19:50,0,2021/7/27
+172,MGMCLN750N215N044,2021/7/4 16:47,,1,
+173,MGMCLN750N215N045,2021/7/19 11:47,,1,
+174,MGMCLN750N215N046,2021/6/25 20:43,,1,
+175,MGMCLN750N215N047,2021/7/16 16:00,,1,
+176,MGMCLN750N215N048,2021/6/1 17:58,,1,
+177,MGMCLN750N215N049,2021/6/24 9:54,2021/7/15 11:14,1,
+178,MGMCLN750N215N051,2021/6/13 16:46,2021/7/13 13:39,1,
+179,MGMCLN750N215N052,2021/6/17 12:00,,1,
+180,MGMCLN750N215N053,2021/7/2 13:55,,1,
+181,MGMCLN750N215N054,2021/7/1 10:01,,1,
+182,MGMCLN750N215N055,2021/6/25 21:01,,1,
+183,MGMCLN750N215N056,2021/6/23 13:58,2021/7/10 10:06,1,
+184,MGMCLN750N215N057,2021/6/9 10:41,,1,
+185,MGMCLN750N215N058,2021/6/21 14:12,,1,
+186,MGMCLN750N215N059,2021/7/19 19:50,,1,
+187,MGMCLN750N215N060,2021/6/23 13:57,2021/7/23 8:42,1,
+188,MGMCLN750N215N062,2021/6/29 14:23,,1,
+189,MGMCLN750N215N063,2021/7/14 23:13,,1,
+190,MGMCLN750N215N064,2021/6/17 15:22,,1,
+191,MGMCLN750N215N065,2021/7/22 8:36,,1,
+192,MGMCLN750N215N066,2021/6/7 20:46,,1,
+193,MGMCLN750N215N067,2021/7/23 14:10,,1,
+194,MGMCLN750N215N069,2021/6/1 9:01,,1,
+195,MGMCLN750N215N070,2021/6/10 8:14,,1,
+196,MGMCLN750N215N071,2021/5/30 14:08,,1,
+197,MGMCLN750N215N072,2021/7/14 17:18,,1,
+198,MGMCLN750N215N074,2021/6/2 10:53,,1,
+199,MGMCLN750N215N075,2021/6/19 14:12,2021/7/7 13:55,0,2021/7/27
+200,MGMCLN750N215N076,2021/6/21 18:31,,1,
+201,MGMCLN750N215N077,2021/6/13 19:17,,1,
+202,MGMCLN750N215N078,2021/7/1 14:58,,1,
+203,MGMCLN750N215N079,2021/6/8 16:58,,1,
+204,MGMCLN750N215N081,2021/7/2 13:52,,1,
+205,MGMCLN750N215N082,2021/7/19 17:34,2021/7/19 17:57,1,
+206,MGMCLN750N215N083,2021/6/18 15:15,,1,
+207,MGMCLN750N215N084,2021/6/2 12:59,2021/7/1 8:52,1,
+208,MGMCLN750N215N085,2021/7/3 19:52,2021/7/17 13:45,1,
+209,MGMCLN750N215N086,2021/6/16 14:54,,1,
+210,MGMCLN750N215N087,2021/6/8 18:55,2021/7/24 20:51,1,
+211,MGMCLN750N215N088,2021/6/2 13:44,,1,
+212,MGMCLN750N215N089,2021/5/30 10:04,,1,
+213,MGMCLN750N215N090,2021/6/1 14:33,2021/6/19 15:27,1,
+214,MGMCLN750N215N091,2021/7/18 15:54,,1,
+215,MGMCLN750N215N092,2021/6/10 12:31,,1,
+216,MGMCLN750N215N093,2021/6/24 15:46,,1,
+217,MGMCLN750N215N094,2021/6/4 15:07,2021/6/30 7:32,1,
+218,MGMCLN750N215N096,2021/6/23 17:31,,1,
+219,MGMCLN750N215N097,2021/7/23 10:48,2021/7/23 12:05,1,
+220,MGMCLN750N215N098,2021/6/17 10:24,,1,
+221,MGMCLN750N215N099,2021/6/23 9:08,,1,
+222,MGMCLN750N215N100,2021/7/18 10:06,,1,
+223,MGMCLN750N215N101,2021/7/1 9:11,,1,
+224,MGMCLN750N215N102,2021/6/27 13:41,,1,
+225,MGMCLN750N215N103,2021/6/2 17:08,,1,
+226,MGMCLN750N215N104,2021/6/23 13:34,,1,
+227,MGMCLN750N215N106,2021/7/23 19:53,,1,
+228,MGMCLN750N215N107,2021/6/22 20:34,,1,
+229,MGMCLN750N215N108,2021/6/9 14:33,2021/6/22 10:18,0,2021/6/22
+230,MGMCLN750N215N109,2021/6/26 15:55,2021/7/7 15:09,1,
+231,MGMCLN750N215N110,2021/6/1 20:19,2021/6/24 16:08,1,
+232,MGMCLN750N215N111,2021/6/23 16:33,,1,
+233,MGMCLN750N215N113,2021/6/10 13:38,2021/6/21 15:38,1,
+234,MGMCLN750N215N114,2021/6/3 16:41,,1,
+235,MGMCLN750N215N115,2021/6/24 11:52,2021/7/4 14:11,1,
+236,MGMCLN750N215N116,2021/7/8 10:37,,1,
+237,MGMCLN750N215N117,2021/7/2 15:32,,1,
+238,MGMCLN750N215N119,2021/6/24 14:37,,1,
+239,MGMCLN750N215N120,2021/6/16 9:08,2021/6/19 14:12,0,2021/6/22
+240,MGMCLN750N215N121,2021/6/6 11:27,2021/7/5 14:31,1,
+241,MGMCLN750N215N122,2021/7/9 19:09,,1,
+242,MGMCLN750N215N123,2021/7/10 8:57,2021/7/11 14:48,1,
+243,MGMCLN750N215N124,2021/7/11 11:10,,1,
+244,MGMCLN750N215N125,2021/6/22 13:59,,1,
+245,MGMCLN750N215N126,2021/6/5 21:36,2021/7/24 13:11,0,2021/7/27
+246,MGMCLN750N215N128,2021/6/24 15:09,,1,
+247,MGMCLN750N215N129,2021/6/30 10:03,2021/7/6 13:31,0,2021/7/27
+248,MGMCLN750N215N131,2021/7/6 12:12,,1,
+249,MGMCLN750N215N132,2021/6/22 10:17,,1,
+250,MGMCLN750N215N133,2021/7/18 17:38,2021/7/19 23:53,1,
+251,MGMCLN750N215N134,2021/6/25 11:23,2021/7/25 13:13,1,
+252,MGMCLN750N215N135,2021/7/3 19:22,2021/7/7 18:33,0,2021/7/27
+253,MGMCLN750N215N136,2021/6/29 14:27,2021/7/4 20:29,1,
+254,MGMCLN750N215N137,2021/6/23 9:50,,1,
+255,MGMCLN750N215N138,2021/6/23 13:48,2021/7/9 17:37,1,
+256,MGMCLN750N215N139,2021/7/11 9:43,2021/7/15 13:48,1,
+257,MGMCLN750N215N141,2021/7/9 11:04,,1,
+258,MGMCLN750N215N142,2021/7/14 20:03,,1,
+259,MGMCLN750N215N143,2021/6/17 14:15,,1,
+260,MGMCLN750N215N144,2021/7/6 20:05,,1,
+261,MGMCLN750N215N145,2021/6/20 22:58,,1,
+262,MGMCLN750N215N146,2021/7/13 15:32,,1,
+263,MGMCLN750N215N147,2021/6/15 10:27,2021/7/16 15:00,1,
+264,MGMCLN750N215N148,2021/6/25 15:27,,1,
+265,MGMCLN750N215N149,2021/7/4 9:52,,1,
+266,MGMCLN750N215N150,2021/7/6 21:12,,1,
+267,MGMCLN750N215N151,2021/6/20 14:53,,1,
+268,MGMCLN750N215N152,2021/6/25 15:48,,1,
+269,MGMCLN750N215N153,2021/6/23 9:15,,1,
+270,MGMCLN750N215N154,2021/6/18 11:43,,1,
+271,MGMCLN750N215N155,2021/6/23 13:58,2021/7/18 19:42,1,
+272,MGMCLN750N215N156,2021/6/21 18:05,2021/7/1 15:36,0,2021/7/27
+273,MGMCLN750N215N157,2021/6/18 9:11,,1,
+274,MGMCLN750N215N158,2021/6/19 11:33,2021/7/19 9:45,1,
+275,MGMCLN750N215N159,2021/7/8 18:36,,1,
+276,MGMCLN750N215N160,2021/6/24 15:52,2021/7/1 11:52,1,
+277,MGMCLN750N215N161,2021/6/26 10:58,,1,
+278,MGMCLN750N215N162,2021/7/14 14:45,2021/7/18 16:09,1,
+279,MGMCLN750N215N163,2021/6/5 17:06,2021/7/5 18:31,1,
+280,MGMCLN750N215N165,2021/7/8 10:33,2021/7/24 9:30,1,
+281,MGMCLN750N215N167,2021/7/5 10:03,,1,
+282,MGMCLN750N215N169,2021/7/7 9:07,2021/7/11 20:43,1,
+283,MGMCLN750N215N170,2021/7/23 17:20,2021/7/23 17:04,1,
+284,MGMCLN750N215N171,2021/7/18 15:53,,1,
+285,MGMCLN750N215N172,2021/7/23 15:25,,1,
+286,MGMCLN750N215N173,2021/6/30 19:55,,1,
+287,MGMCLN750N215N174,2021/6/3 18:18,,1,
+288,MGMCLN750N215N175,2021/7/23 17:04,2021/7/23 17:20,1,
+289,MGMCLN750N215N176,2021/7/11 14:48,2021/7/24 14:22,1,
+290,MGMCLN750N215N177,2021/7/1 15:28,,1,
+291,MGMCLN750N215N178,2021/7/5 20:37,2021/7/24 17:19,1,
+292,MGMCLN750N215N179,2021/6/27 18:26,2021/7/3 14:58,1,
+293,MGMCLN750N215N180,2021/6/12 13:45,,1,
+294,MGMCLN750N215N181,2021/7/8 12:16,2021/7/18 11:44,1,
+295,MGMCLN750N215N182,2021/7/8 10:06,,1,
+296,MGMCLN750N215N183,2021/7/12 13:57,2021/7/21 14:45,1,
+297,MGMCLN750N215N184,2021/6/26 10:56,,1,
+298,MGMCLN750N215N185,2021/6/24 13:34,,1,
+299,MGMCLN750N215N186,2021/7/10 10:54,,1,
+300,MGMCLN750N215N187,2021/6/19 12:17,,1,
+301,MGMCLN750N215N189,2021/6/5 11:30,,1,
+302,MGMCLN750N215N190,2021/6/22 9:27,,1,
+303,MGMCLN750N215N191,2021/7/13 15:19,2021/7/20 12:48,1,
+304,MGMCLN750N215N192,2021/6/23 9:42,2021/7/12 13:57,1,
+305,MGMCLN750N215N193,2021/7/1 11:57,,1,
+306,MGMCLN750N215N194,2021/6/18 13:21,2021/7/3 19:22,1,
+307,MGMCLN750N215N195,2021/7/2 15:03,,1,
+308,MGMCLN750N215N196,2021/6/15 15:26,,1,
+309,MGMCLN750N215N197,2021/7/2 21:03,,1,
+310,MGMCLN750N215N198,2021/7/8 19:20,,1,
+311,MGMCLN750N215N199,2021/6/28 11:15,,1,
+312,MGMCLN750N215N200,2021/6/23 9:35,2021/6/23 9:42,1,
+313,MGMCLN750N215N201,2021/6/21 18:13,2021/6/23 9:35,1,
+314,MGMCLN750N215N202,2021/7/3 11:06,,1,
+315,MGMCLN750N215N204,2021/7/2 17:02,,1,
+316,MGMCLN750N215N205,2021/6/16 17:46,2021/7/13 17:00,1,
+317,MGMCLN750N215N206,2021/7/3 11:36,,1,
+318,MGMCLN750N215N207,2021/6/29 15:58,,1,
+319,MGMCLN750N215N208,2021/6/17 10:56,,1,
+320,MGMCLN750N215N209,2021/6/21 16:29,,1,
+321,MGMCLN750N215N211,2021/6/16 15:54,,1,
+322,MGMCLN750N215N212,2021/7/1 10:22,,1,
+323,MGMCLN750N215N213,2021/7/22 17:07,,1,
+324,MGMCLN750N215N214,2021/6/20 10:33,2021/7/19 11:57,1,
+325,MGMCLN750N215N215,2021/6/20 11:22,2021/7/12 16:51,0,2021/7/27
+326,MGMCLN750N215N216,2021/7/3 14:58,2021/7/14 17:02,0,2021/7/27
+327,MGMCLN750N215N217,2021/7/7 13:54,,1,
+328,MGMCLN750N215N219,2021/6/29 18:55,2021/7/16 16:03,1,
+329,MGMCLN750N215N220,2021/7/1 11:32,,1,
+330,MGMCLN750N215N222,2021/7/10 10:06,2021/7/24 11:20,1,
+331,MGMCLN750N215N223,2021/6/15 13:33,2021/7/14 18:26,1,
+332,MGMCLN750N215N224,2021/7/3 15:50,,1,
+333,MGMCLN750N215N225,2021/6/20 9:39,,1,
+334,MGMCLN750N215N226,2021/6/29 19:45,2021/7/2 9:52,1,
+335,MGMCLN750N215N227,2021/7/1 11:37,,1,
+336,MGMCLN750N215N228,2021/6/22 11:17,2021/7/18 10:12,1,
+337,MGMCLN750N215N229,2021/7/20 9:39,,1,
+338,MGMCLN750N215N230,2021/6/22 19:26,,1,
+339,MGMCLN750N215N231,2021/7/5 13:19,2021/7/5 13:34,1,
+340,MGMCLN750N215N232,2021/6/30 7:32,,1,
+341,MGMCLN750N215N234,2021/7/22 14:12,,1,
+342,MGMCLN750N215N235,2021/6/29 14:56,,1,
+343,MGMCLN750N215N236,2021/7/5 11:20,,1,
+344,MGMCLN750N215N237,2021/7/6 10:43,,1,
+345,MGMCLN750N215N239,2021/7/14 17:40,,1,
+346,MGMCLN750N215N240,2021/6/27 11:14,,1,
+347,MGMCLN750N215N241,2021/7/3 13:07,,1,
+348,MGMCLN750N215N242,2021/7/18 16:36,,1,
+349,MGMCLN750N215N244,2021/7/10 9:03,,1,
+350,MGMCLN750N215N245,2021/7/2 14:55,2021/7/14 16:15,1,
+351,MGMCLN750N215N246,2021/7/7 10:52,,1,
+352,MGMCLN750N215N247,2021/7/22 15:55,,1,
+353,MGMCLN750N215N248,2021/7/4 20:29,,1,
+354,MGMCLN750N215N249,2021/6/28 15:34,,1,
+355,MGMCLN750N215N250,2021/7/1 8:38,,1,
+356,MGMCLN750N215N251,2021/7/5 11:11,,1,
+357,MGMCLN750N215N252,2021/7/2 9:52,,1,
+358,MGMCLN750N215N253,2021/7/4 14:28,2021/7/4 17:59,1,
+359,MGMCLN750N215N254,2021/7/2 14:53,,1,
+360,MGMCLN750N215N255,2021/7/24 14:22,,1,
+361,MGMCLN750N215N257,2021/7/24 14:03,,1,
+362,MGMCLN750N215N258,2021/6/29 15:57,,1,
+363,MGMCLN750N215N259,2021/7/4 15:25,,1,
+364,MGMCLN750N215N260,2021/7/7 17:53,,1,
+365,MGMCLN750N215N261,2021/7/9 20:32,,1,
+366,MGMCLN750N215N262,2021/7/5 8:24,,1,
+367,MGMCLN750N215N263,2021/7/4 16:10,,1,
+368,MGMCLN750N215N264,2021/6/25 19:07,,1,
+369,MGMCLN750N215N266,2021/7/9 9:18,,1,
+370,MGMCLN750N215N267,2021/7/7 10:40,2021/7/10 10:52,0,2021/7/27
+371,MGMCLN750N215N269,2021/7/4 17:38,,1,
+372,MGMCLN750N215N270,2021/7/7 9:50,,1,
+373,MGMCLN750N215N271,2021/7/2 16:30,2021/7/6 18:55,1,
+374,MGMCLN750N215N273,2021/7/6 12:36,2021/7/6 12:43,1,
+375,MGMCLN750N215N274,2021/6/29 12:13,,1,
+376,MGMCLN750N215N275,2021/7/5 11:17,,1,
+377,MGMCLN750N215N276,2021/7/5 13:52,2021/7/10 14:49,1,
+378,MGMCLN750N215N278,2021/7/6 8:10,2021/7/19 16:11,1,
+379,MGMCLN750N215N280,2021/7/6 10:41,,1,
+380,MGMCLN750N215N281,2021/7/1 15:36,,1,
+381,MGMCLN750N215N282,2021/7/4 17:17,,1,
+382,MGMCLN750N215N283,2021/7/21 13:00,,1,
+383,MGMCLN750N215N284,2021/7/4 15:14,,1,
+384,MGMCLN750N215N285,2021/7/5 15:38,,1,
+385,MGMCLN750N215N286,2021/7/2 21:19,,1,
+386,MGMCLN750N215N287,2021/7/4 19:55,,1,
+387,MGMCLN750N215N288,2021/7/2 17:06,,1,
+388,MGMCLN750N215N289,2021/6/30 13:40,,1,
+389,MGMCLN750N215N290,2021/6/29 13:53,,1,
+390,MGMCLN750N215N291,2021/7/4 10:36,,1,
+391,MGMCLN750N215N292,2021/7/6 20:22,,1,
+392,MGMCLN750N215N293,2021/7/16 15:17,,1,
+393,MGMCLN750N215N294,2021/7/6 10:20,2021/7/23 18:46,1,
+394,MGMCLN750N215N296,2021/7/7 13:55,,1,
+395,MGMCLN750N215N298,2021/7/10 16:38,,1,
+396,MGMCLN750N215N300,2021/7/22 17:38,,1,
+397,MGMCLN750N215N301,2021/6/30 17:30,,1,
+398,MGMCLN750N215N302,2021/7/11 11:48,2021/7/13 20:37,1,
+399,MGYGYN660N214E010,2021/4/29 11:51,2021/5/25 14:25,1,
+400,MLSLXN750N215R003,2021/6/23 16:54,2021/7/23 10:42,1,
+401,MLSLXN750N215R004,2021/7/14 17:02,,1,
+402,MLSLXN750N215R005,2021/6/25 15:40,2021/7/22 19:14,1,
+403,MLSLXN750N215R007,2021/6/25 15:14,,1,
+404,MLSLXN750N215R008,2021/6/23 15:34,2021/7/22 19:18,1,
+405,MLSLXN750N215R009,2021/6/22 15:10,,1,
+406,MLSLXN750N215R010,2021/7/19 10:26,2021/7/22 10:21,1,
+408,PK50001A100000013,2020/7/14 19:15,2021/3/31 16:47,0,2021/4/12 16:47
+409,PK50001A100000014,2020/4/10 14:40,2020/11/5 13:31,0,2021/7/13
+410,PK50001A100000016,2020/4/8 13:28,2020/12/29 10:22,0,2021/3/26 10:22
+411,PK50001A100000018,2020/6/1 12:50,2020/6/18 18:35,0,2020/8/7 17:01
+412,PK50001A100000020,2020/7/1 17:14,2021/2/24 11:01,0,2021/3/26 10:22
+413,PK50001A100000021,2020/3/11 17:00,2021/6/5 13:42,1,
+414,PK50001A100000022,2020/7/24 10:21,2020/12/9 10:03,1,
+415,PK50001A100000027,2020/2/25 15:32,2021/4/9 15:11,0,2021/4/12 16:47
+416,PK50001A100000028,2020/7/24 15:11,2020/11/15 20:29,0,2020/12/23 21:46
+417,PK50001A100000029,2020/4/9 13:11,2020/5/30 15:08,0,2020/6/8 15:08
+418,PK50001A100000030,2019/12/31 14:06,2021/1/29 21:23,0,2021/3/26 10:22
+419,PK50001A100000031,2020/2/25 10:33,2021/3/23 10:11,1,
+420,PK50001A100000032,2020/8/5 15:42,,1,
+421,PK50001A100000034,2020/11/9 13:49,2021/3/24 10:23,0,2021/6/2
+422,PK50001A100000035,2020/3/11 10:53,2021/5/20 17:28,0,2021/6/2
+423,PK50001A100000036,2019/11/6 15:51,2020/4/9 9:35,0,2020/4/9 9:35
+424,PK50001A100000037,2020/2/4 20:34,2020/4/20 18:46,0,2020/8/26 18:46
+425,PK50001A100000038,2020/1/14 11:46,2021/3/23 16:42,0,2021/6/2
+426,PK50001A100000039,2020/3/11 14:09,2021/2/22 11:23,1,
+427,PK50001A100000040,2020/2/17 11:40,2021/3/26 11:05,0,2021/4/12 16:47
+428,PK50001A100000042,2020/2/22 9:47,2021/3/22 14:16,0,2021/3/26 10:22
+429,PK50001A100000045,2020/1/6 10:35,2021/4/24 12:17,1,
+430,PK50001A100000046,2020/10/31 11:11,2021/6/13 20:13,1,
+431,PK50001A100000047,2019/12/31 11:18,2021/4/8 11:06,0,2021/4/12 16:47
+432,PK50001A100000048,2020/2/13 16:47,2020/10/26 16:45,0,2020/12/23 21:46
+433,PK50001A100000049,2020/7/6 14:49,2020/8/2 14:04,0,2020/8/7 11:22
+434,PK50001A100000050,2020/1/3 15:43,2021/3/27 17:04,1,
+435,PK50001A100000051,2020/8/6 16:45,2020/9/12 9:43,1,
+436,PK50001A100000052,2020/2/11 19:08,2020/5/25 13:39,0,2020/6/3 13:39
+437,PK50001A100000053,2020/7/9 10:20,2021/1/13 11:50,0,2021/1/22 11:50
+438,PK50001A100000054,2020/8/6 16:47,2020/9/12 9:43,1,
+439,PK50001A100000056,2020/3/11 14:09,2020/6/1 11:22,0,2020/8/7 11:22
+440,PK50001A100000057,2020/2/13 11:49,2021/4/22 13:01,0,2021/6/2
+441,PK50001A100000058,2020/2/28 21:09,2021/4/7 10:46,0,2021/4/12 16:47
+442,PK50001A100000059,2020/4/10 14:38,2020/8/15 21:46,0,2020/10/16 21:46
+443,PK50001A100000061,2020/1/6 15:34,2021/4/7 13:17,0,2021/4/12
+444,PK50001A100000062,2020/9/3 12:29,2021/3/19 10:36,0,2021/3/26 10:22
+445,PK50001A100000063,2019/12/3 14:43,2020/1/3 13:09,0,2020/1/7 13:09
+446,PK50001A100000064,2020/7/25 11:03,2021/3/25 16:27,0,2021/3/26 10:22
+447,PK50001A100000065,2020/8/6 16:48,2021/4/9 15:10,0,2021/4/12 16:47
+448,PK50001A100000068,2020/5/17 22:23,2021/3/31 16:40,1,
+449,PK50001A100000091,2020/6/17 13:32,2020/11/11 14:24,0,2021/1/22 11:50
+450,PK50001A100000092,2020/1/6 15:21,,1,
+451,PK50001A100000095,2020/3/25 7:13,2021/4/23 11:25,1,
+452,PK50001A100000096,2020/2/17 11:43,2020/10/10 11:41,0,2020/10/16 21:46
+453,PK50001A100000097,2020/2/26 14:59,2020/9/12 9:42,0,2020/12/23 21:46
+454,PK50001A100000098,2020/3/25 11:01,2020/8/28 22:24,1,
+455,PK50001A100000099,2020/5/25 13:39,2021/6/15 11:18,1,
+456,PK50001A100000100,2020/7/7 11:37,2021/5/21 10:33,0,2021/6/2
+457,PK50001A100000101,2020/3/8 16:28,2020/9/12 9:42,1,
+458,PK50001A100000120,2021/3/23 14:58,,1,
+459,PK50001A100000121,2021/3/22 16:15,2021/6/30 18:24,1,
+460,PK50001A100000122,2020/4/30 22:09,2020/11/11 14:24,0,2021/7/13
+461,PK50001A100000123,2019/11/21 11:19,2021/7/19 18:40,1,
+462,PK50001A100000124,2020/1/3 11:01,2021/4/5 17:36,1,
+463,PK50001A100000125,2021/1/4 17:45,2021/6/20 14:32,1,
+464,PK50001A100000126,2020/4/7 13:54,2021/5/19 11:13,1,
+465,PK50001A100000127,2019/12/30 10:52,2020/4/22 18:24,1,
+466,PK50001A100000128,2020/2/18 18:24,2020/4/17 8:53,0,2020/4/17 8:53
+467,PK50001A100000130,2019/11/29 16:50,2020/11/17 10:53,0,2021/3/26 10:22
+468,PK50001A100000131,2020/2/19 18:15,2021/4/18 10:16,1,
+469,PK50001A100000132,2020/6/5 15:15,2021/3/1 10:24,0,2021/3/26 10:22
+470,PK50001A100000133,2020/4/2 11:09,2020/11/20 12:52,1,
+471,PK50001A100000134,2020/2/28 20:28,2021/1/14 14:13,0,2021/1/22 11:50
+472,PK50001A100000135,2020/9/17 17:18,2020/9/24 13:34,0,2020/10/16 13:34
+473,PK50001A100000136,2020/2/22 14:27,2020/12/14 14:44,1,
+474,PK50001A100000137,2019/12/24 11:32,2021/6/4 14:01,1,
+475,PK50001A100000138,2020/7/11 13:31,2020/12/7 19:55,1,
+476,PK50001A100000139,2020/3/9 17:16,2020/3/10 20:31,0,2020/3/16 20:31
+477,PK50001A100000141,2020/2/28 18:24,2020/12/8 10:43,1,
+478,PK50001A100000142,2020/2/17 13:19,2020/5/20 10:39,0,2020/6/3 12:16
+479,PK50001A100000143,2019/12/4 16:45,2021/7/14 15:52,1,
+480,PK50001A100000144,2021/1/1 18:24,2021/4/6 16:45,0,2021/6/2
+481,PK50001A100000145,2019/12/24 15:08,2020/2/24 10:00,1,
+482,PK50001A100000146,2021/3/19 10:36,2021/4/9 16:41,0,2021/4/12 16:47
+483,PK50001A100000147,2020/1/3 10:10,2020/11/1 15:27,1,
+484,PK50001A100000148,2020/12/18 9:57,2021/6/4 9:55,0,2020/6/3 17:11
+485,PK50001A100000150,2020/5/1 21:15,2021/4/9 13:25,1,
+486,PK50001A100000151,2020/2/18 10:26,2021/6/8 10:25,1,
+487,PK50001A100000152,2020/6/21 13:48,2021/1/12 11:17,1,
+488,PK50001A100000153,2020/8/24 22:03,2021/1/25 14:03,0,2021/3/26 10:22
+489,PK50001A100000154,2019/12/14 9:37,2019/12/18 17:11,0,2020/6/3 17:11
+490,PK50001A100000155,2021/3/13 17:42,,1,
+491,PK50001A100000156,2020/2/22 15:16,2021/4/9 16:53,0,2021/4/12 16:47
+492,PK50001A100000157,2020/2/23 9:56,2020/5/25 19:01,1,
+493,PK50001A100000159,2020/2/28 22:34,2020/8/30 9:35,1,
+494,PK50001A100000160,2020/4/15 11:48,2020/10/5 11:24,1,
+495,PK50001A100000162,2020/6/26 18:48,2021/7/4 9:32,1,
+496,PK50001A100000163,2020/3/10 14:16,2021/7/4 9:32,1,
+497,PK50001A100000164,2020/4/5 16:01,2021/3/25 16:54,0,2021/3/26 10:22
+498,PK50001A100000165,2020/1/19 12:49,2020/8/19 9:31,0,2020/8/26 9:31
+499,PK50001A100000166,2019/12/9 10:01,,0,2021/1/22 11:50
+500,PK50001A100000167,2019/11/11 17:04,2021/2/5 14:34,1,
+501,PK50001A100000168,2020/4/30 13:27,2020/5/25 12:16,0,2020/6/3 12:16
+502,PK50001A100000169,2019/11/29 11:51,2020/8/16 11:18,0,2020/8/26 9:31
+503,PK50001A100000170,2020/2/27 19:09,2021/4/29 20:01,0,2021/6/2
+504,PK50001A100000171,2020/5/29 14:14,2021/3/31 16:41,1,
+505,PK50001A100000172,2020/1/19 14:24,2020/9/21 10:49,0,2020/10/16 10:49
+506,PK50001A100000173,2020/1/19 10:26,2020/6/8 13:52,1,
+507,PK50001A100000174,2020/6/23 9:38,2021/3/26 14:09,0,2021/6/2
+508,PK50001A100000175,2020/8/13 14:40,,1,
+509,PK50001A100000176,2020/3/2 13:20,2020/6/15 11:16,0,2020/8/7 17:01
+511,PK50001A100000178,2020/4/13 20:29,2021/1/7 14:04,0,2021/1/22 11:50
+512,PK50001A100000181,2020/2/17 14:45,,1,
+513,PK50001A100000182,2020/2/23 12:54,2021/4/29 17:03,1,
+514,PK50001A100000183,2020/3/25 13:46,2021/4/27 9:30,0,2021/6/2
+515,PK50001A100000184,2020/10/20 14:16,2021/5/3 12:25,1,
+516,PK50001A100000186,2020/4/4 11:45,,1,
+517,PK50001A100000187,2020/2/28 15:47,2020/4/15 10:24,0,2020/4/15 10:24
+518,PK50001A100000188,2020/5/1 8:28,2021/4/24 17:20,1,
+519,PK50001A100000189,2020/7/3 9:38,2021/5/12 10:10,0,2021/7/13
+520,PK50001A100000191,2020/11/5 15:35,2021/5/11 13:28,1,
+521,PK50001A100000192,2020/4/30 13:36,2020/12/17 12:56,0,2021/1/22 11:50
+522,PK50001A100000193,2020/2/28 20:26,2021/4/11 11:58,1,
+523,PK50001A100000194,2021/3/13 17:42,2021/4/2 12:01,1,
+524,PK50001A100000195,2020/7/5 8:55,2021/4/4 21:55,1,
+525,PK50001A100000197,2020/3/14 10:53,2021/4/26 13:11,1,
+526,PK50001A100000199,2020/6/22 15:58,2021/5/7 10:10,1,
+527,PK50001A100000200,2020/7/16 19:11,2021/5/14 15:35,1,
+528,PK50001A100000201,2020/5/25 12:16,2020/7/25 17:51,0,2020/7/25 17:51
+529,PK50001A100000202,2020/4/30 20:50,2020/7/3 14:51,0,2020/12/23 21:46
+530,PK50001A100000203,2020/2/19 10:43,2021/6/15 11:18,0,2021/7/13
+531,PK50001A100000204,2020/4/4 10:17,2021/4/4 16:59,1,
+532,PK50001A100000205,2020/5/23 11:00,2020/10/20 13:05,0,2021/1/22 11:50
+533,PK50001A100000206,2020/3/10 16:01,2021/7/4 22:06,1,
+534,PK50001A100000208,2020/7/29 15:30,2020/9/18 16:30,1,
+535,PK50001A100000209,2020/1/31 14:50,2021/1/8 19:21,1,
+536,PK50001A100000210,2020/6/28 15:13,,0,2020/8/7 22:43
+537,PK50001A100000215,2020/3/11 18:04,2021/3/27 19:54,1,
+538,PK50001A100000216,2020/7/3 15:16,2020/12/30 11:05,0,2021/1/22 11:50
+539,PK50001A100000218,2020/5/28 14:23,2021/1/2 18:12,1,
+540,PK50001A100000219,2020/10/20 17:36,2021/5/7 16:11,1,
+541,PK50001A100000220,2020/4/5 10:59,2020/6/19 15:03,1,
+542,PK50001A100000221,2020/2/17 17:03,2021/1/14 11:16,1,
+543,PK50001A100000222,2020/11/7 14:05,2021/4/23 15:04,1,
+544,PK50001A100000223,2019/11/8 17:32,2021/3/22 16:15,0,2021/3/26 16:15
+545,PK50001A100000225,2020/3/5 14:04,2021/2/21 16:36,1,
+546,PK50001A100000226,2020/3/8 16:45,2021/6/29 14:14,1,
+547,PK50001A100000227,2020/6/22 15:14,2021/1/31 11:16,0,2021/3/26 16:15
+548,PK50001A100000228,2020/2/17 16:06,2021/4/6 16:27,1,
+549,PK50001A100000229,2020/4/6 14:34,2021/4/7 18:17,0,2021/3/26 16:15
+550,PK50001A100000231,2020/7/25 10:11,2021/6/1 9:04,1,
+551,PK50001A100000232,2020/5/1 11:30,2021/3/22 16:20,0,2021/3/26 16:15
+552,PK50001A100000233,2021/4/28 16:52,,1,
+553,PK50001A100000234,2020/4/4 9:52,,1,
+554,PK50001A100000235,2020/9/22 18:55,2020/11/30 17:35,1,
+555,PK50001A100000236,2019/11/21 19:48,2021/5/24 14:53,1,
+556,PK50001A100000237,2020/2/24 16:38,2020/7/6 17:18,1,
+557,PK50001A100000238,2020/1/6 15:41,2020/1/23 8:12,0,2021/7/13
+558,PK50001A100000239,2020/1/30 11:53,2020/8/6 9:58,1,
+559,PK50001A100000240,2020/4/15 18:38,2020/11/25 11:24,1,
+560,PK50001A100000242,2020/4/5 16:12,2020/11/2 10:25,1,
+561,PK50001A100000244,2020/10/23 14:46,2021/3/4 14:44,0,2021/3/26 16:15
+562,PK50001A100000245,2020/2/25 14:51,2021/1/11 13:19,0,2021/1/22 11:50
+563,PK50001A100000246,2020/1/3 15:38,2020/3/17 8:19,0,2020/6/3 8:19
+564,PK50001A100000247,2020/9/3 18:05,2021/2/8 15:50,0,2021/3/26 15:50
+565,PK50001A100000248,2019/12/26 17:41,2021/5/8 17:44,1,
+566,PK50001A100000249,2020/6/16 17:41,2020/11/15 15:33,1,
+567,PK50001A100000250,2020/5/7 13:12,2020/6/30 11:03,0,2020/8/7 11:03
+568,PK50001A100000252,2020/12/18 19:44,,1,
+569,PK50001A100000253,2020/4/4 9:53,2021/1/20 15:41,0,2021/1/22 11:50
+570,PK50001A100000254,2021/3/25 16:54,2021/4/6 16:56,1,
+571,PK50001A100000255,2019/11/15 12:49,2020/1/3 13:09,1,
+572,PK50001A100000256,2020/2/17 18:05,2020/10/27 10:46,0,2020/12/23 10:46
+573,PK50001A100000257,2021/3/13 17:48,,1,
+574,PK50001A100000258,2020/2/25 15:10,2020/11/27 9:55,1,
+575,PK50001A100000259,2020/5/1 10:36,2020/12/13 17:22,0,2021/3/26 16:15
+576,PK50001A100000260,2020/2/21 13:11,2021/5/12 11:02,1,
+577,PK50001A100000261,2020/2/17 10:29,2021/5/7 14:33,1,
+578,PK50001A100000263,2020/4/7 14:10,2021/6/15 9:47,0,2021/7/13
+579,PK50001A100000264,2020/4/6 13:23,2020/11/8 14:01,0,2021/6/2
+580,PK50001A100000265,2020/5/1 14:03,2021/7/11 21:49,1,
+581,PK50001A100000266,2020/4/8 21:32,2020/12/28 8:56,0,2021/1/22 11:50
+582,PK50001A100000268,2020/7/30 9:35,2021/1/5 19:36,0,2021/1/22 11:50
+583,PK50001A100000269,2020/4/1 12:11,2021/1/6 15:40,0,2021/1/22 11:50
+584,PK50001A100000271,2020/5/17 18:03,2021/4/11 16:03,0,2021/6/2
+585,PK50001A100000272,2020/10/24 17:56,2021/6/15 10:36,1,
+586,PK50001A100000274,2020/5/3 16:50,2020/12/29 15:39,0,2021/1/22 11:50
+587,PK50001A100000276,2019/11/27 10:42,2020/11/16 16:44,1,
+588,PK50001A100000277,2020/2/17 14:00,2020/5/26 10:08,0,2020/6/3 10:08
+589,PK50001A100000278,2020/2/27 18:40,2020/11/27 10:46,0,2020/12/23 10:46
+590,PK50001A100000279,2021/1/4 14:59,2021/4/5 19:03,0,2021/4/12 16:47
+591,PK50001A100000280,2020/4/9 15:59,2020/12/9 15:18,0,2021/1/22 11:50
+592,PK50001A100000282,2020/1/31 14:51,2020/2/6 16:27,1,
+593,PK50001A100000283,2020/2/21 15:55,2021/1/18 9:53,0,2021/1/22 11:50
+594,PK50001A100000285,2020/2/19 16:05,2020/6/5 15:32,1,
+595,PK50001A100000286,2020/6/6 15:26,2021/6/16 17:45,0,2021/7/13
+596,PK50001A100000287,2020/12/22 14:33,2021/7/18 22:43,1,
+597,PK50001A100000290,2020/7/2 13:02,2021/6/4 9:13,1,
+598,PK50001A100000292,2020/2/19 16:05,2021/5/31 17:17,0,2021/6/2
+599,PK50001A100000293,2020/5/11 17:53,2021/4/2 10:48,1,
+600,PK50001A100000294,2020/4/4 13:12,2020/4/21 10:32,1,
+601,PK50001A100000295,2019/11/14 10:43,2020/11/1 15:53,1,
+602,PK50001A100000296,2020/2/18 11:00,2020/3/25 14:16,1,
+603,PK50001A100000297,2020/2/20 13:58,2020/11/19 14:14,0,2020/12/23 10:46
+604,PK50001A100000298,2020/6/18 18:35,2021/4/5 22:52,1,
+605,PK50001A100000299,2020/9/3 16:11,2021/7/23 19:06,1,
+606,PK50001A100000300,2020/2/26 14:15,2021/5/8 9:28,1,
+607,PK50001A100000301,2019/12/13 17:01,2020/11/26 10:43,1,
+608,PK50001A100000303,2021/5/2 14:01,2021/5/4 16:03,1,
+609,PK50001A100000304,2020/2/25 15:55,2021/5/16 14:34,1,
+610,PK50001A100000305,2020/4/30 21:30,2021/4/8 14:49,1,
+611,PK50001A100000306,2020/2/18 9:37,2021/3/2 10:47,1,
+612,PK50001A100000307,2021/1/3 10:32,2021/6/2 15:35,1,
+613,PK50001A100000308,2019/11/7 13:26,2021/4/26 13:10,1,
+614,PK50001A100000309,2020/2/19 9:38,2021/3/29 16:07,1,
+615,PK50001A100000310,2020/7/25 17:51,2021/7/21 16:30,1,
+616,PK50001A100000311,2019/11/29 16:50,2019/12/30 17:15,1,
+617,PK50001A100000312,2020/8/20 9:38,2021/3/16 15:44,1,
+618,PK50001A100000313,2020/5/3 16:53,2021/5/26 14:42,1,
+619,PK50001A100000316,2020/3/10 15:23,2020/12/26 14:13,0,2021/3/26 16:15
+620,PK50001A100000318,2020/6/1 11:04,2021/3/4 15:52,1,
+621,PK50001A100000319,2020/4/7 20:34,2021/6/20 14:57,1,
+622,PK50001A100000320,2020/6/23 15:41,2020/10/26 13:34,0,2020/12/23 13:34
+623,PK50001A100000321,2021/3/23 15:02,,1,
+624,PK50001A100000322,2020/4/9 10:37,,1,
+625,PK50001A100000323,2020/4/9 10:37,,1,
+626,PK50001A100000324,2020/4/8 21:05,2020/8/7 16:39,0,2021/6/2
+627,PK50001A100000325,2019/11/8 10:42,,1,
+628,PK50001A100000326,2019/11/7 9:12,2021/7/1 8:49,1,
+629,PK50001A100000327,2020/2/23 22:50,2020/10/24 19:25,1,
+630,PK50001A100000328,2019/12/4 11:58,2021/7/14 15:52,1,
+631,PK50001A100000329,2020/2/25 9:03,2021/7/3 12:30,1,
+632,PK50001A100000330,2020/5/31 16:29,2021/6/3 20:48,1,
+633,PK50001A100000332,2019/12/12 16:58,2021/4/12 13:50,0,2021/6/2
+634,PK50001A100000333,2021/3/8 14:42,2021/4/6 12:40,0,2021/6/2
+635,PK50001A100000334,2019/12/5 10:38,2021/3/23 10:57,0,2021/3/26 16:15
+636,PK50001A100000336,2020/4/13 13:54,2021/2/17 13:12,1,
+637,PK50001A100000337,2020/2/27 10:39,2021/4/9 13:34,0,2021/4/12 16:47
+638,PK50001A100000338,2019/12/30 16:51,2020/8/31 15:54,0,2020/12/23 13:34
+639,PK50001A100000339,2019/11/9 13:13,,1,
+640,PK50001A100000340,2021/3/22 16:20,2021/7/13 14:34,1,
+641,PK50001A100000341,2020/4/13 14:05,,1,
+642,PK50001A100000342,2020/5/19 15:19,2021/5/16 14:17,1,
+643,PK50001A100000343,2020/8/26 9:30,2021/5/9 9:41,1,
+644,PK50001A100000344,2020/9/3 8:17,,1,
+645,PK50001A100000345,2020/2/28 18:25,2021/5/8 14:50,1,
+646,PK50001A100000346,2020/4/21 11:15,,1,
+647,PK50001A100000347,2020/4/2 18:26,2020/10/29 15:46,1,
+648,PK50001A100000348,2020/3/27 14:12,2021/1/25 11:22,1,
+649,PK50001A100000349,2020/4/9 15:47,,0,2021/7/13
+650,PK50001A100000350,2020/1/7 11:03,,0,2021/6/2
+651,PK50001A100000351,2020/2/15 12:14,2021/5/31 17:17,0,2021/6/2
+652,PK50001A100000352,2020/2/21 14:55,2021/5/20 14:58,1,
+653,PK50001A100000353,2020/5/9 14:56,2021/6/16 10:49,1,
+654,PK50001A100000354,2020/6/10 16:05,,1,
+655,PK50001A100000355,2020/5/9 9:59,2020/5/12 14:33,0,2020/8/26 9:31
+656,PK50001A100000356,2020/12/28 19:27,,1,
+657,PK50001A100000357,2019/11/8 18:18,2020/9/12 9:42,1,
+658,PK50001A100000359,2020/12/22 21:33,2021/4/18 19:04,1,
+659,PK50001A100000360,2020/4/9 10:36,2020/5/9 14:56,0,2020/8/7 17:01
+660,PK50001A100000362,2020/5/7 16:09,,1,
+661,PK50001A100000363,2020/4/13 14:58,2021/1/6 17:22,0,2021/1/22 11:50
+662,PK50001A100000364,2020/11/20 14:53,2020/12/20 20:36,1,
+663,PK50001A100000365,2019/11/8 17:46,2019/12/17 10:11,0,2021/3/26 16:15
+664,PK50001A100000366,2019/11/10 16:32,2021/6/4 16:57,1,
+665,PK50001A100000367,2020/6/7 12:20,2021/4/14 11:23,1,
+666,PK50001A100000369,2020/4/3 9:32,2020/5/28 7:08,0,2021/4/12 16:47
+667,PK50001A100000370,2020/8/26 14:50,2021/6/27 16:59,1,
+668,PK50001A100000371,2020/11/24 10:09,2021/7/18 15:56,1,
+669,PK50001A100000372,2019/12/12 16:59,,1,
+670,PK50001A100000373,2021/1/5 17:08,2021/7/2 15:29,1,
+671,PK50001A100000374,2020/3/27 13:36,2020/5/28 7:07,1,
+672,PK50001A100000375,2020/2/16 10:52,2020/5/8 14:14,0,2020/5/20 14:14
+673,PK50001A100000377,2020/2/15 11:42,2020/11/7 19:48,1,
+674,PK50001A100000379,2020/4/6 19:17,2021/2/3 22:14,0,2021/3/26 16:15
+675,PK50001A100000380,2020/6/19 15:23,2021/3/25 15:41,0,2021/3/26 16:15
+676,PK50001A100000381,2020/9/19 15:43,2021/5/29 15:45,1,
+677,PK50001A100000382,2019/11/13 18:01,2021/7/1 17:55,1,
+678,PK50001A100000383,2020/1/6 11:19,2021/7/22 10:52,1,
+679,PK50001A100000385,2019/12/12 10:23,2020/7/13 11:53,1,
+680,PK50001A100000386,2020/11/19 19:32,2021/5/16 16:44,1,
+681,PK50001A100000387,2020/2/24 11:01,2021/5/30 20:31,1,
+682,PK50001A100000388,2019/12/27 15:19,2021/3/29 10:05,1,
+683,PK50001A100000390,2020/1/15 18:25,2021/3/9 18:02,1,
+684,PK50001A100000391,2020/6/19 14:52,,1,
+685,PK50001A100000392,2019/11/13 14:14,2021/3/25 14:49,1,
+686,PK50001A100000393,2019/12/12 10:44,2020/12/15 19:33,0,2021/3/26 16:15
+687,PK50001A100000394,2019/11/11 10:25,2021/6/8 18:05,1,
+688,PK50001A100000395,2019/11/15 17:52,2020/11/5 13:55,1,
+689,PK50001A100000396,2019/12/9 17:29,2021/1/29 21:25,1,
+690,PK50001A100000397,2019/11/27 14:43,2019/12/5 16:44,1,
+691,PK50001A100000398,2020/5/5 13:18,2021/1/16 10:14,0,2021/3/26 16:15
+692,PK50001A100000399,2019/12/16 14:36,2020/9/30 20:23,0,2020/10/16 21:46
+693,PK50001A100000400,2020/6/30 11:54,2021/5/20 14:12,1,
+694,PK50001A100000402,2019/12/24 14:24,2020/5/11 21:01,0,2020/5/20 21:01
+695,PK50001A100000403,2019/12/30 11:05,2021/1/11 13:30,1,
+696,PK50001A100000404,2020/1/2 15:18,2020/9/20 17:11,1,
+697,PK50001A100000405,2019/12/27 17:28,2021/5/19 14:54,0,2021/7/13
+698,PK50001A100000406,2019/11/11 15:24,2021/4/25 14:00,0,2021/6/2
+699,PK50001A100000407,2019/12/24 10:29,2021/6/4 16:10,1,
+700,PK50001A100000409,2019/12/23 10:45,2021/4/21 9:43,1,
+701,PK50001A100000410,2020/4/7 10:22,2021/1/8 9:35,0,2021/3/26 16:15
+702,PK50001A100000411,2020/2/12 14:59,2021/1/8 16:13,1,
+703,PK50001A100000412,2020/12/1 12:41,,1,
+704,PK50001A100000413,2020/4/13 18:14,2021/2/5 15:28,1,
+705,PK50001A100000414,2020/2/24 15:23,2020/5/11 21:02,0,2020/10/21 21:46
+706,PK50001A100000415,2020/4/29 18:00,2021/1/11 16:14,0,2021/3/26 16:15
+707,PK50001A100000417,2019/12/4 20:28,2021/4/28 16:59,1,
+708,PK50001A100000418,2020/2/28 15:58,2020/9/12 9:42,1,
+709,PK50001A100000419,2020/8/27 14:22,2021/4/7 13:33,1,
+710,PK50001A100000420,2021/3/9 16:25,,1,
+711,PK50001A100000421,2021/3/25 15:41,2021/5/1 17:22,0,2021/6/2
+712,PK50001A100000422,2019/12/15 17:37,2020/8/7 21:51,1,
+713,PK50001A100000423,2020/12/21 21:51,2021/6/4 16:57,1,
+714,PK50001A100000424,2020/12/21 9:30,2021/4/20 14:25,1,
+715,PK50001A100000425,2020/2/6 16:25,2020/2/12 8:26,0,2019/11/20 8:26
+716,PK50001A100000426,2020/4/9 10:36,,1,
+717,PK50001A100000427,2020/12/19 19:25,2021/5/11 13:29,1,
+718,PK50001A100000428,2021/5/26 15:25,2021/5/27 14:15,0,2021/6/2
+719,PK50001A100000429,2021/1/8 10:11,2021/7/18 20:17,1,
+720,PK50001A100000430,2020/4/22 15:54,2021/3/30 15:56,1,
+721,PK50001A100000431,2020/6/1 16:44,2021/5/23 14:48,0,2021/6/2
+722,PK50001A100000432,2020/2/25 15:34,2020/8/7 18:10,1,
+723,PK50001A100000433,2020/12/15 10:47,2020/12/16 9:04,0,2021/1/22 11:50
+724,PK50001A100000434,2020/12/18 17:28,2021/5/3 12:25,1,
+725,PK50001A100000435,2020/2/8 15:41,2020/8/17 16:22,0,2020/10/16 21:46
+726,PK50001A100000437,2020/1/6 14:28,2020/4/29 8:03,0,2020/5/9 8:03
+727,PK50001A100000438,2020/2/10 18:25,2020/10/28 16:24,1,
+728,PK50001A100000440,2019/11/27 14:24,2020/1/29 8:45,1,
+729,PK50001A100000441,2020/12/22 16:59,,1,
+730,PK50001A100000442,2020/2/15 12:27,2021/6/8 18:05,1,
+731,PK50001A100000443,2020/10/30 10:57,2020/12/8 17:54,1,
+732,PK50001A100000444,2019/12/2 9:52,2021/3/2 20:15,1,
+733,PK50001A100000445,2020/12/25 12:01,2021/6/22 16:42,1,
+734,PK50001A100000446,2020/2/17 16:35,2021/7/21 14:10,1,
+735,PK50001A100000447,2020/3/21 14:09,2020/10/29 18:10,0,2020/12/23 13:34
+736,PK50001A100000448,2020/5/14 13:44,2021/6/22 19:26,1,
+737,PK50001A100000449,2020/12/21 14:00,,1,
+738,PK50001A100000450,2020/12/22 12:53,2021/6/28 14:16,1,
+739,PK50001A100000451,2020/4/9 10:35,2020/6/10 16:05,0,2020/8/7 17:01
+740,PK50001A100000452,2020/2/28 21:20,2020/4/19 12:25,0,2020/5/9 12:25
+741,PK50001A100000453,2021/1/8 9:35,,1,
+742,PK50001A100000454,2020/5/4 18:07,2021/3/24 18:49,1,
+743,PK50001A100000455,2020/12/20 18:07,2021/1/17 11:11,0,2021/3/26 16:15
+744,PK50001A100000457,2019/12/14 10:06,,0,2021/4/12
+745,PK50001A100000458,2020/7/29 15:18,2021/6/8 10:25,1,
+746,PK50001A100000459,2020/4/7 17:24,,1,
+747,PK50001A100000461,2020/11/25 17:34,2021/3/5 13:58,0,2021/3/26 13:58
+748,PK50001A100000463,2020/5/17 18:03,2021/6/5 10:58,1,
+749,PK50001A100000464,2021/1/5 19:36,,0,2021/6/2
+750,PK50001A100000465,2020/2/27 9:29,2020/11/9 14:49,0,2020/12/23 13:34
+751,PK50001A100000466,2020/2/27 16:53,2021/5/20 15:09,0,2021/6/2
+752,PK50001A100000467,2020/5/12 14:33,2020/12/18 9:57,0,2021/1/22 11:50
+753,PK50001A100000468,2020/2/25 16:44,2020/11/3 15:13,1,
+754,PK50001A100000469,2019/12/10 13:48,2021/7/2 8:36,1,
+755,PK50001A100000470,2020/3/27 16:36,2021/5/4 21:25,1,
+756,PK50001A100000471,2019/12/14 10:15,2020/9/22 20:08,0,2020/10/19 21:46
+757,PK50001A100000472,2020/2/27 14:41,2021/1/25 9:23,0,2021/6/2
+758,PK50001A100000474,2020/4/24 15:23,2021/7/6 21:26,0,2021/7/13
+759,PK50001A100000475,2020/10/22 19:28,2021/5/11 13:29,1,
+760,PK50001A100000476,2020/6/30 15:11,2020/8/1 13:35,0,2020/8/26 9:31
+761,PK50001A100000477,2019/12/14 14:14,2020/4/30 13:27,0,2020/5/20 13:27
+762,PK50001A100000478,2019/11/27 10:47,2020/7/26 9:37,1,
+763,PK50001A100000479,2020/2/19 18:10,2021/3/31 16:43,0,2021/6/2
+764,PK50001A100000480,2019/12/5 16:44,2020/5/6 18:36,0,2020/8/26 9:31
+765,PK50001A100000481,2020/4/10 13:10,2020/10/27 13:57,1,
+766,PK50001A100000483,2020/8/11 9:36,2021/6/22 16:42,1,
+767,PK50001A100000485,2020/2/27 16:23,2020/11/24 10:00,1,
+768,PK50001A100000486,2020/2/13 13:10,2021/5/3 9:55,1,
+769,PK50001A100000487,2020/5/23 10:27,2021/2/1 15:19,0,2021/3/26 13:58
+770,PK50001A100000488,2020/2/12 17:26,,1,
+771,PK50001A100000489,2019/12/12 17:15,,1,
+772,PK50001A100000490,2019/12/4 18:18,2021/1/12 10:49,1,
+773,PK50001A100000491,2019/12/4 9:47,2020/12/10 12:34,1,
+774,PK50001A100000492,2020/2/22 15:41,2021/4/18 11:21,1,
+775,PK50001A100000493,2020/2/10 15:31,2021/3/29 15:40,1,
+776,PK50001A100000494,2019/12/19 15:55,2021/4/3 9:26,1,
+777,PK50001A100000495,2019/12/11 17:59,2020/5/28 19:28,1,
+778,PK50001A100000496,2019/11/27 9:40,2019/12/9 11:06,1,
+779,PK50001A100000497,2020/2/29 22:12,2021/3/31 9:25,1,
+780,PK50001A100000498,2019/12/15 9:31,2021/6/27 21:00,1,
+781,PK50001A100000499,2020/3/27 15:50,2021/1/30 18:59,1,
+782,PK50001A100000500,2019/11/29 11:18,2019/11/29 11:51,1,
+783,PK50001A100000501,2020/2/10 18:21,2021/5/7 16:11,1,
+784,PK50001A100000502,2020/6/21 9:50,2021/6/18 10:41,1,
+785,PK50001A100000503,2020/2/12 19:25,,1,
+786,PK50001A100000504,2019/12/3 11:02,2021/1/15 9:24,1,
+787,PK50001A100000505,2020/1/13 15:38,2020/10/18 20:03,1,
+788,PK50001A100000506,2020/5/30 15:08,2020/10/6 15:34,1,
+789,PK50001A100000507,2019/11/12 11:13,2021/7/2 14:42,1,
+790,PK50001A100000508,2020/2/29 15:21,2020/12/18 20:13,1,
+791,PK50001A100000509,2020/9/15 16:10,2021/7/11 15:25,1,
+792,PK50001A100000510,2020/4/21 10:39,2021/3/25 10:53,1,
+793,PK50001A100000511,2020/4/17 8:53,,1,
+794,PK50001A100000512,2020/4/9 10:34,2021/4/9 15:14,0,2021/4/12 15:14
+795,PK50001A100000513,2020/3/10 20:31,2021/4/2 10:48,1,
+796,PK50001A100000514,2019/12/13 17:36,2021/7/18 9:29,1,
+797,PK50001A100000515,2019/12/19 13:21,2020/3/3 17:49,0,2021/3/26 13:58
+798,PK50001A100000516,2020/8/26 9:37,,1,
+799,PK50001A100000518,2020/11/18 18:00,2021/6/4 16:08,0,2021/7/13
+800,PK50001A100000519,2020/7/10 14:24,2020/8/24 22:03,0,2020/8/26 9:31
+801,PK50001A100000520,2019/12/12 11:17,,1,
+802,PK50001A100000522,2020/8/26 14:51,2021/7/18 15:56,1,
+803,PK50001A100000525,2020/4/20 14:27,2020/7/30 15:19,1,
+804,PK50001A100000526,2020/4/20 10:50,2020/4/29 15:25,0,2020/5/9 15:25
+805,PK50001A100000528,2020/5/4 15:01,2020/11/20 12:52,0,2021/6/2
+806,PK50001A100000529,2020/8/8 10:37,2021/4/23 15:04,1,
+807,PK50001A100000530,2020/6/3 14:22,,1,
+808,PK50001A100000531,2020/8/29 13:09,2021/4/22 16:23,0,2021/6/2
+809,PK50001A100000532,2020/4/19 13:57,2020/5/17 22:43,0,2020/8/7 22:43
+810,PK50001A100000533,2021/2/3 11:55,2021/6/4 14:41,0,2021/3/26 15:50
+811,PK50001A100000534,2020/10/18 16:11,2021/6/24 18:10,1,
+812,PK50001A100000535,2020/9/24 16:10,2021/6/5 13:02,1,
+813,PK50001A100000536,2020/6/7 10:06,2020/9/2 10:54,1,
+814,PK50001A100000540,2020/8/28 16:50,2021/5/8 15:43,0,2021/7/13
+815,PK50001A100000542,2020/4/19 9:47,2021/6/2 7:38,1,
+816,PK50001A100000544,2020/4/17 9:36,2020/5/28 6:45,0,2020/6/10 6:45
+817,PK50001A100000545,2020/9/18 18:16,,1,
+818,PK50001A100000546,2020/9/14 20:12,2021/4/10 18:51,0,2021/4/12
+819,PK50001A100000547,2020/6/19 20:39,2020/11/23 17:07,1,
+820,PK50001A100000549,2020/7/29 15:12,2021/4/10 9:54,1,
+821,PK50001A100000550,2020/7/21 10:32,2021/4/1 17:08,1,
+822,PK50001A100000551,2020/4/22 18:27,2021/1/8 13:04,1,
+823,PK50001A100000552,2020/7/13 16:28,2021/4/1 14:25,0,2021/4/12
+824,PK50001A100000553,2020/8/1 13:35,2021/4/4 16:52,1,
+825,PK50001A100000554,2020/5/18 18:47,2020/8/25 17:50,1,
+826,PK50001A100000555,2020/9/21 21:28,,1,
+827,PK50001A100000556,2020/7/28 20:49,2020/10/17 21:26,1,
+828,PK50001A100000558,2020/9/9 14:45,2021/4/6 21:50,1,
+829,PK50001A100000560,2020/10/19 10:40,2021/3/2 13:09,1,
+830,PK50001A100000561,2020/9/19 13:12,2021/6/20 15:22,1,
+831,PK50001A100000563,2020/4/18 14:41,2021/5/19 18:01,1,
+832,PK50001A100000565,2020/9/10 19:09,2021/1/7 19:38,1,
+833,PK50001A100000566,2020/7/29 10:43,2020/11/9 19:54,1,
+834,PK50001A100000567,2020/11/8 14:29,2020/11/13 14:54,1,
+835,PK50001A100000568,2020/8/20 10:46,2021/1/7 14:08,0,2021/3/26 13:58
+836,PK50001A100000571,2020/7/14 10:23,2020/12/26 10:30,1,
+837,PK50001A100000572,2020/4/11 13:45,2021/1/18 14:52,1,
+838,PK50001A100000573,2020/8/15 10:47,,1,
+839,PK50001A100000574,2020/11/7 10:18,2020/12/7 13:43,0,2021/4/12
+840,PK50001A100000576,2020/9/18 18:25,,1,
+841,PK50001A100000577,2020/8/27 18:07,,0,2021/6/2
+842,PK50001A100000578,2020/9/1 10:12,2020/12/4 17:30,1,
+843,PK50001A100000580,2020/9/18 18:16,,1,
+844,PK50001A100000581,2020/7/29 17:43,2021/6/30 13:40,1,
+845,PK50001A100000582,2020/7/14 10:22,2020/9/11 16:46,1,
+846,PK50001A100000583,2020/7/25 11:30,2020/10/28 10:07,0,2020/12/23 10:07
+847,PK50001A100000584,2020/9/29 12:28,,1,
+848,PK50001A100000585,2020/10/31 21:32,2021/6/13 18:12,1,
+849,PK50001A100000586,2020/4/16 15:49,2020/6/13 14:08,0,2020/8/7 17:01
+850,PK50001A100000587,2020/11/22 19:57,2021/3/17 12:43,0,2021/3/26 15:50
+851,PK50001A100000588,2020/9/17 14:43,2021/3/29 10:48,1,
+852,PK50001A100000593,2020/5/15 16:59,2021/1/21 13:22,0,2021/4/12 13:22
+853,PK50001A100000594,2020/6/27 20:23,2021/7/6 8:34,1,
+854,PK50001A100000595,2020/8/21 22:07,2021/7/18 10:45,1,
+855,PK50001A100000599,2020/7/30 14:55,2021/6/29 14:14,1,
+856,PK50001A100000600,2020/8/28 12:30,2021/1/29 10:09,0,2021/6/2
+857,PK50001A100000602,2020/8/1 16:44,2021/7/1 17:05,1,
+858,PK50001A100000603,2020/8/4 10:51,2021/6/27 13:37,1,
+859,PK50001A100000605,2020/6/5 15:08,2021/5/29 16:33,1,
+860,PK50001A100000606,2020/9/1 12:58,2021/7/23 15:59,1,
+861,PK50001A100000609,2020/9/1 13:00,2021/5/9 14:02,1,
+862,PK50001A100000610,2020/7/30 14:03,2021/6/29 13:52,1,
+863,PK50001A100000611,2020/4/29 15:25,2020/6/7 10:06,0,2020/6/10 10:06
+864,PK50001A100000613,2020/11/16 23:43,2021/6/10 13:55,1,
+865,PK50001A100000615,2020/7/25 8:57,2021/7/9 12:50,1,
+866,PK50001A100000617,2020/9/27 9:25,2021/1/24 16:14,0,2021/6/2
+867,PK50001A100000618,2020/10/1 16:23,2021/4/10 22:34,1,
+868,PK50001A100000619,2020/9/11 16:48,,1,
+869,PK50001A100000620,2020/10/27 16:19,2021/6/10 17:33,1,
+870,PK50001A100000622,2020/9/28 13:10,2021/3/25 10:53,1,
+871,PK50001A100000623,2020/9/13 11:15,2021/6/3 16:54,0,2021/6/2
+872,PK50001A100000624,2020/9/8 18:29,,1,
+873,PK50001A100000627,2020/9/9 14:46,2021/5/17 9:51,1,
+874,PK50001A100000629,2020/9/12 17:23,2021/5/26 10:12,1,
+875,PK50001A100000632,2020/9/9 17:24,2021/4/10 18:53,0,2021/4/12
+876,PK50001A100000633,2020/7/24 17:26,2021/4/3 8:37,0,2021/4/12
+877,PK50001A100000634,2020/9/15 15:55,,1,
+878,PK50001A100000635,2021/1/14 18:22,2021/5/12 17:33,1,
+879,PK50001A100000636,2020/7/27 19:11,2021/4/16 17:29,1,
+880,PK50001A100000638,2020/9/20 18:33,2021/1/17 22:48,1,
+881,PK50001A100000640,2020/7/13 17:11,2020/11/15 14:29,1,
+882,PK50001A100000641,2020/10/27 14:53,2021/6/10 17:33,1,
+883,PK50001A100000643,2020/7/18 13:34,2021/6/27 21:00,1,
+884,PK50001A100000644,2020/8/8 19:33,2021/4/16 17:29,1,
+885,PK50001A100000645,2020/9/17 12:18,2021/7/13 16:01,1,
+886,PK50001A100000646,2020/9/10 17:32,2021/2/21 16:55,0,2021/3/26 15:50
+887,PK50001A100000648,2020/7/31 11:57,2021/6/9 16:38,1,
+888,PK50001A100000649,2020/6/2 13:30,2021/7/11 20:25,1,
+889,PK50001A100000650,2020/6/19 15:03,2021/6/15 16:27,1,
+890,PK50001A100000651,2020/6/13 14:08,2020/6/15 17:01,0,2020/8/7 17:01
+891,PK50001A100000652,2020/6/11 20:02,2021/5/22 21:51,0,2021/7/13
+892,PK50001A100000654,2020/6/15 13:35,2020/8/26 22:11,0,2020/8/27 9:31
+893,PK50001A100000655,2020/9/3 9:19,2020/10/29 12:20,1,
+894,PK50001A100000656,2020/6/8 17:36,2020/12/21 15:06,0,2021/3/26 13:58
+895,PK50001A100000658,2020/9/22 10:12,2021/4/10 10:00,0,2021/4/12
+896,PK50001A100000659,2020/6/19 18:53,2021/5/25 15:14,1,
+897,PK50001A100000662,2020/9/24 19:44,2021/5/19 14:25,1,
+898,PK50001A100000664,2020/9/18 18:16,2021/2/1 17:34,0,2021/1/22 21:39
+899,PK50001A100000665,2020/9/9 18:42,2021/5/22 12:22,1,
+900,PK50001A100000666,2020/9/2 12:34,2020/10/29 10:23,0,2021/4/12
+901,PK50001A100000667,2020/12/3 13:05,2021/6/24 10:31,1,
+902,PK50001A100000669,2020/9/18 18:14,,1,
+903,PK50001A100000670,2020/8/14 12:32,2021/7/13 15:22,1,
+904,PK50001A100000671,2020/9/23 19:14,2020/11/19 21:39,0,2020/12/23 21:39
+905,PK50001A100000673,2020/5/22 15:46,2021/1/9 13:15,1,
+906,PK50001A100000674,2020/7/30 19:42,,1,
+907,PK50001A100000675,2020/9/2 12:34,2020/10/29 10:23,1,
+908,PK50001A100000676,2020/9/20 21:45,2021/4/9 17:08,0,2021/6/2
+909,PK50001A100000677,2020/9/18 18:15,,1,
+910,PK50001A100000678,2020/10/12 11:10,2021/7/13 9:51,1,
+911,PK50001A100000679,2020/9/18 18:17,,1,
+912,PK50001A100000680,2020/9/18 18:25,2021/4/12 16:01,1,
+913,PK50001A100000681,2020/9/25 14:08,2021/4/5 16:38,1,
+914,PK50001A100000682,2020/7/11 14:33,2021/1/12 18:11,1,
+915,PK50001A100000685,2020/6/2 17:56,2020/11/24 19:16,0,2020/12/23 13:34
+916,PK50001A100000686,2020/10/19 16:42,2021/7/18 10:44,1,
+917,PK50001A100000687,2020/9/18 18:21,,1,
+918,PK50001A100000688,2020/6/10 8:48,2020/10/27 16:10,1,
+919,PK50001A100000689,2020/11/19 14:14,2021/2/1 11:35,1,
+920,PK50001A100000690,2020/7/25 15:33,2021/4/27 15:51,0,2021/6/2
+921,PK50001A100000692,2021/3/24 9:18,,1,
+922,PK50001A100000693,2020/9/22 20:48,,1,
+923,PK50001A100000694,2020/9/14 20:19,2021/1/13 20:47,1,
+924,PK50001A100000695,2020/11/1 15:53,2021/5/11 10:10,1,
+925,PK50001A100000696,2020/10/19 16:53,2021/4/2 12:01,0,2021/6/2
+926,PK50001A100000697,2020/8/30 16:16,2021/3/2 10:47,1,
+927,PK50001A100000698,2020/6/13 14:51,2021/5/26 9:20,1,
+928,PK50001A100000699,2020/8/31 10:18,2021/7/6 10:26,1,
+929,PK50001A100000700,2020/9/2 10:49,2020/9/15 14:53,1,
+930,PK50001A100000701,2020/9/17 20:21,2021/4/4 17:01,1,
+931,PK50001A100000702,2020/11/4 15:47,2021/7/1 16:20,1,
+932,PK50001A100000704,2020/9/12 10:56,2021/4/11 14:00,1,
+933,PK50001A100000706,2020/9/17 12:17,2021/7/21 13:54,1,
+934,PK50001A100000708,2020/7/18 11:10,2021/2/26 16:56,0,2021/3/26 13:58
+935,PK50001A100000710,2020/10/31 0:00,2021/4/6 14:35,1,
+936,PK50001A100000711,2020/11/4 11:50,2020/11/5 13:54,0,2020/12/23 13:34
+937,PK50001A100000713,2020/10/18 17:21,2021/5/22 21:45,1,
+938,PK50001A100000714,2021/2/26 15:23,2021/7/2 11:38,1,
+939,PK50001A100000728,2020/10/31 0:06,2021/1/12 11:13,1,
+940,PK50001A100000729,2020/11/24 14:15,2021/4/8 13:17,1,
+941,PK500A20100000732,2021/6/22 9:43,,1,
+942,PK500A20100000733,2021/6/6 15:37,,1,
+943,PK500A20100000734,2021/6/21 15:28,,1,
+944,PK500A20100000735,2021/5/18 10:42,,1,
+945,PK500A20100000743,2021/6/22 9:41,,1,
+946,PK500A20100000748,2021/5/2 18:46,,1,
+947,PK500A20100000750,2021/7/15 11:35,,1,
+948,PK500A20100000751,2021/5/10 14:07,2021/5/11 12:39,0,2021/6/2
+949,PK500A20100000752,2021/7/19 16:15,,1,
+950,PK500A20100000755,2021/7/19 11:02,,1,
+951,PK500A20100000756,2021/4/30 8:55,2021/7/21 14:02,1,
+952,PK500A20100000758,2021/5/16 18:10,2021/7/15 9:51,1,
+953,PK500A20100000762,2021/7/24 14:16,,1,
+954,PK500A20100000764,2021/5/18 10:43,,1,
+955,PK500A20100000765,2021/7/14 11:43,,1,
+956,PK500A20100000766,2021/5/30 10:24,,1,
+957,PK500A20100000767,2021/7/14 17:00,,1,
+958,PK500A20100000772,2021/7/18 9:29,,1,
+959,PK500A20100000773,2021/6/12 14:58,,1,
+960,PK500A20100000779,2021/5/10 14:40,2021/7/13 11:29,1,
+961,PK500A20100000782,2021/7/15 9:51,,1,
+962,PK500A20100000783,2021/7/14 17:26,,1,
+963,PK500A20100000784,2021/5/16 14:17,2021/7/16 14:58,1,
+964,PK500A20100000787,2021/7/15 17:04,,1,
+965,PK500A20100000788,2021/5/10 14:07,2021/6/9 10:50,1,
+966,PK500A20100000794,2021/7/15 16:35,,1,
+967,PK500A20100000795,2021/5/25 15:14,,1,
+968,PK500A20100000796,2021/5/11 12:39,2021/6/9 10:50,1,
+969,PK500A20100000799,2021/5/31 11:18,,1,
+970,PK500A20100000800,2021/5/27 14:15,,1,
+971,PK500A20100000802,2021/7/19 19:08,,1,
+972,PK500A20100000809,2021/5/21 10:49,2021/5/21 18:29,0,2021/6/2
+973,PK500A20100000813,2021/5/17 16:46,2021/6/29 13:53,1,
+974,PK500A20100000814,2021/6/11 14:45,,1,
+975,PK500A20100000819,2021/6/17 17:02,2021/7/17 9:50,1,
+976,PK500A20100000821,2021/6/1 13:26,,1,
+977,PK500A20100000823,2021/4/27 12:44,,1,
+978,PK500A20100000829,2021/6/2 9:40,,1,
+979,PK500A20100000831,2021/6/17 12:15,2021/6/17 17:02,0,2021/7/13
+980,PK500A20100000832,2021/6/3 19:28,2021/7/3 18:42,1,
+981,PK500A20100000837,2021/7/14 11:39,2021/7/17 22:52,1,
+982,PK500A20100000840,2021/5/23 16:47,,1,
+983,PK500A20100000842,2021/6/26 10:59,,1,
+984,PK500A20100000844,2021/5/13 14:10,,1,
+985,PK500A20100000845,2021/6/20 16:28,,1,
+986,PK500A20100000848,2021/5/27 18:29,2021/7/5 18:54,1,
+987,PK500A20100000849,2021/7/21 16:04,,1,
+988,PK500A20100000850,2021/5/6 15:14,,1,
+989,PK500A20100000852,2021/6/5 16:40,,1,
+990,PK500A20100000853,2021/5/24 13:07,,1,
+991,PK500A20100000855,2021/5/20 11:04,,1,
+992,PK500A20100000858,2021/6/2 9:39,,1,
+993,PK500A20100000865,2021/7/16 14:58,,1,
+994,PK500A20100000910,2021/7/18 14:40,,1,
+995,PK500A20100000916,2021/7/16 11:58,,1,
+996,PK500A20100000921,2021/7/19 11:24,2021/7/21 18:40,1,
+997,PK500A20100000927,2021/7/19 19:06,,1,
+998,PK500A20100000928,2021/7/21 9:16,,1,
+999,PK500A20100000929,2021/7/22 14:42,,1,
+1000,PK500A20100000932,2021/7/20 10:16,,1,
+1001,PK500A20100000935,2021/7/24 10:37,,1,
+1002,PK501B00100004177,2020/12/23 8:22,2021/7/15 12:47,1,
+1003,PK50201A000002006,2021/1/14 11:24,2021/3/26 16:00,0,
+1004,PK50201A000002007,2020/8/29 19:10,2021/3/26 15:58,0,
+1005,PK50201A000002008,2020/7/19 21:15,2021/6/24 18:44,0,
+1006,PK50201A000002009,2020/5/25 16:33,2021/2/25 12:27,0,
+1007,PK50201A000002011,2020/7/19 21:25,2021/3/26 15:58,0,
+1008,PK50201A000002012,2020/8/5 9:25,2020/9/22 10:24,0,
+1009,PK50201A000002014,2020/10/31 16:09,2021/6/2 16:15,0,
+1010,PK50201A000002015,2020/5/27 8:59,2021/3/26 15:55,0,
+1011,PK50201A000002016,2020/7/28 17:07,2021/6/2 16:16,0,
+1012,PK50201A000002017,2021/2/18 15:08,2021/6/2 16:14,0,
+1013,PK50201A000002018,2020/7/16 14:30,2020/8/18 9:00,0,
+1014,PK50201A000002020,2020/12/30 9:59,2021/3/26 15:59,0,
+1015,PK50201A000002021,2020/7/2 14:12,2021/6/2 16:15,0,
+1016,PK50201A000002022,2020/7/6 15:55,2021/6/2 16:17,0,
+1017,PK50201A000002023,2020/7/2 13:03,2021/3/25 13:16,0,
+1018,PK50201A000002024,2020/5/26 11:14,2020/7/28 17:46,0,
+1019,PK50201A000002026,2020/8/19 11:01,2021/3/26 15:57,0,
+1020,PK50201A000002028,2020/8/5 14:58,2021/3/26 16:00,0,
+1021,PK50201A000002029,2021/1/3 14:58,2021/3/26 15:58,0,
+1022,PK50201A000002030,2021/1/14 11:15,2021/2/7 16:30,0,
+1023,PK50201A000002031,2021/1/12 11:18,2021/6/2 16:15,0,
+1024,PK50201A000002032,2020/5/22 10:06,2021/3/26 15:55,0,
+1025,PK50201A000002034,2020/7/27 17:28,2021/3/26 15:57,0,
+1026,PK50201A000002035,2020/7/6 10:16,2021/3/28 13:16,0,
+1027,PK50201A000002036,2020/5/23 19:20,2021/6/2 16:16,0,
+1028,PK50201A000002037,2020/8/26 13:25,2021/6/2 16:15,0,
+1029,PK50201A000002038,2021/1/10 10:45,2021/3/26 15:59,0,
+1030,PK50201A000002039,2021/1/15 9:40,2021/3/30 13:12,0,
+1031,PK50201A000002040,2020/10/9 17:37,2021/6/2 16:15,0,
+1032,PK50201A000002041,2021/2/9 15:48,2021/6/2 16:16,0,
+1033,PK50201A000002043,2020/5/21 21:18,2021/3/26 15:59,0,
+1034,PK50201A000002044,2021/3/8 11:21,2021/3/25 13:17,0,
+1035,PK50201A000002045,2021/2/24 12:35,,0,
+1036,PK50201A000002046,2020/8/28 16:27,2021/3/26 15:58,0,
+1037,PK50201A000002047,2020/8/16 23:14,2021/3/26 15:56,0,
+1038,PK50201A000002048,2020/9/29 19:00,2021/6/2 16:17,0,
+1039,PK50201A000002049,2020/7/18 8:12,2021/2/18 16:43,0,
+1040,PK50201A000002050,2021/2/18 12:25,2021/3/16 12:19,0,
+1041,PK50201A000002051,2020/5/25 16:24,2021/3/26 15:58,0,
+1042,PK50201A000002052,2020/6/18 16:19,2021/6/2 16:16,0,
+1043,PK50201A000002053,2021/1/13 14:15,2021/1/23 11:22,0,
+1044,PK50201A000002054,2020/7/30 10:43,2021/3/26 15:58,0,
+1045,PK50201A000002055,2021/2/3 12:09,2021/6/2 16:15,0,
+1046,PK50201A000002057,2020/9/13 14:28,2020/10/16 16:13,0,
+1047,PK50201A000002058,2020/11/27 23:52,2021/6/2 16:14,0,
+1048,PK50201A000002059,2021/3/6 15:42,,0,
+1049,PK50201A000002060,2020/5/21 14:03,2020/6/8 15:22,0,
+1050,PK50201A000002062,2021/1/5 10:31,,0,
+1051,PK50201A000002063,2020/9/25 17:25,2021/3/26 15:58,0,
+1052,PK50201A000002064,2020/5/21 21:06,2021/3/22 11:38,0,
+1053,PK50201A000002065,2021/2/8 15:12,2021/6/2 16:17,0,
+1054,PK50201A000002066,2020/7/3 22:58,2021/3/26 15:59,0,
+1055,PK50201A000002067,2020/7/4 13:29,2021/6/2 16:15,0,
+1056,PK50201A000002068,2020/9/24 10:16,2020/11/3 14:14,0,
+1057,PK50201A000002069,2020/5/20 15:04,2020/9/23 9:29,0,
+1058,PK50201A000002070,2020/8/7 22:51,2020/9/24 13:01,0,
+1059,PK50201A000002071,2021/1/16 14:33,2021/1/17 10:41,0,
+1060,PK50201A000002073,2020/7/8 15:21,2021/3/26 15:56,0,
+1061,PK50201A000002078,2020/6/25 15:52,2021/1/23 11:24,0,
+1062,PK50201A000002080,2021/3/14 12:42,2021/6/2 16:16,0,
+1063,PK50201A000002081,2021/1/3 10:40,2021/3/26 15:57,0,
+1064,PK50201A000002082,2020/10/21 20:49,2021/3/26 15:57,0,
+1065,PK50201A000002083,2020/8/17 12:57,2021/3/26 15:59,0,
+1066,PK50201A000002084,2020/6/20 17:18,2020/7/28 10:57,0,
+1067,PK50201A000002086,2020/7/3 20:17,2021/3/26 15:59,0,
+1068,PK50201A000002087,2020/10/13 19:01,2021/6/2 16:14,0,
+1069,PK50201A000002088,2020/7/1 11:42,2021/3/26 15:56,0,
+1070,PK50201A000002089,2020/9/30 9:58,2021/1/17 12:53,0,
+1071,PK50201A000002090,2020/10/15 11:51,2021/1/23 11:22,0,
+1072,PK50201A000002091,2020/8/19 14:27,2020/9/23 9:29,0,
+1073,PK50201A000002093,2020/7/3 11:35,2021/3/26 15:58,0,
+1074,PK50201A000002094,2021/1/6 16:52,2021/6/2 16:14,0,
+1075,PK50201A000002095,2020/5/21 17:58,2020/8/4 11:14,0,
+1076,PK50201A000002096,2020/7/3 21:01,2021/2/18 16:43,0,
+1077,PK50201A000002097,2021/1/2 14:44,2021/3/26 15:58,0,
+1078,PK50201A000002098,2020/5/28 15:46,2020/9/23 9:29,0,
+1079,PK50201A000002100,2021/1/3 16:37,2021/3/26 15:59,0,
+1080,PK50201A000002101,2020/9/22 17:19,2021/3/26 16:00,0,
+1081,PK50201A000002102,2020/9/19 9:58,2021/3/4 15:21,0,
+1082,PK50201A000002103,2020/7/18 13:15,2021/3/8 12:55,0,
+1083,PK50201A000002104,2020/8/18 16:02,2020/9/23 9:29,0,
+1084,PK50201A000002105,2020/5/30 9:17,2021/3/26 15:58,0,
+1085,PK50201A000002106,2020/9/7 12:55,2021/3/16 13:59,0,
+1086,PK50201A000002107,2020/8/21 11:25,2021/3/26 15:55,0,
+1087,PK50201A000002108,2020/7/4 13:25,2020/8/12 9:01,0,
+1088,PK50201A000002109,2020/5/20 10:48,2021/3/26 15:58,0,
+1089,PK50201A000002110,2020/10/9 17:35,2021/3/26 15:58,0,
+1090,PK50201A000002111,2020/5/22 17:40,2020/10/20 15:01,0,
+1091,PK50201A000002113,2021/5/27 13:19,,0,
+1092,PK50201A000002114,2020/10/3 9:28,2021/6/2 16:15,0,
+1093,PK50201A000002116,2020/9/4 10:18,2021/6/2 16:16,0,
+1094,PK50201A000002117,2020/7/31 14:22,2021/3/26 15:58,0,
+1095,PK50201A000002118,2020/12/31 19:48,2021/3/26 15:57,0,
+1096,PK50201A000002119,2021/6/5 7:57,,0,
+1097,PK50201A000002121,2020/8/19 15:04,2021/3/22 11:38,0,
+1098,PK50201A000002122,2021/1/2 15:56,2021/3/26 15:57,0,
+1099,PK50201A000002123,2020/7/5 16:14,2020/9/24 13:01,0,
+1100,PK50201A000002124,2020/6/6 21:41,2020/8/7 15:48,0,
+1101,PK50201A000002125,2020/5/27 15:03,,0,
+1102,PK50201A000002126,2020/8/4 15:04,2021/5/28 14:24,0,
+1103,PK50201A000002127,2020/9/4 13:16,2021/3/5 16:42,0,
+1104,PK50201A000002128,2020/8/12 15:37,2020/9/14 18:03,0,
+1105,PK50201A000002130,2020/9/6 13:40,2020/10/7 8:38,0,
+1106,PK50201A000002131,2020/5/21 22:24,2021/6/2 16:17,0,
+1107,PK50201A000002132,2020/9/5 14:25,2021/3/4 11:18,0,
+1108,PK50201A000002133,2020/6/1 14:11,2021/6/2 16:15,0,
+1109,PK50201A000002135,2020/7/2 16:15,2021/6/2 16:14,0,
+1110,PK50201A000002136,2020/5/30 15:21,2021/3/26 15:58,0,
+1111,PK50201A000002137,2020/5/20 13:09,2021/6/2 16:17,0,
+1112,PK50201A000002138,2020/7/8 8:48,2020/7/8 11:29,0,
+1113,PK50201A000002139,2021/1/6 16:41,2021/4/14 14:46,0,
+1114,PK50201A000002140,2020/12/9 11:32,2021/3/26 15:56,0,
+1115,PK50201A000002141,2020/11/23 17:16,2021/3/30 13:12,0,
+1116,PK50201A000002143,2020/8/26 11:13,2021/3/26 15:59,0,
+1117,PK50201A000002144,2020/11/15 16:46,2021/3/26 15:56,0,
+1118,PK50201A000002145,2020/7/13 17:48,2021/3/26 15:59,0,
+1119,PK50201A000002146,2021/1/9 14:47,2021/3/26 15:58,0,
+1120,PK50201A000002149,2020/8/2 18:10,2020/10/7 8:39,0,
+1121,PK50201A000002150,2021/2/23 10:57,2021/6/2 16:15,0,
+1122,PK50201A000002151,2020/11/16 22:18,2021/3/26 15:56,0,
+1123,PK50201A000002152,2021/1/8 12:59,2021/6/2 16:15,0,
+1124,PK50201A000002154,2020/9/21 14:54,2021/6/2 16:17,0,
+1125,PK50201A000002155,2020/8/2 21:09,2020/9/24 13:01,0,
+1126,PK50201A000002156,2020/8/10 15:59,2020/11/2 14:58,0,
+1127,PK50201A000002157,2020/10/30 17:08,2021/1/29 10:31,0,
+1128,PK50201A000002160,2020/8/25 17:18,2021/6/2 16:15,0,
+1129,PK50201A000002162,2020/12/13 20:25,2021/6/2 16:16,0,
+1130,PK50201A000002163,2020/10/21 18:44,2021/3/26 15:57,0,
+1131,PK50201A000002164,2020/8/12 15:45,2021/6/2 16:15,0,
+1132,PK50201A000002165,2020/9/19 11:50,2020/10/20 14:48,0,
+1133,PK50201A000002166,2020/7/27 19:28,2021/3/26 15:56,0,
+1134,PK50201A000002167,2020/8/12 16:35,2021/6/2 16:16,0,
+1135,PK50201A000002168,2020/11/1 13:19,2021/6/2 16:17,0,
+1136,PK50201A000002169,2020/10/12 10:33,,0,
+1137,PK50201A000002170,2020/10/7 17:03,2020/11/8 17:31,0,
+1138,PK50201A000002171,2020/10/12 11:00,2021/3/26 15:58,0,
+1139,PK50201A000002172,2020/10/21 17:09,2021/3/26 15:58,0,
+1140,PK50201A000002173,2020/8/28 10:00,2021/6/2 16:15,0,
+1141,PK50201A000002174,2021/1/3 22:14,2021/6/2 16:15,0,
+1142,PK50201A000002175,2020/10/25 12:12,2021/3/4 11:18,0,
+1143,PK50201A000002177,2020/8/19 10:28,2020/9/23 9:30,0,
+1144,PK50201A000002180,2021/1/9 10:22,2021/3/26 15:58,0,
+1145,PK50201A000002181,2020/11/21 14:20,2021/6/2 16:17,0,
+1146,PK50201A000002182,2020/8/23 9:44,2021/2/3 12:00,0,
+1147,PK50201A000002183,2020/7/31 14:21,2020/9/24 13:01,0,
+1148,PK50201A000002185,2021/2/24 12:21,,0,
+1149,PK50201A000002186,2020/8/22 15:14,2021/6/2 16:16,0,
+1150,PK50201A000002187,2020/6/20 14:36,2020/9/22 11:38,0,
+1151,PK50201A000002188,2020/11/1 12:57,2021/6/2 16:17,0,
+1152,PK50201A000002189,2021/3/17 18:33,,0,
+1153,PK50201A000002190,2020/7/31 13:56,2020/9/1 9:01,0,
+1154,PK50201A000002191,2020/9/19 15:47,2021/6/2 16:15,0,
+1155,PK50201A000002192,2021/1/3 22:05,2021/3/26 15:58,0,
+1156,PK50201A000002193,2021/1/1 17:05,2021/3/26 15:57,0,
+1157,PK50201A000002194,2021/4/29 15:59,2021/6/2 16:14,0,
+1158,PK50201A000002195,2020/8/22 14:31,2021/3/26 15:59,0,
+1159,PK50201A000002196,2021/3/8 10:46,,0,
+1160,PK50201A000002197,2020/8/26 13:26,2021/6/2 16:16,0,
+1161,PK50201A000002198,2021/3/2 11:41,2021/6/2 16:17,0,
+1162,PK50201A000002199,2020/10/20 14:54,2021/3/26 15:56,0,
+1163,PK50201A000002200,2021/1/11 10:37,2021/6/2 16:15,0,
+1164,PK50201A000002201,2020/10/3 13:56,2021/6/2 16:17,0,
+1165,PK50201A000002202,2021/3/14 12:41,2021/6/2 16:16,0,
+1166,PK50201A000002203,2020/11/20 17:01,2021/6/2 16:15,0,
+1167,PK50201A000002204,2020/11/18 13:24,2021/3/26 15:59,0,
+1168,PK50301A000001002,2020/4/19 19:40,2020/8/17 11:23,0,
+1169,PK50301A000001004,2020/2/21 14:50,2020/2/28 15:25,0,
+1170,PK50301A000001005,2020/3/23 10:08,2020/8/17 11:22,0,
+1171,PK50301A000001006,2020/3/27 19:24,2021/1/8 23:21,0,
+1172,PK50301A000001009,2020/3/21 10:10,2020/4/19 19:40,0,
+1173,PK50301A000001010,2020/4/8 19:18,2020/7/13 13:22,0,
+1174,PK50301A000001011,2020/2/28 21:11,2020/8/3 17:52,0,
+1175,PK50301A000001012,2020/7/14 21:31,2020/8/17 11:15,0,
+1176,PK50301A000001013,2020/3/8 10:29,2020/3/22 8:51,0,
+1177,PK50301A000001014,2020/3/7 13:23,2020/8/8 12:44,0,
+1178,PK50301A000001015,2020/2/28 15:09,2020/7/8 20:29,0,
+1179,PK50301A000001016,2020/3/5 19:36,2020/8/2 14:39,0,
+1180,PK50301A000001017,2020/5/20 12:17,2021/5/26 11:15,0,2021/6/2 15:36
+1181,PK50301A000001018,2020/3/12 9:29,2020/11/3 11:52,1,
+1182,PK50301A000001019,2020/2/29 16:29,2020/7/31 20:09,0,
+1183,PK50301A000001020,2020/3/6 12:35,2020/6/10 14:24,0,
+1184,PK50301A000001021,2020/3/1 19:10,2020/7/30 13:43,0,
+1185,PK50301A000001022,2020/3/9 16:37,2020/8/4 14:17,0,
+1186,PK50301A000001023,2020/3/10 16:52,2020/7/29 20:21,0,
+1187,PK50301A000001024,2020/3/12 10:11,2020/12/17 10:42,0,
+1188,PK50301A000001025,2020/3/22 14:54,2020/8/7 21:33,0,
+1189,PK50301A000001026,2020/3/15 7:40,2021/1/30 21:48,0,
+1190,PK50301A000001027,2020/2/28 15:25,,0,
+1191,PK50301A000001028,2020/3/6 18:44,2020/6/15 10:26,0,
+1192,PK50301A000001029,2020/3/2 18:41,2021/6/27 10:56,1,
+1193,PK50301A000001030,2020/3/13 16:50,2020/8/9 10:21,0,
+1194,PK50301A000001031,2020/3/7 16:48,2020/8/15 10:43,0,
+1195,PK50301A000001032,2020/3/8 10:30,2020/8/4 17:51,0,
+1196,PK50301A000001033,2020/3/11 20:41,2020/8/6 22:34,0,
+1197,PK50301A000001034,2020/3/10 15:13,2020/11/3 9:16,0,
+1198,PK50301A000001035,2020/3/21 17:20,2020/8/3 11:19,0,
+1199,PK504B00100004002,2020/8/31 16:40,2021/7/5 11:29,1,
+1200,PK504B00100004003,2020/9/2 14:53,2021/3/26 18:10,0,2021/3/26
+1201,PK504B00100004004,2020/9/16 16:39,2021/6/4 16:57,1,
+1202,PK504B00100004005,2020/8/20 20:23,2021/6/8 12:49,1,
+1203,PK504B00100004007,2020/10/11 12:34,2021/5/18 11:30,1,
+1204,PK504B00100004009,2020/8/10 23:31,2021/7/3 19:01,1,
+1205,PK504B00100004010,2020/8/5 21:14,2021/7/9 16:40,1,
+1206,PK504B00100004011,2020/8/11 9:39,,1,
+1207,PK504B00100004012,2020/9/1 10:49,2020/12/9 10:00,1,
+1208,PK504B00100004014,2020/8/7 19:28,2020/8/13 14:32,1,
+1209,PK504B00100004015,2020/8/7 21:33,2021/3/2 14:11,1,
+1210,PK504B00100004016,2020/7/28 13:53,,1,
+1211,PK504B00100004017,2020/8/4 14:43,2021/6/22 10:51,1,
+1212,PK504B00100004018,2020/8/7 19:30,2021/6/23 15:27,1,
+1213,PK504B00100004019,2020/8/19 13:05,2021/5/1 9:28,1,
+1214,PK504B00100004020,2020/8/20 17:42,2021/6/23 15:27,1,
+1215,PK504B00100004021,2020/8/17 17:47,2020/12/4 14:28,1,
+1216,PK504B00100004022,2020/8/27 8:32,2021/6/5 19:50,1,
+1217,PK504B00100004023,2020/8/4 17:51,,1,
+1218,PK504B00100004024,2020/8/19 11:02,2021/2/23 12:52,1,
+1219,PK504B00100004027,2020/8/16 13:46,2021/5/16 17:13,1,
+1220,PK504B00100004028,2020/8/8 10:10,2021/5/5 15:57,1,
+1221,PK504B00100004029,2020/8/2 14:26,2020/12/21 11:28,1,
+1222,PK504B00100004030,2020/7/30 14:55,2021/4/23 15:12,1,
+1223,PK504B00100004031,2020/9/4 16:29,2021/6/4 16:40,1,
+1224,PK504B00100004032,2020/8/7 15:30,2021/4/1 17:11,0,2021/4/12 17:11
+1225,PK504B00100004033,2020/8/6 22:34,2021/6/24 15:17,1,
+1226,PK504B00100004034,2020/8/22 9:24,2021/5/27 11:32,1,
+1227,PK504B00100004035,2020/8/2 13:24,2020/11/18 11:51,1,
+1228,PK504B00100004036,2020/8/10 11:10,2021/7/23 11:17,1,
+1229,PK504B00100004037,2020/8/26 13:34,2021/3/31 15:46,1,
+1230,PK504B00100004038,2020/8/19 17:33,2020/9/18 16:27,1,
+1231,PK504B00100004040,2020/8/9 9:52,2021/5/25 17:47,1,
+1232,PK504B00100004041,2020/8/10 19:08,,1,
+1233,PK504B00100004042,2020/8/30 12:18,2021/1/31 15:39,1,
+1234,PK504B00100004043,2020/8/18 18:14,2020/11/2 14:54,1,
+1235,PK504B00100004044,2020/9/10 22:16,2021/6/23 17:29,1,
+1236,PK504B00100004045,2020/7/1 20:16,2021/5/13 15:22,1,
+1237,PK504B00100004046,2020/8/22 9:45,2021/5/31 22:26,1,
+1238,PK504B00100004047,2020/7/29 9:04,2020/11/3 18:23,1,
+1239,PK504B00100004048,2020/8/11 9:00,2020/12/9 10:04,1,
+1240,PK504B00100004049,2020/8/18 16:50,2021/6/18 12:38,1,
+1241,PK504B00100004050,2020/8/17 12:11,2021/7/23 19:12,1,
+1242,PK504B00100004051,2020/8/15 21:42,2021/6/12 20:23,0,2021/7/13
+1243,PK504B00100004052,2020/8/10 20:47,2021/6/4 15:51,1,
+1244,PK504B00100004053,2020/8/16 11:17,2020/12/15 9:04,1,
+1245,PK504B00100004054,2020/8/10 13:17,2021/6/20 13:05,1,
+1246,PK504B00100004055,2020/8/15 19:32,2021/6/27 16:11,1,
+1247,PK504B00100004056,2020/8/10 9:44,2021/5/27 14:35,1,
+1248,PK504B00100004057,2020/8/6 16:51,2021/5/12 9:38,1,
+1249,PK504B00100004058,2020/7/31 14:47,2021/5/7 14:00,1,
+1250,PK504B00100004059,2020/8/2 13:15,2021/5/30 14:27,1,
+1251,PK504B00100004060,2020/8/20 18:45,2021/7/2 16:30,1,
+1252,PK504B00100004061,2020/7/28 17:35,2021/6/24 15:20,1,
+1253,PK504B00100004062,2020/8/15 13:14,2021/6/23 17:11,0,2021/7/13
+1254,PK504B00100004064,2020/8/10 15:46,2020/10/17 16:08,0,2020/10/19 21:46
+1255,PK504B00100004065,2020/8/19 17:50,2020/11/5 19:00,1,
+1256,PK504B00100004066,2020/8/18 10:31,2020/12/26 20:57,0,2021/3/26 20:57
+1257,PK504B00100004067,2020/9/1 16:18,2021/5/19 14:55,1,
+1258,PK504B00100004068,2020/8/7 12:53,2021/6/25 16:37,1,
+1259,PK504B00100004069,2020/7/30 19:21,2020/12/12 18:45,1,
+1260,PK504B00100004070,2020/8/21 20:43,2021/1/22 14:14,1,
+1261,PK504B00100004071,2020/8/4 14:17,,1,
+1262,PK504B00100004073,2020/8/6 15:03,2021/4/11 9:53,1,
+1263,PK504B00100004074,2020/8/7 12:54,2021/4/17 17:32,1,
+1264,PK504B00100004075,2020/8/2 20:02,2020/12/30 13:31,1,
+1265,PK504B00100004076,2020/8/3 17:52,2021/7/22 17:05,1,
+1266,PK504B00100004077,2020/7/29 20:21,2021/7/2 10:13,1,
+1267,PK504B00100004078,2020/8/17 14:16,2021/7/16 13:43,1,
+1268,PK504B00100004079,2020/8/15 19:58,2021/6/19 15:25,1,
+1269,PK504B00100004080,2020/8/16 14:27,2021/7/17 11:16,1,
+1270,PK504B00100004081,2020/8/30 15:00,2021/4/27 9:38,1,
+1271,PK504B00100004082,2020/8/14 10:27,2021/3/27 19:57,1,
+1272,PK504B00100004083,2020/8/6 10:31,2021/7/7 10:33,1,
+1273,PK504B00100004084,2020/9/7 12:24,2020/12/6 10:36,1,
+1274,PK504B00100004085,2020/8/4 13:45,2021/7/20 9:06,1,
+1275,PK504B00100004086,2020/8/8 14:08,2021/5/26 21:00,0,2021/7/13
+1276,PK504B00100004087,2020/7/28 13:46,2021/3/17 14:45,1,
+1277,PK504B00100004088,2020/8/8 13:10,2021/7/8 12:10,1,
+1278,PK504B00100004089,2020/8/2 13:25,2021/5/5 15:53,1,
+1279,PK504B00100004090,2020/8/5 13:57,2021/5/28 14:48,1,
+1280,PK504B00100004091,2020/8/11 13:16,2021/4/27 21:26,0,2021/6/2 15:36
+1281,PK504B00100004092,2020/8/25 19:12,2021/6/10 10:16,1,
+1282,PK504B00100004093,2020/8/21 16:13,2021/7/15 11:19,1,
+1283,PK504B00100004094,2020/7/30 20:22,2021/7/20 14:23,1,
+1284,PK504B00100004095,2020/8/18 16:44,2021/5/2 18:57,1,
+1285,PK504B00100004096,2020/10/22 10:19,2021/3/27 14:25,1,
+1286,PK504B00100004097,2020/8/2 11:14,2021/3/20 16:30,1,
+1287,PK504B00100004098,2020/8/17 19:39,2021/7/4 12:10,1,
+1288,PK504B00100004099,2020/7/20 16:43,,1,
+1289,PK504B00100004100,2020/8/25 19:10,2021/1/23 15:47,1,
+1290,PK504B00100004101,2020/8/11 19:49,2021/4/21 16:36,1,
+1291,PK504B00100004102,2020/7/31 20:09,2020/10/10 9:51,1,
+1292,PK504B00100004103,2020/8/22 18:09,2021/5/25 16:51,1,
+1293,PK504B00100004105,2020/8/27 14:13,2020/10/28 12:16,1,
+1294,PK504B00100004106,2020/10/1 12:22,2021/1/27 11:16,1,
+1295,PK504B00100004108,2020/10/27 11:16,,1,
+1296,PK504B00100004110,2020/9/1 10:13,2021/7/15 14:06,1,
+1297,PK504B00100004133,2020/10/7 10:57,2021/5/1 13:48,1,
+1298,PK504B00100004134,2020/10/23 14:50,,1,
+1299,PK504B00100004135,2020/10/9 12:40,2021/5/19 9:53,1,
+1300,PK504B00100004137,2020/10/27 12:48,2021/7/1 17:57,1,
+1301,PK504B00100004141,2020/10/26 21:01,,1,
+1302,PK504B00100004143,2020/10/8 11:47,2021/5/18 18:25,1,
+1303,PK504B00100004145,2020/10/10 9:51,2021/6/7 9:41,1,
+1304,PK504B00100004146,2020/10/23 11:59,2021/6/22 10:53,0,2021/7/13
+1305,PK504B00100004147,2020/10/14 21:02,2021/6/28 9:30,1,
+1306,PK504B00100004149,2020/10/14 16:33,2021/6/13 14:15,0,2021/7/13
+1307,PK504B00100004150,2020/10/8 13:24,2021/5/20 11:19,0,2021/6/2 15:36
+1308,PK504B00100004151,2020/10/6 20:46,2021/6/18 15:59,1,
+1309,PK504B00100004152,2020/10/9 11:49,,1,
+1310,PK504B00100004154,2020/10/7 21:04,2020/11/7 19:26,1,
+1311,PK504B00100004157,2020/10/8 19:05,2021/2/4 9:57,1,
+1312,PK504B00100004158,2020/10/6 15:57,2020/11/17 16:18,0,2020/12/2 21:46
+1313,PK504B00100004159,2020/10/15 19:23,2021/4/25 17:18,1,
+1314,PK504B00100004161,2020/10/9 11:16,2021/4/18 19:06,1,
+1315,PK504B00100004162,2020/10/10 18:32,2021/6/28 14:59,1,
+1316,PK504B00100004163,2020/10/24 15:49,2021/5/12 15:46,1,
+1317,PK504B00100004164,2020/10/9 13:00,,1,
+1318,PK504B00100004165,2020/10/30 10:31,2021/2/22 10:52,1,
+1319,PK504B00100004166,2020/10/9 12:54,2020/12/18 12:24,0,
+1320,PK504B00100004168,2020/11/5 14:20,2021/5/19 14:16,1,
+1321,PK504B00100004169,2020/10/11 15:38,2021/1/23 18:37,1,
+1322,PK504B00100004170,2020/10/15 13:38,2021/1/29 16:37,1,
+1323,PK504B00100004172,2020/10/14 17:43,,1,
+1324,PK504B00100004173,2020/10/27 10:09,2020/11/27 16:14,0,2020/12/2 21:46
+1325,PK504B00100004174,2020/10/17 20:31,2021/1/1 17:28,1,
+1326,PK504B00100004175,2021/1/5 11:06,2021/6/4 10:22,1,
+1327,PK504B00100004176,2020/10/17 18:30,2020/12/17 14:44,1,
+1328,PK504B00100004177,2020/10/23 14:24,2020/12/23 8:22,0,
+1329,PK504B00100004178,2021/1/13 16:25,2021/3/26 16:46,1,
+1330,PK504B00100004179,2020/10/12 22:26,2021/7/13 11:00,1,
+1331,PK504B00100004180,2020/11/6 14:26,2021/3/24 21:09,1,
+1332,PK504B00100004181,2020/10/12 19:54,2021/7/18 15:05,1,
+1333,PK504B00100004182,2020/10/9 17:23,2020/11/29 20:46,1,
+1334,PK504B00100004184,2020/10/30 17:16,2020/11/11 16:57,1,
+1335,PK504B00100004186,2020/10/11 14:13,2021/7/8 11:45,1,
+1336,PK504B00100004187,2020/10/14 15:03,2021/7/13 11:00,1,
+1337,PK504B00100004188,2020/12/31 18:24,2021/1/31 17:26,0,2021/3/26 20:57
+1338,PK504B00100004189,2020/11/1 16:00,2021/5/7 17:11,1,
+1339,PK504B00100004190,2020/10/12 16:46,2021/7/16 13:27,1,
+1340,PK504B00100004191,2020/10/19 13:43,2021/1/27 13:57,1,
+1341,PK504B00100004192,2020/10/17 16:08,2021/1/29 11:46,0,2021/3/26 20:57
+1342,PK504B00100004193,2020/10/15 15:21,2021/6/6 18:50,1,
+1343,PK504B00100004194,2020/10/12 16:01,2021/5/11 16:14,1,
+1344,PK504B00100004197,2020/10/23 14:49,2021/6/13 20:08,1,
+1345,PK504B00100004198,2020/10/9 16:27,2021/6/8 12:48,1,
+1346,PK504B00100004199,2020/10/14 16:38,2021/5/21 15:35,1,
+1347,PK504B00100004200,2020/10/9 17:17,2020/12/24 9:27,0,2021/3/26 20:57
+1348,PK504B00100004202,2020/10/15 18:32,,1,
+1349,PK504B00100004203,2020/10/29 12:15,2021/2/18 13:21,1,
+1350,PK504B00100004204,2020/10/15 13:08,2021/6/1 11:57,1,
+1351,PK504B00100004226,2020/12/30 11:35,2021/6/23 17:01,0,2021/7/13
+1352,PK504B00100004253,2021/1/1 16:51,,1,
+1353,PK504B00100004254,2020/12/25 18:58,,1,
+1354,PK504B00100004255,2021/1/8 23:22,2021/2/5 15:23,1,
+1355,PK504B00100004256,2021/3/11 9:57,,1,
+1356,PK504B00100004257,2020/12/30 13:31,2021/7/18 0:49,1,
+1357,PK504B00100004258,2020/12/30 11:18,2021/6/27 19:36,1,
+1358,PK504B00100004259,2021/1/29 18:52,2021/4/14 21:59,1,
+1359,PK504B00100004260,2021/1/8 10:10,2021/6/21 18:35,1,
+1360,PK504B00100004261,2020/12/30 15:46,2021/3/6 13:52,1,
+1361,PK504B00100004262,2021/1/8 21:22,2021/2/1 13:36,1,
+1362,PK504B00100004263,2020/12/30 15:16,2021/5/5 18:41,1,
+1363,PK504B00100004264,2020/12/30 16:28,,1,
+1364,PK504B00100004265,2020/12/30 17:28,2021/7/9 8:49,1,
+1365,PK504B00100004266,2021/1/11 16:52,2021/3/22 15:38,1,
+1366,PK504B00100004267,2020/12/30 16:37,2021/5/28 16:39,1,
+1367,PK504B00100004268,2020/12/30 11:01,,1,
+1368,PK504B00100004269,2021/1/23 18:07,2021/7/2 9:40,1,
+1369,PK504B00100004270,2020/12/25 14:50,2021/7/23 9:32,1,
+1370,PK504B00100004271,2021/1/1 11:35,2021/6/12 21:38,1,
+1371,PK504B00100004272,2021/1/8 15:22,2021/5/27 12:33,1,
+1372,PK504B00100004273,2021/1/6 15:31,2021/3/29 16:11,1,
+1373,PK504B00100004275,2020/12/30 16:19,2021/2/16 9:43,0,2021/3/26 20:57
+1374,PK504B00100004276,2020/12/30 16:00,2021/6/4 15:52,1,
+1375,PK504B00100004277,2020/12/30 15:14,2021/4/9 16:29,1,
+1376,PK504B00100004278,2020/12/30 11:27,,1,
+1377,PK504B00100004279,2020/12/30 10:57,2021/5/27 16:42,1,
+1378,PK504B00100004281,2020/12/28 18:06,2021/6/26 15:17,1,
+1379,PK504B00100004282,2020/12/30 16:11,2021/4/20 18:07,1,
+1380,PK504B00100004283,2021/1/8 23:21,2021/3/23 14:17,1,
+1381,PK504B00100004284,2021/1/29 13:53,2021/6/24 14:36,1,
+1382,PK504B00100004285,2020/12/30 11:58,2021/3/25 8:33,1,
+1383,PK504B00100004286,2020/12/28 12:09,2021/6/30 18:47,1,
+1384,PK504B00100004287,2021/1/1 10:39,2021/2/2 9:44,1,
+1385,PK504B00100004288,2020/12/30 14:27,2021/7/2 20:13,1,
+1386,PK504B00100004290,2020/12/30 15:42,2021/3/21 15:44,1,
+1387,PK504B10100003007,2021/7/5 13:30,,1,
+1388,PK504B10100003008,2021/7/12 12:13,,1,
+1389,PK504B10100003010,2021/7/8 16:06,,1,
+1390,PK504B10100003011,2021/7/1 10:49,,1,
+1391,PK504B10100003012,2021/7/5 10:31,,1,
+1392,PK504B10100003014,2021/7/12 12:31,2021/7/16 10:08,1,
+1393,PK504B10100003015,2021/7/23 18:55,,1,
+1394,PK504B10100003017,2021/7/5 13:14,,1,
+1395,PK504B10100003022,2021/7/4 19:58,,1,
+1396,PK504B10100003024,2021/6/17 11:39,2021/7/8 11:51,1,
+1397,PK504B10100003025,2021/7/20 10:22,,1,
+1398,PK504B10100003029,2021/6/18 10:19,,1,
+1399,PK504B10100003032,2021/7/21 15:28,,1,
+1400,PK504B10100003033,2021/7/5 10:44,2021/7/12 10:57,1,
+1401,PK504B10100003034,2021/7/1 10:48,,1,
+1402,PK504B10100003035,2021/7/23 18:53,,1,
+1403,PK504B10100003038,2021/7/22 17:22,,1,
+1404,PK504B10100003039,2021/7/2 10:28,,1,
+1405,PK504B10100003040,2021/6/18 10:18,,1,
+1406,PK504B10100003045,2021/7/10 17:36,,1,
+1407,PK504B10100003048,2021/6/17 15:06,,1,
+1408,PK504B10100003050,2021/7/23 14:06,,1,
+1409,PK504B10100003051,2021/7/17 14:59,,1,
+1410,PK504B10100003056,2021/7/5 13:40,,1,
+1411,PK504B10100003060,2021/6/26 20:19,,1,
+1412,PK504B10100003061,2021/7/7 17:13,,1,
+1413,PK504B10100003062,2021/6/17 11:39,2021/7/20 18:25,1,
+1414,PK504B10100003065,2021/7/20 12:53,,1,
+1415,PK504B10100003069,2021/6/22 15:47,2021/7/23 12:47,1,
+1416,PK504B10100003071,2021/6/18 11:24,2021/7/8 20:15,1,
+1417,PK504B10100003073,2021/7/5 18:28,,1,
+1418,PK504B10100003079,2021/7/6 16:36,,1,
+1419,PK504B10100003097,2021/7/6 14:52,,1,
+1420,PK504B10100003127,2021/7/4 17:31,,1,
+1421,PK504B10100003131,2021/7/9 16:58,,1,
+1422,PK504B10100003133,2021/7/23 10:09,,1,
+1423,PK504B10100003137,2021/7/21 13:29,,1,
+1424,PK504B10100003139,2021/7/22 13:05,,1,
+1425,PK504B10100003140,2021/7/2 9:40,,1,
+1426,PK504B10100003142,2021/6/25 18:24,,1,
+1427,PK504B10100003144,2021/6/24 14:10,,1,
+1428,PK504B10100003147,2021/6/30 21:12,,1,
+1429,PK504B10100003148,2021/6/24 14:14,,1,
+1430,PK504B10100003149,2021/6/28 19:04,2021/7/4 17:31,1,
+1431,PK504B10100003155,2021/6/25 17:23,,1,
+1432,PK504B10100003175,2021/6/30 14:08,2021/7/6 12:54,1,
+1433,PK504B10100003180,2021/7/6 14:55,,1,
+1434,PK504B10100003185,2021/7/6 14:48,,1,
+1435,PK504B10100003204,2021/7/6 15:01,,1,
+1436,PK504B10100003206,2021/6/24 14:08,,1,
+1437,PK504B10100004301,2021/4/2 18:08,,1,
+1438,PK504B10100004302,2021/5/16 22:08,,1,
+1439,PK504B10100004303,2021/3/18 14:13,2021/5/23 13:18,1,
+1440,PK504B10100004305,2021/5/7 9:36,2021/5/8 15:30,0,2021/6/2 15:36
+1441,PK504B10100004306,2021/4/11 15:33,2021/6/2 11:59,0,2021/7/13
+1442,PK504B10100004307,2021/3/23 11:23,2021/6/28 14:59,1,
+1443,PK504B10100004308,2021/3/26 14:21,,1,
+1444,PK504B10100004309,2021/3/19 12:32,2021/4/13 10:07,1,
+1445,PK504B10100004310,2021/3/23 11:25,2021/7/8 11:50,1,
+1446,PK504B10100004311,2021/3/20 11:58,2021/3/22 17:33,1,
+1447,PK504B10100004312,2021/3/28 12:12,2021/4/27 15:52,1,
+1448,PK504B10100004313,2021/3/22 19:24,2021/4/5 14:51,1,
+1449,PK504B10100004314,2021/3/19 16:07,2021/7/15 15:46,1,
+1450,PK504B10100004315,2021/3/21 18:45,,1,
+1451,PK504B10100004316,2021/3/27 10:00,2021/3/30 10:33,1,
+1452,PK504B10100004317,2021/3/25 12:06,2021/7/11 20:34,1,
+1453,PK504B10100004318,2021/3/18 12:19,2021/3/23 16:48,1,
+1454,PK504B10100004319,2021/3/31 15:50,2021/4/27 10:16,1,
+1455,PK504B10100004320,2021/4/2 16:28,2021/4/9 9:19,0,2021/4/12 17:11
+1456,PK504B10100004321,2021/3/26 14:39,2021/4/2 8:49,0,2021/4/12 17:11
+1457,PK504B10100004322,2021/4/7 17:47,,1,
+1458,PK504B10100004323,2021/3/21 16:24,,1,
+1459,PK504B10100004324,2021/5/7 10:06,2021/7/4 10:21,1,
+1460,PK504B10100004325,2021/3/23 11:24,2021/5/19 10:49,0,2021/6/2 15:36
+1461,PK504B10100004326,2021/4/6 11:03,2021/6/1 14:43,1,
+1462,PK504B10100004328,2021/3/29 14:11,2021/4/27 16:46,1,
+1463,PK504B10100004329,2021/4/11 15:30,2021/6/25 16:46,1,
+1464,PK504B10100004330,2021/3/26 19:03,2021/4/25 9:50,1,
+1465,PK504B10100004331,2021/5/15 14:47,2021/6/5 17:34,1,
+1466,PK504B10100004332,2021/3/20 12:58,,1,
+1467,PK504B10100004333,2021/3/19 12:32,2021/4/13 10:06,1,
+1468,PK504B10100004335,2021/3/24 12:16,2021/3/24 15:28,0,2021/3/26 20:57
+1469,PK504B10100004336,2021/3/25 10:53,2021/7/2 11:59,1,
+1470,PK504B10100004337,2021/3/26 18:08,,1,
+1471,PK504B10100004338,2021/4/11 15:31,2021/6/25 16:33,1,
+1472,PK504B10100004339,2021/3/21 19:39,2021/4/19 13:41,0,2021/6/2 15:36
+1473,PK504B10100004340,2021/3/22 16:35,,1,
+1474,PK504B10100004341,2021/5/9 14:46,2021/6/8 14:09,1,
+1475,PK504B10100004342,2021/4/30 16:13,2021/6/29 16:41,1,
+1476,PK504B10100004343,2021/3/26 16:06,2021/3/26 19:03,0,2021/4/12 17:11
+1477,PK504B10100004344,2021/5/19 12:15,2021/7/7 22:00,1,
+1478,PK504B10100004346,2021/5/19 12:13,2021/6/17 11:03,1,
+1479,PK504B10100004347,2021/3/29 12:43,2021/6/19 15:33,1,
+1480,PK504B10100004348,2021/4/14 16:36,2021/4/14 17:37,0,2021/6/2 17:37
+1481,PK504B10100004349,2021/3/31 19:30,,1,
+1482,PK504B10100004350,2021/6/15 17:49,2021/6/20 11:54,1,
+1483,PK504B10100004352,2021/6/14 15:15,,1,
+1484,PK504B10100004353,2021/4/28 12:37,,1,
+1485,PK504B10100004355,2021/7/8 13:26,,1,
+1486,PK504B10100004356,2021/4/15 10:57,2021/5/31 15:02,1,
+1487,PK504B10100004357,2021/3/18 14:37,,1,
+1488,PK504B10100004358,2021/4/2 16:47,2021/7/1 13:56,1,
+1489,PK504B10100004359,2021/4/2 8:49,2021/7/2 11:58,1,
+1490,PK504B10100004360,2021/5/23 10:34,2021/6/18 20:42,1,
+1491,PK504B10100004361,2021/3/30 17:03,,1,
+1492,PK504B10100004362,2021/4/8 19:38,2021/6/28 15:00,1,
+1493,PK504B10100004363,2021/3/31 15:36,2021/4/30 20:06,1,
+1494,PK504B10100004364,2021/7/3 8:56,,1,
+1495,PK504B10100004365,2021/4/3 15:01,2021/6/28 15:00,1,
+1496,PK504B10100004366,2021/4/23 14:10,,1,
+1497,PK504B10100004367,2021/4/12 14:48,2021/7/13 14:07,1,
+1498,PK504B10100004368,2021/6/30 16:20,2021/7/23 17:42,1,
+1499,PK504B10100004369,2021/5/20 20:11,2021/7/2 21:04,1,
+1500,PK504B10100004370,2021/3/29 16:24,2021/6/26 15:40,1,
+1501,PK504B10100004371,2021/4/18 12:29,2021/7/20 18:26,1,
+1502,PK504B10100004372,2021/7/9 12:03,,1,
+1503,PK504B10100004373,2021/3/19 10:47,2021/5/6 9:13,1,
+1504,PK504B10100004374,2021/5/23 10:37,,1,
+1505,PK504B10100004376,2021/5/17 18:25,2021/6/6 11:16,1,
+1506,PK504B10100004377,2021/4/4 16:07,,1,
+1507,PK504B10100004378,2021/7/12 18:01,2021/7/13 11:32,1,
+1508,PK504B10100004379,2021/3/25 15:47,2021/7/2 12:01,1,
+1509,PK504B10100004380,2021/3/18 15:44,2021/7/2 12:00,1,
+1510,PK504B10100004381,2021/3/21 20:33,2021/5/9 22:23,1,
+1511,PK504B10100004382,2021/4/18 11:30,2021/4/18 12:29,0,2021/6/2 15:36
+1512,PK504B10100004384,2021/6/15 14:11,2021/6/15 14:11,1,
+1513,PK504B10100004385,2021/3/27 17:10,2021/4/23 15:20,1,
+1514,PK504B10100004386,2021/4/1 11:09,2021/5/8 10:21,1,
+1515,PK504B10100004387,2021/3/22 15:30,2021/6/27 15:37,1,
+1516,PK504B10100004388,2021/4/11 15:24,2021/5/6 15:36,0,2021/6/2 15:36
+1517,PK504B10100004389,2021/3/26 14:38,2021/3/26 16:06,0,2021/3/26 20:57
+1518,PK504B10100004390,2021/4/11 15:37,2021/6/25 16:43,1,
+1519,PK504B10100004391,2021/3/29 16:10,2021/6/29 13:10,1,
+1520,PK504B10100004392,2021/6/3 11:56,2021/6/15 10:31,0,2021/7/13
+1521,PK504B10100004393,2021/3/26 17:02,2021/7/15 10:02,1,
+1522,PK504B10100004394,2021/4/12 10:30,2021/6/17 11:03,1,
+1523,PK504B10100004395,2021/3/27 19:21,2021/6/16 15:21,1,
+1524,PK504B10100004396,2021/3/24 10:30,2021/6/11 20:40,1,
+1525,PK504B10100004397,2021/4/11 15:32,2021/6/25 16:47,1,
+1526,PK504B10100004398,2021/7/3 20:02,2021/7/4 19:58,1,
+1527,PK504B10100004399,2021/5/15 12:12,2021/7/5 18:28,1,
+1528,PK504B10100004400,2021/3/23 20:21,2021/5/21 22:30,1,
+1529,PK504B10100004401,2021/5/4 19:40,,1,
+1530,PK504B10100004402,2021/4/9 9:19,,1,
+1531,PK504B10100004403,2021/4/4 15:32,2021/7/19 11:55,1,
+1532,PK504B10100004404,2021/4/6 18:23,,1,
+1533,PK504B10100004405,2021/4/8 9:32,,1,
+1534,PK504B10100004407,2021/4/11 15:36,2021/6/25 16:45,1,
+1535,PK504B10100004408,2021/2/20 13:09,,1,
+1536,PK504B10100004409,2021/3/20 9:03,,1,
+1537,PK504B10100004410,2021/5/8 15:30,,1,
+1538,PK504B10100004411,2021/4/1 16:07,,1,
+1539,PK504B10100004412,2021/3/29 11:20,,1,
+1540,PK504B10100004413,2021/5/12 10:45,2021/6/27 17:08,1,
+1541,PK504B10100004414,2021/4/4 18:04,2021/6/3 20:54,1,
+1542,PK504B10100004415,2021/3/29 15:41,2021/7/9 19:29,1,
+1543,PK504B10100004416,2021/6/1 13:13,,1,
+1544,PK504B10100004417,2021/3/27 17:14,2021/5/21 16:05,1,
+1545,PK504B10100004418,2021/4/8 18:05,2021/6/9 9:19,1,
+1546,PK504B10100004419,2021/4/7 18:06,2021/7/9 11:21,1,
+1547,PK504B10100004420,2021/3/25 16:01,2021/4/21 10:27,1,
+1548,PK504B10100004421,2021/5/23 10:36,2021/6/23 17:28,0,2021/7/13
+1549,PK504B10100004422,2021/3/30 13:27,2021/6/28 11:46,1,
+1550,PK504B10100004423,2021/4/10 15:49,,1,
+1551,PK504B10100004424,2021/4/3 18:27,2021/5/26 11:13,1,
+1552,PK504B10100004425,2021/7/13 11:32,,1,
+1553,PK504B10100004426,2021/6/15 17:48,2021/6/20 11:55,1,
+1554,PK504B10100004427,2021/3/31 13:24,2021/4/27 12:10,1,
+1555,PK504B10100004428,2021/3/29 14:19,2021/4/27 19:55,1,
+1556,PK504B10100004429,2021/5/12 9:35,2021/7/13 10:17,1,
+1557,PK504B10100004430,2021/5/10 10:20,2021/5/15 8:52,1,
+1558,PK504B10100004432,2021/4/1 19:31,,1,
+1559,PK504B10100004433,2021/3/23 17:25,2021/5/22 11:05,1,
+1560,PK504B10100004434,2021/5/6 15:36,2021/6/25 16:34,1,
+1561,PK504B10100004436,2021/5/15 8:14,2021/5/23 9:50,0,2021/6/2 9:50
+1562,PK504B10100004438,2021/3/27 9:25,2021/5/25 16:50,0,
+1563,PK504B10100004439,2021/4/23 15:12,,1,
+1564,PK504B10100004441,2021/5/2 19:51,2021/5/7 11:54,1,
+1565,PK504B10100004442,2021/5/9 10:39,2021/6/9 18:56,1,
+1566,PK504B10100004443,2021/4/20 16:04,2021/7/20 18:11,1,
+1567,PK504B10100004444,2021/4/26 19:16,,1,
+1568,PK504B10100004445,2021/4/10 16:52,2021/6/30 18:22,1,
+1569,PK504B10100004446,2021/4/12 22:27,2021/4/13 14:32,1,
+1570,PK504B10100004447,2021/4/23 16:57,,1,
+1571,PK504B10100004448,2021/4/5 17:15,2021/5/6 17:11,1,
+1572,PK504B10100004450,2021/4/1 13:09,2021/7/16 8:21,1,
+1573,PK504B10100004451,2021/5/21 17:23,,1,
+1574,PK504B10100004452,2021/4/11 15:28,2021/6/25 16:35,1,
+1575,PK504B10100004453,2021/5/23 9:50,2021/7/23 9:13,1,
+1576,PK504B10100004454,2021/7/16 8:21,2021/7/16 12:23,1,
+1577,PK504B10100004455,2021/4/23 15:20,2021/7/19 11:54,1,
+1578,PK504B10100004456,2021/5/23 10:36,2021/6/19 18:45,1,
+1579,PK504B10100004457,2021/4/5 17:15,2021/6/5 10:59,1,
+1580,PK504B10100004458,2021/3/29 9:00,,1,
+1581,PK504B10100004459,2021/5/21 10:31,,1,
+1582,PK504B10100004460,2021/4/12 14:44,2021/6/2 9:01,1,
+1583,PK504B10100004462,2021/3/27 14:13,,1,
+1584,PK504B10100004463,2021/4/20 9:42,,1,
+1585,PK504B10100004464,2021/5/19 12:16,2021/6/15 14:31,1,
+1586,PK504B10100004466,2021/5/21 16:15,2021/5/21 17:23,0,2021/6/2 15:36
+1587,PK504B10100004467,2021/5/2 19:25,2021/5/2 19:51,0,2021/6/2 15:36
+1588,PK504B10100004469,2021/4/15 15:00,2021/7/2 12:01,1,
+1589,PK504B10100004470,2021/4/2 15:48,2021/4/30 20:07,1,
+1590,PK504B10100004471,2021/4/20 18:01,,1,
+1591,PK504B10100004472,2021/4/3 11:14,2021/6/18 15:28,1,
+1592,PK504B10100004473,2021/4/1 15:17,2021/6/30 12:33,1,
+1593,PK504B10100004474,2021/3/26 22:12,2021/5/4 19:40,1,
+1594,PK504B10100004475,2021/4/28 13:29,2021/5/28 10:27,1,
+1595,PK504B10100004478,2021/4/23 14:50,2021/5/25 18:15,1,
+1596,PK504B10100004479,2021/7/2 16:30,2021/7/11 3:18,1,
+1597,PK504B10100004480,2021/5/12 10:43,2021/7/17 8:19,1,
+1598,PK504B10100004481,2021/5/19 16:56,2021/6/18 16:34,1,
+1599,PK504B10100004482,2021/5/25 20:42,2021/7/12 18:01,0,2021/7/13
+1600,PK504B10100004483,2021/3/24 15:28,2021/6/20 7:32,1,
+1601,PK504B10100004486,2021/4/20 19:05,,1,
+1602,PK504B10100004488,2021/4/6 14:16,2021/5/22 21:47,1,
+1603,PK504B10100004490,2021/6/24 16:44,,1,
+1604,PK504B10100004491,2021/4/22 8:54,2021/5/24 10:13,1,
+1605,PK504B10100004492,2021/7/23 14:53,,1,
+1606,PK504B10100004493,2021/6/6 17:17,,1,
+1607,PK504B10100004496,2021/4/21 11:36,2021/7/21 0:56,1,
+1608,PK504B10100004497,2021/3/17 16:21,,1,
+1609,PK505B00100004166,2020/12/18 12:24,,1,
+1610,UD02030118B4C0001,2021/5/9 16:30,2021/7/11 14:10,1,
+1611,UD02030118B4C0002,2021/4/29 12:56,2021/7/17 20:39,1,
+1612,UD02030118B4C0003,2021/5/25 12:21,,1,
+1613,UD02030118B4C0004,2021/5/7 13:57,2021/5/24 17:32,1,
+1614,UD02030118B4C0007,2021/5/8 12:53,,1,
+1615,UD02030118B4C0008,2021/5/14 13:02,2021/6/8 21:00,1,
+1616,UD02030118B4C0009,2021/7/12 14:49,,1,
+1617,UD02030118B4C0010,2021/5/5 15:57,2021/5/8 16:28,1,
+1618,UD02030118B4C0011,2021/5/21 10:33,,1,
+1619,UD02030118B4C0012,2021/5/7 13:12,2021/5/10 17:58,1,
+1620,UD02030118B4C0013,2021/5/20 15:09,2021/6/20 8:32,1,
+1621,UD02030118B4C0014,2021/5/6 13:19,,1,
+1622,UD02030118B4C0015,2021/5/10 17:56,2021/7/23 15:25,1,2021/7/27
+1623,UD02030118B4C0016,2021/7/23 16:56,,1,
+1624,UD02030118B4C0017,2021/5/5 15:07,2021/5/24 21:09,1,2021/6/22
+1625,UD02030118B4C0021,2021/5/10 14:07,2021/6/10 13:57,1,
+1626,UD02030118B4C0022,2021/5/6 14:50,2021/6/13 16:57,1,
+1627,UD02030118B4C0025,2021/5/23 9:03,,1,
+1628,UD02030118B4C0026,2021/5/7 14:08,,1,
+1629,UD02030118B4C0028,2021/5/8 14:19,2021/6/1 14:17,1,
+1630,UD02030118B4C0029,2021/5/15 16:10,2021/6/14 13:28,1,
+1631,UD02030118B4C0030,2021/7/17 13:45,,1,
+1632,UD02030118B4C0031,2021/6/20 12:00,,1,
+1633,UD02030118B4C0032,2021/5/6 17:55,2021/7/13 10:28,1,
+1634,UD02030118B4C0034,2021/5/8 14:52,,1,
+1635,UD02030118B4C0035,2021/5/7 16:05,,1,
+1636,UD02030118B4C0036,2021/7/10 13:13,,1,
+1637,UD02030118B4C0038,2021/5/5 18:17,2021/6/1 13:23,1,
+1638,UD02030118B4C0039,2021/5/8 10:23,2021/6/16 16:44,1,
+1639,UD02030118B4C0040,2021/5/8 16:28,,1,
+1640,UD02030118B4C0041,2021/5/8 14:30,2021/6/2 13:44,1,
+1641,UD02030118B4C0042,2021/5/11 15:13,,1,
+1642,UD02030118B4C0043,2021/5/14 16:54,2021/5/20 10:21,1,2021/6/22
+1643,UD02030118B4C0044,2021/5/7 14:35,,1,
+1644,UD02030118B4C0045,2021/5/7 10:18,2021/7/6 17:02,1,
+1645,UD02030118B4C0046,2021/5/12 19:16,,1,
+1646,UD02030118B4C0047,2021/5/8 16:11,2021/7/1 11:03,1,
+1647,UD02030118B4C0048,2021/5/5 15:05,2021/6/3 16:42,1,
+1648,UD02030118B4C0049,2021/7/20 15:46,,1,
+1649,UD02030118B4C0050,2021/5/14 19:27,,1,
+1650,UD02030118B4C0051,2021/5/9 18:28,2021/7/8 16:25,1,
+1651,UD02030118B4C0052,2021/5/10 9:08,2021/6/3 12:00,1,
+1652,UD02030118B4C0053,2021/5/20 10:21,2021/7/19 10:16,1,
+1653,UD02030118B4C0055,2021/5/7 14:23,2021/7/25 11:56,1,
+1654,UD02030118B4C0056,2021/5/24 11:58,2021/7/20 15:37,1,
+1655,UD02030118B4C0057,2021/7/11 20:43,,1,
+1656,UD02030118B4C0061,2021/5/7 19:03,2021/5/26 15:47,1,
+1657,UD02030118B4C0062,2021/5/11 14:25,2021/7/9 19:01,1,
+1658,UD02030118B4C0081,2021/5/12 12:13,2021/5/15 18:00,1,
+1659,UD02030118B4C0084,2021/5/7 17:13,2021/5/17 16:36,1,

+ 143 - 0
LIB/FRONTEND/day_sta.py

@@ -0,0 +1,143 @@
+__author__ = 'Wang Liming'
+
+# 每日指标统计函数
+import CONFIGURE.PathSetting as PathSetting
+import sys
+sys.path.append(PathSetting.backend_path)
+sys.path.append(PathSetting.middle_path)
+import DBManager
+import Tools
+import DataPreProcess
+import IndexStaByPeriod
+import Log
+import IndexStaByPeriod
+import importlib
+import datetime
+import os
+import pandas as pd
+import time
+importlib.reload(IndexStaByPeriod)
+
+dbManager = DBManager.DBManager()
+dataPrePro = DataPreProcess.DataPreProcess()
+indexPerSta = IndexStaByPeriod.IndexStaByPeriod()
+
+# log 文件配置
+myLog = Log.Mylog('day_sta')
+myLog.set_file_hl(file_name=r'D:\Platform\platform\FRONTEND\day_sta\day_sta.log', log_level='info')
+myLog.set_stream_hl(log_level='info')
+logger = myLog.get_logger()
+logger.info(str(os.getpid()))
+
+# sn文件读取
+sn_list = list(pd.read_excel('D:\Platform\platform\苏州电池列表.xlsx')['sn'])
+sn_list.extend(list(pd.read_excel('D:\Platform\platform\骑享北京6040电池包统计更新20210407.xlsx')['SN号']))
+
+sn = sn_list[0]
+
+# 字段设置及结果文件生成
+columns = ['sn', 'time',  'sumDriveTime', 'sumDriveSoc', 'sumDriveAh', 'sumDriveEnergy']
+st = datetime.datetime.strptime('00:00:00', '%H:%M:%S')
+for i in range(96):
+    et = st + datetime.timedelta(minutes=15)
+    columns.append(st.strftime('%H:%M') + '-' + et.strftime('%H:%M'))
+    st = et
+result_path = r'D:\Platform\platform\FRONTEND\day_sta\result.csv'
+df_res = pd.DataFrame(columns=columns)
+if not os.path.exists(result_path):
+    df_res.to_csv(result_path, index=False)
+    
+# 时间范围设置
+start_time = '{} 00:00:00'.format('2020-01-01')
+end_time = '{} 00:00:00'.format('2021-06-01')
+sta_days = (datetime.datetime.strptime(end_time, '%Y-%m-%d %H:%M:%S') - datetime.datetime.strptime(start_time, '%Y-%m-%d %H:%M:%S')).days
+
+count= 0
+sn_result = {}
+for sn in sn_list[:]:
+    count += 1
+    logger.info('{} start,  {}/{} '.format(sn, str(count), str(len(sn_list))))
+    if sn[2:5] == '500':
+        cap = 40
+    elif sn[2:5] == '504':
+        cap = 55
+    else:
+        logger.info('{} cap error'.format(sn))
+        cap = None
+        continue
+        
+    sn_result.update({'sn':sn})
+    logger.info('{} :{} to {} start'.format(sn, str(start_time), str(end_time)))
+    
+    # 获取数据
+    df_bms, df_gps = dbManager.get_data(sn=sn, start_time=start_time, end_time=end_time, gps_switch=True, mode=0)
+    if df_bms.empty:
+        continue
+    # 数据预处理
+    
+    # 时间完全相同的数据仅保留一行
+    df_bms_pro, df_gps_pro = dataPrePro.time_filter(df_bms, df_gps)
+    
+    # bms数据按照电流和状态分段, 然后在状态分段内部,根据时间跳变继续分段(解决段内数据丢失)
+    df_bms_pro = dataPrePro.data_split_by_status(df_bms_pro)
+    df_bms_pro = dataPrePro.data_split_by_time(df_bms_pro)
+
+    # bms数据将两次充电间的状态合并
+    df_bms_pro = dataPrePro.combine_drive_stand(df_bms_pro)
+    # bms 数据计算行车和充电开始前后的静置时间
+    df_bms_pro = dataPrePro.cal_stand_time(df_bms_pro)
+    # gps 数据可靠性判断, 并增加里程和速度至gps数据(根据未合并的数据段判断)
+    df_bms_pro, df_gps_pro, res_record= dataPrePro.gps_data_judge(df_bms_pro, df_gps_pro)
+    # gps 数据可靠性判断, 并增加里程和速度至gps数据(根据已合并的数据段判断)
+    df_bms_pro, df_gps_pro, res_record= dataPrePro.data_gps_judge_after_combine(df_bms_pro, df_gps_pro)
+    
+    for sta_day in range(sta_days):
+        try:
+            st_ = datetime.datetime.strptime(start_time, '%Y-%m-%d %H:%M:%S') + datetime.timedelta(days=sta_day)
+            et_ =datetime.datetime.strptime(start_time, '%Y-%m-%d %H:%M:%S') + datetime.timedelta(days=sta_day+1)
+
+        # 按天统计指标
+            sn_result.update({'time':st_.strftime('%Y-%m-%d')})
+
+            df_bms_period = df_bms_pro[(df_bms_pro['时间戳'] > st_.strftime('%Y-%m-%d %H:%M:%S')) & (df_bms_pro['时间戳'] <= et_.strftime('%Y-%m-%d %H:%M:%S'))]
+            #df_gps_period = df_gps_pro[(df_gps_pro['时间戳'] > st_.strftime('%Y-%m-%d %H:%M:%S')) & (df_gps_pro['时间戳'] <= et_.strftime('%Y-%m-%d %H:%M:%S'))]
+            sn_result.update({'sumDriveTime':[indexPerSta.drive_time_sta(df_bms_period)]})
+            sn_result.update({'sumDriveSoc':[indexPerSta.drive_soc_sta(df_bms_period)]})
+            sn_result.update({'sumDriveAh':[indexPerSta.drive_capacity_sta(cap, df_bms_period)]})
+            sn_result.update({'sumDriveEnergy':[indexPerSta.drive_energy_sta(cap, df_bms_period)]})
+
+            # 每天间隔15分钟 统计一次
+            for i in range(96):
+                cur_result = []
+                st__ = st_ + datetime.timedelta(minutes=15 * i)
+                et__ = st_ + datetime.timedelta(minutes=15 * (i+1))
+                df_bms_period = df_bms_pro[(df_bms_pro['时间戳'] > st__.strftime('%Y-%m-%d %H:%M:%S')) & (df_bms_pro['时间戳'] <= et__.strftime('%Y-%m-%d %H:%M:%S'))]
+                #df_gps_period = df_gps_pro[(df_gps_pro['时间戳'] > st__.strftime('%Y-%m-%d %H:%M:%S')) & (df_gps_pro['时间戳'] <= et__.strftime('%Y-%m-%d %H:%M:%S'))]
+                cur_result.append(indexPerSta.drive_time_sta(df_bms_period))
+                cur_result.append(indexPerSta.drive_soc_sta(df_bms_period))
+                cur_result.append(indexPerSta.drive_capacity_sta(cap, df_bms_period))
+                cur_result.append(indexPerSta.drive_energy_sta(cap, df_bms_period))
+                key = st__.strftime('%H:%M') + '-' + et__.strftime('%H:%M')
+                sn_result.update({key:[cur_result]})
+            df_cur_res = pd.DataFrame(sn_result)
+            df_cur_res = df_cur_res[columns]
+
+            # 防止写入结果时,结果文件被打开
+            write_flag = False
+            while not write_flag:
+                try:
+                    df_cur_res.to_csv(result_path, mode='a+', index=False,  header=False)
+                except PermissionError as e:
+                    logger.info('{} error:{}'.format(sn, str(e)))
+                    time.sleep(10)
+                    continue
+                else:
+                    write_flag = True 
+        except Exception as e:
+                logger.info('{} {}_{} error: {}'.format(sn, st_.strftime('%Y-%m-%d %H:%M:%S'), et_.strftime('%Y-%m-%d %H:%M:%S'), str(e)))
+                continue
+        else:
+            continue
+    logger.info('{} done,  {}/{} '.format(sn, str(count), str(len(sn_list))))
+ 
+        

+ 197 - 0
LIB/MIDDLE/IndexStaByOneCycle.py

@@ -0,0 +1,197 @@
+'''
+基于单一状态(一次行车、一次静置、一次充电)的指标统计库
+
+'''
+__author__ = 'Wang Liming'
+
+import CONFIGURE.PathSetting as PathSetting
+import sys
+sys.path.append(PathSetting.backend_path)
+import datetime
+import Tools
+import pandas as pd
+import numpy as np
+
+class IndexStaByOneCycle():
+    def __init__(self):
+        pass
+
+    def odo_sta(self, odo_array):
+        '''
+        一次行车行驶里程统计
+        ---------输入参数------------
+        odo_array : 一次行车对应的odo数据
+        ---------输出参数------------
+        如果gps 可信,则输出本次行车的累积行驶里程;
+        否则,输出None
+        '''
+        odo_array = odo_array[~pd.isnull(odo_array)]
+        if len(odo_array) > 0:
+            return np.sum(odo_array)
+        else:
+            return None
+
+    def capacity_sta(self, cap, soc_array, soh_array):
+        '''
+        一个cycle净累积ah统计
+        ---------输入参数------------
+        cap : 标称容量
+        soc_array : 一个cycle对应的soc数据
+        soh_array : 一个cycle对应的soh数据
+        ---------输出参数------------
+        本次行车的累积ah
+        '''
+        soc_array = soc_array[~pd.isnull(soc_array)]
+        soh_array = soh_array[~pd.isnull(soh_array)]
+        if len(soc_array) > 0 and len(soh_array) > 0 :
+            return (soc_array[0] - soc_array[-1]) * np.mean(soh_array) * cap / 100.0 / 100.0
+        else:
+            return None
+    def energy_sta(self, cap, soc_array, soh_array, volt_array):
+        '''
+        一个cycle净累积能量统计
+        ---------输入参数------------
+        cap : 标称容量
+        soc_array : 一个cycle对应的soc数据
+        soh_array : 一个cycle对应的soh数据
+        volt_array : 一个cycle对应的volt数据
+        ---------输出参数------------
+        本次行车的累积能量
+        '''
+        soc_array = soc_array[~pd.isnull(soc_array)]
+        soh_array = soh_array[~pd.isnull(soh_array)]
+        volt_array = volt_array[~pd.isnull(volt_array)]
+        if len(soc_array) > 0 and len(soh_array) > 0 and len(volt_array)>0:
+            cap = self.capacity_sta(cap, soc_array, soh_array)
+            return cap * np.mean(volt_array) / 1000.0
+        else:
+            return None
+
+
+
+    def acc_time_sta(self, time_array):
+        '''
+        一个cycle的持续时间
+        ---------输入参数------------
+        time_array : 一次cycle对应的time数据
+        ---------输出参数------------
+        本cycle的持续时间,单位 h
+        '''
+        time_array = time_array[~pd.isnull(time_array)]
+        if len(time_array) > 0:
+            return float(abs(time_array[0] - time_array[-1]))/1e9/3600.0
+        else:
+            return None
+
+    def mean_temp_sta(self, temp_array):
+        '''
+        一个cycle的单体平均温度
+        ---------输入参数------------
+        temp_array : 一个cycle对应的某个单体的temp数据
+        ---------输出参数------------
+        本cycle的单体平均温度
+        '''
+        temp_array = temp_array[~pd.isnull(temp_array)]
+        if len(temp_array) > 0:
+            return np.mean(temp_array)
+        else:
+            return None
+
+    def temp_change_rate_sta(self, time_array, temp_array):
+        '''
+        一个cycle的单体温度变化率
+        ---------输入参数------------
+        time_array : 一个cycle对应的time数据
+        temp_array : 一个cycle对应的temp数据
+        ---------输出参数------------
+        本cycle的单体温度变化率
+        '''
+        time_array = time_array[~pd.isnull(time_array)]
+        temp_array = temp_array[~pd.isnull(temp_array)]
+        if len(temp_array) > 0 and len(time_array) > 0:
+            return abs(temp_array[0] - temp_array[-1])/\
+                (float(abs(time_array[0] - time_array[-1]))/1e9/3600.0)
+        else:
+            return None
+
+    def dischrg_max_pwr_sta(self, volt_array, crnt_array):
+        '''
+        一个cycle的放电功率最大值
+        ---------输入参数------------
+        volt_array : 一个cycle对应的volt数据
+        crnt_array : 一个cycle对应的crnt数据
+        ---------输出参数------------
+        本cycle的放电功率最大值
+        '''
+        volt_array = volt_array[~pd.isnull(volt_array)]
+        crnt_array = crnt_array[~pd.isnull(crnt_array)]
+        if len(volt_array) > 0 and len(crnt_array) > 0:
+            pwr = volt_array * crnt_array / 1000.0
+            pwr = pwr[pwr > 0]
+            return np.max(pwr)
+        else:
+            return None
+
+    def chrg_max_pwr_sta(self, volt_array, crnt_array):
+        '''
+        一个cycle的充电功率最大值
+        ---------输入参数------------
+        volt_array : 一个cycle对应的volt数据
+        crnt_array : 一个cycle对应的crnt数据
+        ---------输出参数------------
+        本cycle的充电功率最大值
+        '''
+        volt_array = volt_array[~pd.isnull(volt_array)]
+        crnt_array = crnt_array[~pd.isnull(crnt_array)]
+        if len(volt_array) > 0 and len(crnt_array) > 0:
+            pwr = volt_array * crnt_array / 1000.0
+            pwr = pwr[pwr < 0]
+            return np.max(abs(pwr))
+        else:
+            return None
+
+    def regen_count_sta(self, crnt_array):
+        '''
+        一个行车cycle的regen 行数
+        ---------输入参数------------
+        crnt_array : 一个行车cycle对应的crnt数据
+        ---------输出参数------------
+        本行车cycle的regen行数, 总行数
+        '''
+        crnt_array = crnt_array[~pd.isnull(crnt_array)]
+        if  len(crnt_array) > 0:
+            return len(crnt_array[crnt_array < -1]), len(crnt_array)
+        else:
+            return None, None
+
+    def speed_sta(self, sum_odo, acc_time, speed_array):
+        '''
+        一个行车cycle的平均速度和最大瞬时速度
+        ---------输入参数------------
+        sum_odo : 一个行车cycle对应的累积odo数据
+        acc_time : 一个行车cycle对应的累积time数据
+        speed_array : 一个行车cycle对应的speed数据
+        ---------输出参数------------
+        本行车cycle的平均速度和最大速度
+        '''
+        speed_array = speed_array[~pd.isnull(speed_array)]
+        if  ~pd.isnull(sum_odo) and ~pd.isnull(acc_time) and len(speed_array) > 0:
+            return sum_odo/acc_time, np.max(speed_array)
+        else:
+            return None, None
+
+    def speed_sta(self, sum_odo, acc_time, speed_array):
+        '''
+        一个行车cycle的平均速度和最大瞬时速度
+        ---------输入参数------------
+        sum_odo : 一个行车cycle对应的累积odo数据
+        acc_time : 一个行车cycle对应的累积time数据
+        speed_array : 一个行车cycle对应的speed数据
+        ---------输出参数------------
+        本行车cycle的平均速度和最大速度
+        '''
+        speed_array = speed_array[~pd.isnull(speed_array)]
+        if  ~pd.isnull(sum_odo) and ~pd.isnull(acc_time) and len(speed_array) > 0:
+            return sum_odo/acc_time, np.max(speed_array)
+        else:
+            return None, None

+ 172 - 0
LIB/MIDDLE/IndexStaByPeriod.py

@@ -0,0 +1,172 @@
+'''
+基于某个周期(一天,一周...)的指标统计库
+
+'''
+__author__ = 'Wang Liming'
+
+import CONFIGURE.PathSetting as PathSetting
+import sys
+sys.path.append(PathSetting.backend_path)
+sys.path.append(PathSetting.middle_path)
+import datetime
+import Tools
+import pandas as pd
+import numpy as np
+import IndexStaByOneCycle
+
+class IndexStaByPeriod():
+    def __init__(self):
+        self.indexStaByOneCycle = IndexStaByOneCycle.IndexStaByOneCycle()
+        pass
+
+    def drive_odo_sta(self, df_bms, df_gps):
+        '''
+        计算周期内行车累积行驶里程
+        ---------输入参数------------
+        df_bms : 一段周期内的预处理后的bms数据
+        df_gps : 一段周期内的预处理后的gps数据
+        ---------输出参数------------
+        sum_odo : 累积里程, 如果该周期内gps均无效,则返回None
+        invalid_rate : 该周期内gps无效的bms数据行所占比例
+        '''
+        invalid_count = 0
+        total_count = 0
+        sum_odo = 0
+        data_number_list = sorted(list(set(df_bms[(df_bms['data_status'].isin(['drive']))]['data_split_by_status_after_combine'])))
+        if len(data_number_list) == 0:
+            return {'sum_odo':0, 'invalid_rate':0}
+        for data_number in data_number_list[:]:
+            df_sel_bms = df_bms[df_bms['data_split_by_status_after_combine'] == data_number]
+            df_sel_bms = df_sel_bms.reset_index(drop=True)
+
+            total_count += len(df_sel_bms)
+            if df_sel_bms.loc[0, 'gps_rely'] != 1:
+                invalid_count += len(df_sel_bms)
+                continue
+            else:
+                df_sel_gps = df_gps[(df_gps['时间戳']>df_sel_bms.loc[0,'时间戳']) & (df_gps['时间戳']<df_sel_bms.loc[len(df_sel_bms)-1,'时间戳'])]
+                df_sel_gps = df_sel_gps.reset_index(drop=True)
+                odo = self.indexStaByOneCycle.odo_sta(np.array(df_sel_gps['odo']))
+                if not pd.isnull(odo):
+                    sum_odo += odo
+        invalid_rate = invalid_count/total_count
+        return {'sum_odo':sum_odo, 'invalid_rate':invalid_rate}
+    
+    
+    #该函数未完成, TODO!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+    def _energy_consump_sta(self, cap, df_bms, df_gps):
+        '''
+        计算周期内百公里能耗
+        ---------输入参数------------
+        df_bms : 本周期内的bms数据
+        df_gps : 本周期内的gps数据
+        ---------输出参数------------
+        本周期内的百公里能耗
+        '''
+        if not df_bms.empty and not df_gps.empty:
+            # 计算能耗
+            energy_sum = 0
+            data_number_list = sorted(list(set(df_bms[(df_bms['data_status'].isin(['drive']))]['data_split_by_status_time'])))
+            for data_number in data_number_list[:]:
+                df_sel_bms = df_bms[df_bms['data_split_by_status_time'] == data_number]
+                df_sel_bms = df_sel_bms.reset_index(drop=True)
+                soc_array = np.array(df_sel_bms['SOC[%]'])
+                soh_array = np.array(df_sel_bms['SOH[%]'])
+                volt_array = np.array(df_sel_bms['总电压[V]'])
+                energy = self.indexStaByOneCycle.energy_sta(cap, soc_array, soh_array, volt_array)
+                if not pd.isnull(energy):
+                    energy_sum += energy
+            # 计算里程
+            pass # TODO!!!!!!!!!!!!!!!!!!!!!
+            return 0
+        else:
+            return None
+
+    def drive_soc_sta(self, df_bms):
+        '''
+        计算周期内行车净累积soc
+        ---------输入参数------------
+        cap : 标称容量
+        df_bms : 一段周期内的预处理后的bms数据
+        df_gps : 一段周期内的预处理后的gps数据
+        ---------输出参数------------
+        sum_ah : 本周期的净累积soc
+       '''   
+
+        sum_soc = 0
+        data_number_list = sorted(list(set(df_bms[(df_bms['data_status'].isin(['drive']))]['data_split_by_status_time'])))
+        if len(data_number_list) == 0:
+            return sum_soc
+        for data_number in data_number_list[:]:
+            df_sel_bms = df_bms[df_bms['data_split_by_status_time'] == data_number]
+            df_sel_bms = df_sel_bms.reset_index(drop=True)
+            sum_soc += abs(df_sel_bms.loc[0, 'SOC[%]'] - df_sel_bms.loc[len(df_sel_bms)-1, 'SOC[%]'])
+        return sum_soc
+
+    def drive_time_sta(self, df_bms):
+        '''
+        计算周期内累计行车时长/h
+        ---------输入参数------------
+        cap : 标称容量
+        df_bms : 一段周期内的预处理后的bms数据
+        df_gps : 一段周期内的预处理后的gps数据
+        ---------输出参数------------
+        sum_ah : 本周期的累计行车时长
+       '''   
+
+        sum_time = 0
+        data_number_list = sorted(list(set(df_bms[(df_bms['data_status'].isin(['drive']))]['data_split_by_status_time'])))
+        if len(data_number_list) == 0:
+            return sum_time
+        for data_number in data_number_list[:]:
+            df_sel_bms = df_bms[df_bms['data_split_by_status_time'] == data_number]
+            df_sel_bms = df_sel_bms.reset_index(drop=True)
+            sum_time += (df_sel_bms.loc[len(df_sel_bms)-1, '时间戳'] - df_sel_bms.loc[0, '时间戳']).total_seconds()
+        return sum_time / 3600.0
+
+    def drive_capacity_sta(self, cap, df_bms):
+        '''
+        计算周期内行车净累积ah
+        ---------输入参数------------
+        cap : 标称容量
+        df_bms : 一段周期内的预处理后的bms数据
+        df_gps : 一段周期内的预处理后的gps数据
+        ---------输出参数------------
+        sum_ah : 本周期的净累积ah
+       '''   
+
+        sum_ah = 0
+        data_number_list = sorted(list(set(df_bms[(df_bms['data_status'].isin(['drive']))]['data_split_by_status_time'])))
+        if len(data_number_list) == 0:
+            return sum_ah
+        for data_number in data_number_list[:]:
+            df_sel_bms = df_bms[df_bms['data_split_by_status_time'] == data_number]
+            df_sel_bms = df_sel_bms.reset_index(drop=True)
+            soc_array = np.array(df_sel_bms['SOC[%]'])
+            soh_array = np.array(df_sel_bms['SOH[%]'])
+            sum_ah += self.indexStaByOneCycle.capacity_sta(cap, soc_array, soh_array)
+        return sum_ah
+
+    def drive_energy_sta(self, cap, df_bms):
+        '''
+        计算周期内行车净累积能量
+        ---------输入参数------------
+        cap : 标称容量
+        df_bms : 一段周期内的预处理后的bms数据
+        df_gps : 一段周期内的预处理后的gps数据
+        ---------输出参数------------
+        sum_ah : 本周期的净累积能量
+       '''   
+
+        sum_energy = 0
+        data_number_list = sorted(list(set(df_bms[(df_bms['data_status'].isin(['drive']))]['data_split_by_status_time'])))
+        if len(data_number_list) == 0:
+            return sum_energy
+        for data_number in data_number_list[:]:
+            df_sel_bms = df_bms[df_bms['data_split_by_status_time'] == data_number]
+            df_sel_bms = df_sel_bms.reset_index(drop=True)
+            soc_array = np.array(df_sel_bms['SOC[%]'])
+            soh_array = np.array(df_sel_bms['SOH[%]'])
+            volt_array = np.array(df_sel_bms['总电压[V]'])
+            sum_energy += self.indexStaByOneCycle.energy_sta(cap, soc_array, soh_array, volt_array)
+        return sum_energy

+ 235 - 0
LIB/MIDDLE/SignalMonitor.py

@@ -0,0 +1,235 @@
+import datetime
+import os
+import pandas as pd
+import Tools
+import sys
+import xlutils
+from xlrd import open_workbook
+from xlutils.copy import copy
+
+import CONFIGURE.PathSetting as PathSetting
+sys.path.append(PathSetting.backend_path)
+import DBManager
+dbManager = DBManager.DBManager()
+
+class SignalMonitor():
+    def __init__(self):
+        pass
+
+    @staticmethod
+    def _set_working_states(df_state):
+        for i in range(0, len(df_state)):
+            if abs(df_state.loc[i, 'current']) >= 0.45:
+                df_state.loc[i, 'PackState'] = 0
+            else:
+                df_state.loc[i, 'PackState'] = 1
+        # path = r'D:\daily_data_analysis_01.csv'
+        # df_state.to_csv(path, index=True, encoding='GB2312')
+        return df_state
+    
+    @staticmethod
+    def _set_standby_states(df_state):
+        index = 0
+        set = 0
+        while index < len(df_state)-1:
+            index = index + 1
+            if set == 0:
+                if df_state.loc[index, 'PackState'] == 1 and df_state.loc[index-1, 'PackState'] == 0:
+                    set = 1
+                    start_time = df_state.loc[index-1, 'Timestamp']
+                    timeDelta = datetime.timedelta(minutes=10)
+                    end_time = start_time + timeDelta
+                    df_state.loc[index, 'PackState'] = 0
+            else:
+                if df_state.loc[index, 'Timestamp'] <= end_time:
+                    df_state.loc[index, 'PackState'] = 0
+                    if abs(df_state.loc[index, 'current']) >= 0.45:
+                        start_time = df_state.loc[index-1, 'Timestamp']
+                        timeDelta = datetime.timedelta(minutes=10)
+                        end_time = start_time + timeDelta
+                else:
+                    set = 0
+        # path = r'D:\daily_data_analysis_02.csv'
+        # df_state.to_csv(path, index=True, encoding='GB2312')
+        return df_state
+    
+    @staticmethod
+    def _set_lowpwr_states(df_state):
+        index = 0
+        set = 0
+        while index < len(df_state)-1:
+            index = index + 1
+            if df_state.loc[index,'PackState'] == 1:
+                if set ==0:
+                    start_time = df_state.loc[index,'Timestamp']
+                    timeDelta = datetime.timedelta(minutes=300)
+                    end_time = start_time + timeDelta
+                    set = 1
+                else:
+                    if df_state.loc[index,'Timestamp'] > end_time:
+                        df_state.loc[index,'PackState'] = 2
+            else:
+                set = 0
+        # path = r'D:\daily_data_analysis_03.csv'
+        # df_state.to_csv(path, index=True, encoding='GB2312')
+        return df_state
+    
+    @staticmethod
+    def _judge_offline_state_between_messages(sn, PackState_new, PackState_old, Timestamp_new, Timestamp_old, df_res, mode):
+        delta_time = (Timestamp_new - Timestamp_old).total_seconds()
+        max_state = max(PackState_new, PackState_old)
+        if max_state == 0:
+            if mode == 'BMS':
+                thres1 = 60
+                thres2 = 300
+            elif mode == 'GPS':
+                thres1 = 120
+                thres2 = 600
+        elif max_state == 1:
+            if mode == 'BMS':
+                thres1 = 1200
+                thres2 = 2400
+            elif mode == 'GPS':
+                thres1 = 2400
+                thres2 = 4800
+        else:
+            if mode == 'BMS':
+                thres1 = 3600
+                thres2 = 7200
+            elif mode == 'GPS':
+                thres1 = 7200
+                thres2 = 14400
+        
+        if delta_time <= thres1:
+            LineState = 0
+        elif delta_time <= thres2:
+            LineState = 1
+        else:
+            LineState = 2
+        
+        if LineState > 0:
+            df_res = df_res.append({'sn':sn[0], 'PackState':PackState_new*16+PackState_old, 'LineState':LineState, 'StartTime':Timestamp_old, 
+                        'EndTime':Timestamp_new, 'OfflineTime':delta_time}, ignore_index=True)
+        return LineState, df_res
+
+    @staticmethod
+    def _get_offline_info(sn, df_state, df_last_state, df_res, mode):
+        index = 0
+        if len(df_last_state) == 0:
+            df_state.loc[0,'LineState'] = 0
+            while index < len(df_state)-1:
+                index = index + 1
+                LineState, df_res = SignalMonitor._judge_offline_state_between_messages(sn, df_state.loc[index, 'PackState'], df_state.loc[index-1, 'PackState'], 
+                df_state.loc[index, 'Timestamp'], df_state.loc[index-1, 'Timestamp'], df_res, mode=mode)
+                df_state.loc[index, 'LineState'] = LineState
+        else:
+            df_last_info = df_last_state.loc[len(df_last_state) - 1]
+            df_state.loc[0,'LineState'], df_res = SignalMonitor._judge_offline_state_between_messages(sn, df_state.loc[0, 'PackState'], df_last_info['PackState'], 
+                df_state.loc[0, 'Timestamp'], df_last_info['Timestamp'], df_res, mode=mode)
+            while index < len(df_state)-1:
+                index = index + 1
+                LineState, df_res = SignalMonitor._judge_offline_state_between_messages(sn, df_state.loc[index, 'PackState'], df_state.loc[index-1, 'PackState'], 
+                df_state.loc[index, 'Timestamp'], df_state.loc[index-1, 'Timestamp'], df_res, mode=mode)
+                df_state.loc[index, 'LineState'] = LineState
+        # SignalMonitor._file_write(r'D:\result_03.xls', df_state)
+        return df_res
+    
+    @staticmethod
+    def _set_gps_working_states(df_state, df_state_gps):
+        for i in range(0, len(df_state_gps)):
+                if df_state_gps.loc[i, 'Timestamp'] <= df_state.loc[0, 'Timestamp']:
+                    df_state_gps.loc[i, 'PackState'] = df_state.loc[0, 'PackState']
+                elif df_state_gps.loc[i, 'Timestamp'] >= df_state.loc[len(df_state)-1, 'Timestamp']:
+                    df_state_gps.loc[i:len(df_state_gps)-1, 'PackState'] = df_state.loc[len(df_state)-1, 'PackState']
+                    break
+                else:
+                    index0 = max(df_state[df_state['Timestamp'] <= df_state_gps.loc[i, 'Timestamp']].index)
+                    index1 = min(df_state[df_state['Timestamp'] >= df_state_gps.loc[i, 'Timestamp']].index)
+                    front = (df_state_gps.loc[i, 'Timestamp'] - df_state.loc[index0, 'Timestamp']).total_seconds()
+                    back = (df_state.loc[index1, 'Timestamp'] - df_state_gps.loc[i, 'Timestamp']).total_seconds()
+                    if front > back:
+                        df_state_gps.loc[i, 'PackState'] = df_state.loc[index1, 'PackState']
+                    elif front == back:
+                        df_state_gps.loc[i, 'PackState'] = max(df_state.loc[index1, 'PackState'], df_state.loc[index0, 'PackState'])
+                    else:
+                        df_state_gps.loc[i, 'PackState'] = df_state.loc[index0, 'PackState']
+        return df_state_gps
+    
+    @staticmethod
+    def _file_write(path, df_res):
+        r_xls = open_workbook(path) # 读取excel文件
+        sheet = len(r_xls.sheets())
+        row = r_xls.sheets()[sheet-1].nrows # 获取已有的行数
+        excel = copy(r_xls) # 将xlrd的对象转化为xlwt的对象
+        table = excel.get_sheet(sheet-1) # 获取要操作的sheet
+        #对excel表追加一行内容
+        # print(row)
+        current_row = row
+        num = len(df_res.columns)
+        for i in range(0, len(df_res)):
+            for j in range(0, num):
+                table.write(current_row, j, df_res.iloc[i][j]) #括号内分别为行数、列数、内容
+            current_row = current_row + 1
+            if current_row == 65500:
+                table = r_xls.add_sheet('sheet'+ str(sheet))
+                sheet = sheet + 1
+                current_row = 0
+        excel.save(path) # 保存并覆盖文件
+    
+    def get_bms_offline_stat(self, sn, st, et, df_res, df_last_state, cal_Period=24):    # 计算一段时间内BMS信号统计数据
+        df_state = pd.DataFrame(columns=['sn', 'current', 'Timestamp', 'PackState', 'LineState'])
+        # print("start_time is {}, limit_time is {}".format(st, limit_time))
+        relative_delta_time = datetime.timedelta(hours=6)    # 将时间往前推nh,以便更准确计算BMS状态
+        end_time = st + datetime.timedelta(hours=cal_Period)    # 结束时间
+        relative_time = st - relative_delta_time
+        relative_time = relative_time.strftime('%Y-%m-%d %H:%M:%S')
+        end_time_str = end_time.strftime('%Y-%m-%d %H:%M:%S')
+        df_data = dbManager.get_data(sn=sn[0], start_time=relative_time, end_time=end_time_str, data_groups=['bms'])
+        df_bms = df_data['bms']
+        df_bms = df_bms.drop_duplicates(['时间戳'])
+        df_bms = df_bms.reset_index(drop=True)
+        df_bms['时间戳'] = pd.to_datetime(df_bms['时间戳'])
+        print('{} BMS data read Well Done!'.format(sn[0]))
+
+        df_state['current'] = df_bms['总电流[A]']
+        df_state['Timestamp'] = df_bms['时间戳']
+        df_state['sn'] = sn[0]
+
+        if len(df_state[df_state['Timestamp'] >= st]) > 0:     # 无数据则不计算
+            df_state = SignalMonitor._set_working_states(df_state)    # 根据电流初步定义BMS状态
+            if len(df_state) > 1:
+                df_state = SignalMonitor._set_standby_states(df_state)    # 根据静置时间修正standby状态
+                df_state = SignalMonitor._set_lowpwr_states(df_state)    # 根据静置持续时间设置lowpwr状态
+            df_state_spec = df_state[df_state['Timestamp'] >= st]
+            df_state_spec = df_state_spec.reset_index(drop=True)    # 去除为准确计算BMS状态而多获取的数据
+            df_res = SignalMonitor._get_offline_info(sn, df_state_spec, df_last_state, df_res, 'BMS')    # 计算设定时间段内信号质量数据
+            df_last_info = df_state_spec.loc[len(df_state_spec) - 1]
+            df_last_state = df_last_state.append(df_last_info)    # 记录该段时间内最后数据
+            df_last_state = df_last_state.reset_index(drop=True)
+        return df_res,df_state, df_last_state
+    
+    def get_gps_offline_stat(self,sn, st, et, df_state, df_res_gps, df_last_state_gps, cal_Period=24):    # 计算一段时间内GPS信号统计数据
+        df_state_gps = pd.DataFrame(columns=['sn', 'Timestamp', 'PackState', 'LineState'])
+        # print("start_time is {}, limit_time is {}".format(st, limit_time))
+        end_time = st + datetime.timedelta(hours=cal_Period)    # 结束时间
+        start_time_str = st.strftime('%Y-%m-%d %H:%M:%S')
+        end_time_str = end_time.strftime('%Y-%m-%d %H:%M:%S')
+        df_data = dbManager.get_data(sn=sn[0], start_time=start_time_str, end_time=end_time_str, data_groups=['gps'])
+        df_gps = df_data['gps']
+        df_gps = df_gps.drop_duplicates(['时间戳'])
+        df_gps = df_gps.reset_index(drop=True)
+        df_gps['时间戳'] = pd.to_datetime(df_gps['时间戳'])
+        print('{} GPS data read Well Done!'.format(sn[0]))
+
+        df_state_gps['Timestamp'] = df_gps['时间戳']
+        df_state_gps['sn'] = sn[0]
+
+        if len(df_state_gps) > 0:    # 无数据则不计算    
+            df_state_gps = SignalMonitor._set_gps_working_states(df_state, df_state_gps)    # 根据同时间段内BMS状态计算GPS数据对应的BMS状态
+            df_res_gps = SignalMonitor._get_offline_info(sn, df_state_gps, df_last_state_gps, df_res_gps, 'GPS')    # 计算设定时间段内信号质量数据
+            df_last_info = df_state_gps.loc[len(df_state_gps) - 1]
+            df_last_state_gps = df_last_state_gps.append(df_last_info)    # 记录该段时间内最后数据
+            df_last_state_gps = df_last_state_gps.reset_index(drop=True)
+        return df_res_gps, df_last_state_gps
+
+

+ 167 - 0
LIB/MIDDLE/User_persona.py

@@ -0,0 +1,167 @@
+# 读取数据
+import numpy as np
+import pandas as pd
+import preprocess.preprocess
+import importlib
+import ana.parameters
+import datetime
+import os
+import matplotlib
+import openpyxl
+
+file_path = r'D:\Work\Interior\Cloud_BMS\data_ana\7250.csv'
+sn_list = pd.read_csv(file_path,encoding='gbk')
+sn_list = sn_list.values.tolist()
+# print(sn_list)
+sn_list = [['PK504B10100004301']]
+df_res = pd.DataFrame(columns=['sn', 'date', 'odo', 'capacity', 'energy', 'energy_rate', 'acc_time_drive',
+                               'acc_time_stand', 'acc_time_charge', 'avr_stand_tem', 'avr_stand_tem_rate',
+                               'max_pwr', 'regen_flag', 'regen_rate', 'avr_speed', 'max_speed', 'avr_drive_tem',
+                               'avr_drive_tem_rate', 'center_long', 'center_lat', 'rad'])
+df_soh_res = pd.DataFrame(columns=['sn', 'time', 'accum_ah', 'soh_cell01', 'soh_cell02', 'soh_cell03',
+                                   'soh_cell04', 'soh_cell05', 'soh_cell06', 'soh_cell07',
+                                   'soh_cell08', 'soh_cell09', 'soh_cell10', 'soh_cell11',
+                                   'soh_cell12', 'soh_cell13', 'soh_cell14', 'soh_cell15',
+                                   'soh_cell16', 'soh_cell17', 'soh_cell18', 'soh_cell19',
+                                   'soh_cell20'])
+df_cell_res = pd.DataFrame(columns=['sn', 'time', 'status', 'volt_cell01', 'volt_cell02', 'volt_cell03',
+                                    'volt_cell04', 'volt_cell05', 'volt_cell06', 'volt_cell07',
+                                    'volt_cell08', 'volt_cell09', 'volt_cell10', 'volt_cell11',
+                                    'volt_cell12', 'volt_cell13', 'volt_cell14', 'volt_cell15',
+                                    'volt_cell16', 'volt_cell17', 'volt_cell18', 'volt_cell19',
+                                    'volt_cell20', 'volt_max', 'volt_min', 'volt_avr', 'soc_diff',
+                                    'soc_diff_div', 'over_discharge'])
+
+for sn in sn_list:
+    # 数据读取
+    base_path = r'D:\Work\Interior\Cloud_BMS\data_ana\Data_Files'
+    time = '_from_2020-04-27_to_2021-04-27.csv'
+    bms_file = base_path + r'\\' + sn[0] + '\BMS_' + sn[0] + time
+    gps_file = base_path + r'\\' + sn[0] + '\GPS_' + sn[0] + time
+    # print(bms_file)
+    if not os.path.exists(bms_file):
+        print('{} bms file does not exist!!!!!!'.format(sn[0]))
+        continue
+    if not os.path.exists(gps_file):
+        print('{} gps file does not exist!!!!!!'.format(sn[0]))
+        continue
+    df_bms = pd.read_csv(bms_file, encoding='GB2312')
+    df_gps = pd.read_csv(gps_file, encoding='GB2312')
+    df_bms = df_bms.drop_duplicates(['时间戳'])
+    df_gps = df_gps.drop_duplicates(['时间戳'])
+    df_bms = df_bms.reset_index(drop=True)
+    df_gps = df_gps.reset_index(drop=True)
+    df_bms['时间戳'] = pd.to_datetime(df_bms['时间戳'])
+    df_gps['时间戳'] = pd.to_datetime(df_gps['时间戳'])
+    print('{} data read Well Done!'.format(sn[0]))
+    df_bms.to_csv('result2.csv', index=False, encoding='GB2312')
+    # 数据预处理
+    # 1、数据分段
+    # 2、GPS数据可靠与否的判断(根据GPS计算出的平均车速<2认为可靠)
+    importlib.reload(preprocess.preprocess)
+    df_bms = preprocess.preprocess.data_split(df_bms)
+    df_bms.to_csv('result.csv',encoding='GB2312')
+    df_bms, df_gps, prepro_record = preprocess.preprocess.data_gps_judge(df_bms, df_gps, 2)
+    print('{} data preprocess Well Done!'.format(sn[0]))
+    df_bms.to_csv('result.csv', index=False, encoding='GB2312')
+    df_gps.to_csv('result1.csv', index=False, encoding='GB2312')
+    importlib.reload(ana.parameters)
+    # test = ana.parameters.sta_one_drive_cycle(df_bms, df_gps, prepro_record, time_window=3600*24, step=3600*24, start_time="00:00:00")
+
+    # print(test)
+    # 计算Daily数据
+
+    start_time = df_bms.loc[0, '时间戳']
+    # print(start_time)
+    cur_time = start_time
+    index = 0
+    while cur_time < df_bms.loc[len(df_bms) - 1, '时间戳']:
+        if cur_time.day != start_time.day:
+            break
+        else:
+            index = index + 1
+            cur_time = df_bms.loc[index, '时间戳']
+    start = '00:00:00'
+    start_time = datetime.datetime.strptime(str(df_bms.loc[index, '时间戳'])[0:10] + ' ' + start, '%Y-%m-%d %H:%M:%S')
+    # print(index, start_time)
+    timeDelta = datetime.timedelta(days=1)
+    end_time = start_time + timeDelta
+    # print(start_time, end_time)
+    while end_time < df_bms.loc[len(df_bms) - 1, '时间戳']:
+        # while end_time < df_bms.loc[8500, '时间戳']:
+        df_sel_bms = df_bms[(df_bms['时间戳'] >= start_time) & (df_bms['时间戳'] <= end_time)]
+        df_sel_bms = df_sel_bms.reset_index(drop=True)
+        df_sel_gps = df_gps[(df_gps['时间戳'] >= start_time) & (df_gps['时间戳'] <= end_time)]
+        df_sel_gps = df_sel_gps.reset_index(drop=True)
+        if len(df_sel_bms) == 0:
+            continue
+        date = ana.parameters.get_date(df_sel_bms)
+
+        odo_total, odo_sum, odo_plus = ana.parameters.get_daily_odo(df_sel_bms, df_sel_gps)
+        print('total={},odo={},plus={}'.format(odo_total, odo_sum, odo_plus))
+
+        # 计算单日里程,单日平均车速,单日最高车速
+        # print(start_time)
+        odo, avr_speed, max_speed = ana.parameters.get_daily_odo_and_speed(df_sel_bms, df_sel_gps)
+        # 计算单日使用容量,单日使用能量
+        capacity, energy = ana.parameters.get_daily_capacity_and_energy(df_sel_bms, 55)
+        # 计算单日平均电耗:kwh/100km
+        if odo > 10:
+            energy_rate = energy / odo * 100
+        else:
+            energy_rate = 0
+        # 计算单日累积时间(行驶、静置、充电)
+        acc_time_drive = ana.parameters.get_daily_accum_time(df_sel_bms, 'drive')
+        acc_time_stand = ana.parameters.get_daily_accum_time(df_sel_bms, 'stand')
+        acc_time_charge = ana.parameters.get_daily_accum_time(df_sel_bms, 'charge')
+        # 计算过程平均温度,平均温升(静置、行驶)
+
+        avr_stand_tem, avr_stand_tem_rate = ana.parameters.get_daily_stand_temp(df_sel_bms, 'stand')
+        avr_drive_tem, avr_drive_tem_rate = ana.parameters.get_daily_stand_temp(df_sel_bms, 'drive')
+        # 计算车辆功率
+        max_pwr = ana.parameters.get_daily_max_pwr(df_sel_bms, 'drive')
+        # 计算regen数据,是否有regen以及regen比例
+        regen_flag, regen_rate = ana.parameters.get_daily_regen(df_sel_bms, 'drive')
+        # 计算活动范围,圆心和半径
+
+        center_long, center_lat, rad = ana.parameters.get_working_scope(df_sel_bms, df_sel_gps, 'drive')
+
+        df_res = df_res.append({'sn': sn[0],
+                                'date': date,
+                                'odo': odo,
+                                'capacity': capacity,
+                                'energy': energy,
+                                'energy_rate': energy_rate,
+                                'acc_time_drive': acc_time_drive,
+                                'acc_time_stand': acc_time_stand,
+                                'acc_time_charge': acc_time_charge,
+                                'avr_stand_tem': avr_stand_tem,
+                                'avr_stand_tem_rate': avr_stand_tem_rate,
+                                'max_pwr': max_pwr,
+                                'regen_flag': regen_flag,
+                                'regen_rate': regen_rate,
+                                'avr_speed': avr_speed,
+                                'max_speed': max_speed,
+                                'avr_drive_tem': avr_drive_tem,
+                                'avr_drive_tem_rate': avr_drive_tem_rate,
+                                'center_long': center_long,
+                                'center_lat': center_lat,
+                                'rad': rad}, ignore_index=True)
+        start_time = end_time
+        end_time = start_time + timeDelta
+        # print(end_time,df_bms.loc[len(df_bms) - 1, '时间戳'])
+    print('{} daily data process Well Done!'.format(sn[0]))
+
+    # 计算电池周期性数据
+    df_soh_res_single, df_cell_res_single = ana.parameters.get_soh(df_bms, sn)
+    df_soh_res = pd.concat([df_soh_res, df_soh_res_single], ignore_index=True)
+    df_cell_res = pd.concat([df_cell_res, df_cell_res_single], ignore_index=True)
+    print('{} period data process Well Done!'.format(sn[0]))
+
+path = r'D:\Work\Interior\Cloud_BMS\data_ana\report\daily_data_analysis.csv'
+df_res.to_csv(path, index=False, encoding='GB2312')
+path = r'D:\Work\Interior\Cloud_BMS\data_ana\report\period_data_analysis.xlsx'
+writer = pd.ExcelWriter(path)
+df_soh_res.to_excel(writer, "SOH数据")
+df_cell_res.to_excel(writer, "一致性数据")
+writer.save()

+ 199 - 0
LIB/MIDDLE/ana.py

@@ -0,0 +1,199 @@
+
+import datetime
+import tools.tools
+import pdb
+import pandas as pd
+import numpy as np
+from sklearn.cluster import DBSCAN
+
+# 数据分析
+# 按月统计 停车(静置+充电)发送数据最长的地点
+def sta_stop_position(df_bms, df_gps, days=30):
+    df_res = pd.DataFrame(columns=['time', 'lat', 'long', 'max_duration'])
+    # 从静置+充电数据段,且GPS可靠的数据中进行统计
+    start_time = df_bms.loc[0, '时间戳']
+    timeDelta = datetime.timedelta(days=days)
+    end_time = start_time + timeDelta
+    while end_time < df_bms.loc[len(df_bms)-1, '时间戳']:
+        df_res_temp = pd.DataFrame(columns=['time', 'lat', 'long', 'duration'])
+        df_sel = df_bms[(df_bms['时间戳']>start_time) & (df_bms['时间戳']<=end_time)]
+        data_number_list = sorted(list(set(df_sel[(df_sel['data_status'].isin(['charge', 'stand'])) & (df_sel['gps_rely']==1)
+                                             ]['data_split_by_status'])))
+        # 每段数据的经纬度求均值后记录下来
+        for data_number in data_number_list[:]:
+            df_sel_bms = df_sel[df_sel['data_split_by_status'] == data_number]
+            df_sel_bms = df_sel_bms.reset_index(drop=True)
+            df_sel_gps = df_gps[(df_gps['时间戳']>df_sel_bms.loc[0,'时间戳']) & (df_gps['时间戳']<df_sel_bms.loc[len(df_sel_bms)-1,'时间戳'])]
+            df_sel_gps = df_sel_gps.reset_index(drop=True)
+
+            deltaT = abs(df_sel_gps.loc[0,'时间戳'] - df_sel_gps.loc[len(df_sel_gps)-1,'时间戳']).total_seconds()
+            df_res_temp = df_res_temp.append({'time': df_sel_gps.loc[0,'时间戳'],
+                                    'lat':np.mean(df_sel_gps['纬度']), 
+                                    'long':np.mean(df_sel_gps['经度']), 
+                                    'duration':deltaT}, ignore_index=True)
+
+        # 利用聚类算法,将靠近的停车地点合并
+        # 计算每次停车的GPS地点之间的距离
+        count = len(df_res_temp)
+        dis_mat_half = np.full((count,count), 0.0)
+        for i in range(count):
+            for j in range(i,count):
+                dis_mat_half[i][j] = tools.tools.cal_distance(df_res_temp.loc[i,'lat'],df_res_temp.loc[i,'long'],
+                                                       df_res_temp.loc[j,'lat'],df_res_temp.loc[j,'long'])      
+        dis_mat=np.array(dis_mat_half)+np.transpose(dis_mat_half) 
+
+        # 执行聚类算法,聚类参数:距离50,类内最少样本数10
+        dbscan = DBSCAN(eps=0.05, min_samples=10, metric='precomputed').fit(dis_mat)
+        # 将对应的类内的GPS合并
+        class_label = list(sorted(set(dbscan.labels_)))
+        if -1 in class_label:
+            class_label.remove(-1)
+        for label in class_label:
+            index = sorted(np.where(dbscan.labels_ == label))[0]
+            min_index = index[0]
+            gps_lat = df_res_temp.loc[min_index,'lat']
+            gps_long = df_res_temp.loc[min_index,'long']
+            temp_duration = df_res_temp.loc[min_index,'duration']
+            for i in index[1:]:
+                gps_lat = gps_lat + df_res_temp.loc[i, 'lat']
+                gps_long = gps_long + df_res_temp.loc[i, 'long']
+                temp_duration = temp_duration + df_res_temp.loc[i, 'duration']
+                df_res_temp.drop(index=i, inplace=True)
+            df_res_temp.loc[min_index, 'lat'] = gps_lat/len(index)
+            df_res_temp.loc[min_index, 'long'] = gps_long/len(index)
+            df_res_temp.loc[min_index, 'duration'] = temp_duration
+
+        df_res = df_res.append({'time': start_time[0:10],
+                                    'lat':np.mean(df_sel_gps['纬度']), 
+                                    'long':np.mean(df_sel_gps['经度']), 
+                                    'max_duration':df_res_temp['duration'].max()/3600.0}, ignore_index=True)
+
+        start_time = end_time
+        end_time = end_time + timeDelta
+    return df_res
+
+# 统计单位时间内的累积行车时长、soc累积使用量以及累积行驶里程(若GPS可信)
+# 计算单位时间内行车时长占比, 单位时间内行车soc平均变化量,单位时间内平均里程数。
+# 输入 
+# time_window: 统计时间长度
+# step: 时间窗口滑动步进值
+def sta_one_drive_cycle(df_bms, df_gps, prepro_record, time_window=3600, step=3600, start_time="00:00:00"):
+    st = datetime.datetime.strptime(str(df_bms.loc[0, '时间戳'])[0:10] + ' ' + start_time, '%Y-%m-%d %H:%M:%S')
+    et = st + datetime.timedelta(seconds=time_window)
+    time_list = []
+    driveT_list = []
+    driveSoc_list = []
+    driveOdo_list = []
+    driveOdoRevise_list = []
+    while (et < df_bms.loc[len(df_bms)-1, '时间戳']):
+        df_t = df_bms[(df_bms['时间戳'] > st ) & (df_bms['时间戳'] < et )]
+        df_t = df_t.reset_index(drop=True)
+
+        driveT = 0
+        driveSoc = 0
+        driveOdo = 0
+        driveOdoRevise = 0
+        if not df_t.empty:
+            deltaT = (df_t.loc[len(df_t)-1, '时间戳'] - df_t.loc[0, '时间戳']).total_seconds()
+            df_drive = df_t[df_t['data_status']=='drive']
+            df_drive = df_drive.reset_index(drop=True)
+            data_number_list = sorted(list(set(df_drive['data_split_by_status'])))
+
+            for data_number in data_number_list[:]:
+                df_d = df_drive[df_drive['data_split_by_status'] == data_number]
+                df_d = df_d.reset_index(drop=True)
+                driveT = driveT + (df_d.loc[len(df_d)-1, '时间戳'] - df_d.loc[0, '时间戳']).total_seconds()
+                driveSoc = driveSoc + (df_d.loc[0, 'SOC[%]'] - df_d.loc[len(df_d)-1, 'SOC[%]'])
+                if df_d.loc[0, 'gps_rely'] == 1 and driveOdo != None:
+                    df_sel_gps = df_gps[(df_gps['时间戳']>=df_d.loc[0,'时间戳']) & (df_gps['时间戳']<=df_d.loc[len(df_d)-1,'时间戳'])]
+                    df_sel_gps = df_sel_gps.reset_index(drop=True)
+                    if len(df_sel_gps) > 0:
+                        driveOdo = driveOdo + (df_sel_gps.loc[len(df_sel_gps)-1, 'odo'] - df_sel_gps.loc[0, 'odo'])
+                        
+                    else:
+                        driveOdo = None
+                else:
+                    driveOdo = None 
+        time_list.append(st)
+        driveT_list.append(driveT)
+        driveSoc_list.append(driveSoc)
+        driveOdo_list.append(driveOdo)
+        st = st + datetime.timedelta(seconds=step)
+        et = st + datetime.timedelta(seconds=time_window)
+    if prepro_record['drive']<0.8 and sum(driveSoc_list) > 0:
+        # 计算能耗
+        sum_odo = 0
+        sum_soc = 0
+        for i,odo in enumerate(driveOdo_list):
+            if odo !=0 and not pd.isnull(odo):
+                sum_odo += odo
+                sum_soc += driveSoc_list[i]
+        ene_consump = sum_odo/sum_soc
+        st = datetime.datetime.strptime(str(df_bms.loc[0, '时间戳'])[0:10] + ' ' + start_time, '%Y-%m-%d %H:%M:%S')
+        et = st + datetime.timedelta(seconds=time_window)
+        driveOdoRevise_list = []
+        while (et < df_bms.loc[len(df_bms)-1, '时间戳']):
+            df_t = df_bms[(df_bms['时间戳'] > st ) & (df_bms['时间戳'] < et )]
+            df_t = df_t.reset_index(drop=True)
+
+            driveOdoRevise = 0
+            if not df_t.empty:
+                deltaT = (df_t.loc[len(df_t)-1, '时间戳'] - df_t.loc[0, '时间戳']).total_seconds()
+                df_drive = df_t[df_t['data_status']=='drive']
+                df_drive = df_drive.reset_index(drop=True)
+                data_number_list = sorted(list(set(df_drive['data_split_by_status'])))
+
+                for data_number in data_number_list[:]:
+                    df_d = df_drive[df_drive['data_split_by_status'] == data_number]
+                    df_d = df_d.reset_index(drop=True)
+
+                    if df_d.loc[0, 'gps_rely'] == 1 and driveOdo != None:
+                        df_sel_gps = df_gps[(df_gps['时间戳']>=df_d.loc[0,'时间戳']) & (df_gps['时间戳']<=df_d.loc[len(df_d)-1,'时间戳'])]
+                        df_sel_gps = df_sel_gps.reset_index(drop=True)
+                        if len(df_sel_gps) > 0:
+                            driveOdoRevise = driveOdoRevise + (df_sel_gps.loc[len(df_sel_gps)-1, 'odo'] - df_sel_gps.loc[0, 'odo'])
+                        else:
+                            driveOdoRevise = driveOdoRevise + (df_d.loc[0, 'SOC[%]'] - df_d.loc[len(df_d)-1, 'SOC[%]']) * ene_consump
+                    else:
+                            driveOdoRevise = driveOdoRevise + (df_d.loc[0, 'SOC[%]'] - df_d.loc[len(df_d)-1, 'SOC[%]']) * ene_consump
+            driveOdoRevise_list.append(driveOdoRevise)
+            st = st + datetime.timedelta(seconds=step)
+            et = st + datetime.timedelta(seconds=time_window)
+    else:
+        driveOdoRevise_list = [None] * len(driveSoc_list)
+    df_res = pd.DataFrame({'time':time_list, 'driveT':driveT_list, 'driveSoc':driveSoc_list, 'driveOdo':driveOdo_list, 'driveOdoRevise':driveOdoRevise_list})
+    return df_res
+
+
+# 统计充电前的GPS海拔与充电时的GPS海拔差(若GPS可信)
+def sta_charge_height(df_bms, df_gps):
+    data_number_list = sorted(list(set(df_bms['data_split_by_status'])))
+    df_sel_bms_last = df_bms[df_bms['data_split_by_status'] == 1]
+    df_sel_bms_last = df_sel_bms_last.reset_index(drop=True)
+    time_list = []
+    last_height_list = []
+    height_list = []
+    last_status_list = []
+    for data_number in data_number_list[1:]:
+        df_sel_bms = df_bms[df_bms['data_split_by_status'] == data_number]
+        df_sel_bms = df_sel_bms.reset_index(drop=True)
+        if df_sel_bms_last.loc[0, 'data_status'] != 'charge' and df_sel_bms.loc[0, 'data_status'] == 'charge' and\
+           df_sel_bms_last.loc[0, 'gps_rely'] == 1 and df_sel_bms.loc[0, 'gps_rely'] == 1:
+
+            df_sel_gps_last = df_gps[(df_gps['时间戳']>=df_sel_bms_last.loc[0,'时间戳']) & (df_gps['时间戳']<=df_sel_bms_last.loc[len(df_sel_bms_last)-1,'时间戳'])]
+            df_sel_gps_last = df_sel_gps_last.reset_index(drop=True)
+            df_sel_gps = df_gps[(df_gps['时间戳']>=df_sel_bms.loc[0,'时间戳']) & (df_gps['时间戳']<=df_sel_bms.loc[len(df_sel_bms)-1,'时间戳'])]
+            df_sel_gps = df_sel_gps.reset_index(drop=True)
+            if (df_sel_bms_last.loc[0, 'data_status'] == 'stand'):
+                last_height = df_sel_gps_last['海拔m'].mean()
+            else:
+                last_height = df_sel_gps_last.loc[len(df_sel_gps_last)-1, '海拔m']
+            cur_height = df_sel_gps['海拔m'].mean()
+            time_list.append(df_sel_bms.loc[0, '时间戳'])
+            last_height_list.append(last_height)
+            height_list.append(cur_height)
+            last_status_list.append(df_sel_bms_last.loc[0, 'data_status'])
+        df_sel_bms_last = df_sel_bms.copy()
+
+    df_res = pd.DataFrame({'time':time_list, 'last_status':last_status_list, 'last_height':last_height_list, 'cur_height':height_list, 'diff':np.array(height_list)-np.array(last_height_list)})
+    return df_res

+ 665 - 0
LIB/MIDDLE/parameters.py

@@ -0,0 +1,665 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Wed Dec 30 14:38:35 2020
+
+@author: striv
+"""
+# import getdata
+import time
+import datetime
+import numpy as np
+import pandas as pd
+import os
+import matplotlib.pyplot as plt
+import tools.tools
+import importlib
+importlib.reload(tools.tools)
+import math
+from collections import Counter
+from sklearn.cluster import DBSCAN
+
+
+def getcellsoc(Chrg_data_static_cellu,soc_ocv_table):
+    pass
+    x = soc_ocv_table.iloc[:,0]
+    y = soc_ocv_table.iloc[:,1]*1000
+    xnew=np.linspace(0,105,1000)
+    # print(x,y)
+    z1 = np.polyfit(x,y,11)
+    ynew = np.polyval(z1,xnew)
+    data = [xnew,ynew]
+    soc_ocv_ply = pd.DataFrame(data,index=('SOC','OCV')).T
+    cellsoc = pd.DataFrame()
+    cellsoc_list=[]
+    temp = []
+    for i_num,i in enumerate(Chrg_data_static_cellu):
+        i = i /1000.0
+        temp = soc_ocv_table.iloc[:,1]
+        ocv_temp = soc_ocv_table.iloc[:,1].tolist()
+        ocv_temp.append(i)
+        ocv_temp.sort()
+        ocv_index = ocv_temp.index(i)
+        if ocv_index == 0:
+            value = 0
+        elif ocv_index == len(ocv_temp)-1:
+            value = 100
+        else:
+            temp1=ocv_temp[ocv_index-1]
+            temp2=ocv_temp[ocv_index+1]
+            j_temp1 = temp.index[temp==temp1][0]
+            j_temp2 = temp.index[temp==temp2][0]
+            value = (soc_ocv_table.iloc[j_temp1,0]*(temp2-i) + soc_ocv_table.iloc[j_temp2,0]*(i-temp1))/min(1,(temp2 - temp1))
+        cellsoc.loc[0,'cell'+str(i_num+1)] = min([100,value])
+        cellsoc_list.append(cellsoc.loc[0,'cell'+str(i_num+1)])
+        temp = []
+    return cellsoc,cellsoc_list
+
+
+def get_date(df):
+    time = df.loc[0, '时间戳']
+    date = time.strftime('%Y-%m-%d %H:%M:%S')
+    date = date[0:10]
+    return date
+
+def get_daily_odo_and_speed(df,df_gps):
+    data_number_list = sorted(list(set(df[df['data_status'].isin(['drive' or 'stand'])]['data_split_by_status'])))
+    odo_sum = 0
+    res_single = pd.DataFrame(columns=['speed'])
+    max_speed_single = []
+    max_speed = -1
+    for data_number in data_number_list[0:]:
+        df_sel_bms = df[df['data_split_by_status'] == data_number]
+        df_sel_bms = df_sel_bms.reset_index(drop=True)
+        # print('bmsstart={},bmsend={}'.format(df_sel_bms.loc[0, '时间戳'], df_sel_bms.loc[len(df_sel_bms)-1, '时间戳']))
+        df_sel_gps = df_gps[(df_gps['时间戳']>df_sel_bms.loc[0,'时间戳']) & (df_gps['时间戳']<df_sel_bms.loc[len(df_sel_bms)-1,'时间戳'])]
+        df_sel_gps = df_sel_gps.reset_index(drop=True)
+
+        if len(df_sel_gps) >= 2:
+
+            odo, avg_speed, odo_list, speed_list, invalid_flag = tools.tools.cal_odo_speed(df_sel_gps['纬度'], df_sel_gps['经度'],
+                                                                                           df_sel_gps['时间戳'])
+            # print('gpsstart={},gpsend={},odo={}'.format(df_sel_gps.loc[0, '时间戳'], df_sel_gps.loc[len(df_sel_gps) - 1, '时间戳'],odo))
+            # print(df_sel_gps['时间戳'])
+            odo_sum = odo_sum + odo
+            res_single = res_single.append({'speed':avg_speed},ignore_index = True)
+            max_speed_single.append(np.max(speed_list))
+    avr_speed = np.mean(res_single['speed'])
+    if len(max_speed_single) > 0:
+        max_speed = np.max(max_speed_single)
+    return odo_sum, avr_speed, max_speed
+
+
+def get_daily_odo(df,df_gps):
+    odo_sum = 0
+    odo_plus = 0
+    soc_sum = 0
+    data_number_list = sorted(list(set(df[df['data_status'].isin(['drive' or 'stand' or 'charge' or 'None'])]['data_split_by_status'])))
+    data_number_list = sorted(list(set(df['data_split_by_status'])))
+    for i in range(0, len(data_number_list)):
+    # for data_number in data_number_list[0:]:
+        data_number = data_number_list[i]
+        df_sel_bms = df[df['data_split_by_status'] == data_number]
+        # print(df_sel_bms)
+        df_sel_bms = df_sel_bms.reset_index(drop=True)
+        df_sel_gps = df_gps[
+            (df_gps['时间戳'] >= df_sel_bms.loc[0, '时间戳']) & (df_gps['时间戳'] <= df_sel_bms.loc[len(df_sel_bms) - 1, '时间戳'])]
+        df_sel_gps = df_sel_gps.reset_index(drop=True)
+        if len(df_sel_gps) >= 2:
+            odo, avg_speed, odo_list, speed_list, invalid_flag = tools.tools.cal_odo_speed(df_sel_gps['纬度'],
+                                                                                           df_sel_gps['经度'],
+                                                                                           df_sel_gps['时间戳'])
+            soc = abs(df_sel_bms.loc[len(df_sel_bms) - 1, 'SOC[%]'] - df_sel_bms.loc[0, 'SOC[%]'])
+        if len(df_sel_gps) >= 2 and len(df_sel_bms) >= 2:
+            last_df = df_sel_bms[
+            (df_sel_bms['时间戳'] >= df_sel_gps.loc[0, '时间戳']) & (
+                        df_sel_bms['时间戳'] <= df_sel_gps.loc[len(df_sel_gps) - 1, '时间戳'])]
+            last_df = last_df.reset_index(drop=True)
+            last_soc = last_df.loc[len(last_df) - 1, 'SOC[%]']
+            last_time = last_df.loc[len(last_df) - 1, '时间戳']
+        else:
+            last_soc = -1
+        odo_sum = odo_sum + odo
+        soc_sum = soc_sum + soc
+        if i < len(data_number_list) - 1:
+            data_number = data_number_list[i + 1]
+            df_sel_bms = df[df['data_split_by_status'] == data_number]
+            df_sel_bms = df_sel_bms.reset_index(drop=True)
+            df_sel_gps = df_gps[
+        (df_gps['时间戳'] >= df_sel_bms.loc[0, '时间戳']) & (df_gps['时间戳'] <= df_sel_bms.loc[len(df_sel_bms) - 1, '时间戳'])]
+            df_sel_gps = df_sel_gps.reset_index(drop=True)
+            if len(df_sel_gps) >= 2 and len(df_sel_bms) >= 2:
+                cur_df = df_sel_bms[
+                (df_sel_bms['时间戳'] >= df_sel_gps.loc[0, '时间戳']) & (
+                            df_sel_bms['时间戳'] <= df_sel_gps.loc[len(df_sel_gps) - 1, '时间戳'])]
+                cur_df = cur_df.reset_index(drop=True)
+                if len(cur_df)>0:
+                    # print('cur={}'.format(cur_df))
+                    cur_soc = cur_df.loc[0, 'SOC[%]']
+                    cur_time = cur_df.loc[0, '时间戳']
+                else:
+                    cur_soc = -1
+            else:
+                cur_soc = -1
+            print(last_time, cur_time, last_soc, cur_soc)
+            if abs(cur_soc - last_soc) > 1 and soc_sum > 1 and cur_soc >= 0 and last_soc >= 0:
+                odo_plus = odo_plus + odo_sum/soc_sum*abs(cur_soc - last_soc)
+    return odo_sum+odo_plus, odo_sum, odo_plus
+
+def sta_one_drive_cycle(df_bms, df_gps, prepro_record, time_window=3600, step=3600, start_time="00:00:00"):
+    st = datetime.datetime.strptime(str(df_bms.loc[0, '时间戳'])[0:10] + ' ' + start_time, '%Y-%m-%d %H:%M:%S')
+    et = st + datetime.timedelta(seconds=time_window)
+    time_list = []
+    driveT_list = []
+    driveSoc_list = []
+    driveOdo_list = []
+    driveOdoRevise_list = []
+    while (et < df_bms.loc[len(df_bms) - 1, '时间戳']):
+        df_t = df_bms[(df_bms['时间戳'] > st) & (df_bms['时间戳'] < et)]
+        df_t = df_t.reset_index(drop=True)
+
+        driveT = 0
+        driveSoc = 0
+        driveOdo = 0
+        driveOdoRevise = 0
+        if not df_t.empty:
+            deltaT = (df_t.loc[len(df_t) - 1, '时间戳'] - df_t.loc[0, '时间戳']).total_seconds()
+            df_drive = df_t[df_t['data_status'] == 'drive']
+            df_drive = df_drive.reset_index(drop=True)
+            data_number_list = sorted(list(set(df_drive['data_split_by_status'])))
+
+            for data_number in data_number_list[:]:
+                df_d = df_drive[df_drive['data_split_by_status'] == data_number]
+                df_d = df_d.reset_index(drop=True)
+                driveT = driveT + (df_d.loc[len(df_d) - 1, '时间戳'] - df_d.loc[0, '时间戳']).total_seconds()
+                driveSoc = driveSoc + (df_d.loc[0, 'SOC[%]'] - df_d.loc[len(df_d) - 1, 'SOC[%]'])
+                if df_d.loc[0, 'gps_rely'] == 1 and driveOdo != None:
+                    df_sel_gps = df_gps[
+                        (df_gps['时间戳'] >= df_d.loc[0, '时间戳']) & (df_gps['时间戳'] <= df_d.loc[len(df_d) - 1, '时间戳'])]
+                    df_sel_gps = df_sel_gps.reset_index(drop=True)
+                    if len(df_sel_gps) > 0:
+                        driveOdo = driveOdo + (df_sel_gps.loc[len(df_sel_gps) - 1, 'odo'] - df_sel_gps.loc[0, 'odo'])
+
+                    else:
+                        driveOdo = None
+                else:
+                    driveOdo = None
+        time_list.append(st)
+        driveT_list.append(driveT)
+        driveSoc_list.append(driveSoc)
+        driveOdo_list.append(driveOdo)
+        st = st + datetime.timedelta(seconds=step)
+        et = st + datetime.timedelta(seconds=time_window)
+        print(driveOdo_list)
+    if prepro_record['drive'] < 0.8 and sum(driveSoc_list) > 0:
+        # 计算能耗
+        sum_odo = 0
+        sum_soc = 0
+        for i, odo in enumerate(driveOdo_list):
+            if odo != 0 and not pd.isnull(odo):
+                sum_odo += odo
+                sum_soc += driveSoc_list[i]
+        if sum_soc > 0:
+            ene_consump = sum_odo / sum_soc
+        else:
+            ene_consump = -1
+        st = datetime.datetime.strptime(str(df_bms.loc[0, '时间戳'])[0:10] + ' ' + start_time, '%Y-%m-%d %H:%M:%S')
+        et = st + datetime.timedelta(seconds=time_window)
+        driveOdoRevise_list = []
+        while (et < df_bms.loc[len(df_bms) - 1, '时间戳']):
+            df_t = df_bms[(df_bms['时间戳'] > st) & (df_bms['时间戳'] < et)]
+            df_t = df_t.reset_index(drop=True)
+
+            driveOdoRevise = 0
+            if not df_t.empty:
+                deltaT = (df_t.loc[len(df_t) - 1, '时间戳'] - df_t.loc[0, '时间戳']).total_seconds()
+                df_drive = df_t[df_t['data_status'] == 'drive']
+                df_drive = df_drive.reset_index(drop=True)
+                data_number_list = sorted(list(set(df_drive['data_split_by_status'])))
+
+                for data_number in data_number_list[:]:
+                    df_d = df_drive[df_drive['data_split_by_status'] == data_number]
+                    df_d = df_d.reset_index(drop=True)
+
+                    if df_d.loc[0, 'gps_rely'] == 1 and driveOdo != None:
+                        df_sel_gps = df_gps[
+                            (df_gps['时间戳'] >= df_d.loc[0, '时间戳']) & (df_gps['时间戳'] <= df_d.loc[len(df_d) - 1, '时间戳'])]
+                        df_sel_gps = df_sel_gps.reset_index(drop=True)
+                        if len(df_sel_gps) > 0:
+                            driveOdoRevise = driveOdoRevise + (
+                                        df_sel_gps.loc[len(df_sel_gps) - 1, 'odo'] - df_sel_gps.loc[0, 'odo'])
+                        else:
+                            driveOdoRevise = driveOdoRevise + (
+                                        df_d.loc[0, 'SOC[%]'] - df_d.loc[len(df_d) - 1, 'SOC[%]']) * ene_consump
+                    else:
+                        driveOdoRevise = driveOdoRevise + (
+                                    df_d.loc[0, 'SOC[%]'] - df_d.loc[len(df_d) - 1, 'SOC[%]']) * ene_consump
+            driveOdoRevise_list.append(driveOdoRevise)
+            st = st + datetime.timedelta(seconds=step)
+            et = st + datetime.timedelta(seconds=time_window)
+    else:
+        driveOdoRevise_list = [None] * len(driveSoc_list)
+    df_res = pd.DataFrame(
+        {'time': time_list, 'driveT': driveT_list, 'driveSoc': driveSoc_list, 'driveOdo': driveOdo_list,
+         'driveOdoRevise': driveOdoRevise_list})
+    return df_res
+
+
+def get_daily_capacity_and_energy(df, cap):
+    data_number_list = sorted(list(set(df[df['data_status'].isin(['drive'])]['data_split_by_status'])))
+    energy_sum = 0
+    capacity_sum = 0
+    for data_number in data_number_list[0:]:
+        df_sel_bms = df[df['data_split_by_status'] == data_number]
+        df_sel_bms = df_sel_bms.reset_index(drop=True)
+        capacity = (df_sel_bms.loc[0, 'SOC[%]'] - df_sel_bms.loc[len(df_sel_bms)-1,'SOC[%]']) * np.mean(df_sel_bms['SOH[%]']) * \
+               cap / 100 / 100
+        energy = capacity * np.mean(df_sel_bms['总电压[V]']) / 1000
+        capacity_sum = capacity_sum + capacity
+        energy_sum = energy_sum + energy
+    return capacity_sum, energy_sum
+
+def get_daily_accum_time(df, status):
+    data_number_list = sorted(list(set(df[df['data_status'].isin([status])]['data_split_by_status'])))
+    accum_time_sum = 0
+    for data_number in data_number_list[0:]:
+        df_sel_bms = df[df['data_split_by_status'] == data_number]
+        df_sel_bms = df_sel_bms.reset_index(drop=True)
+        accum_time = (df_sel_bms.loc[len(df_sel_bms)-1, '时间戳'] - df_sel_bms.loc[0,'时间戳']).seconds
+        accum_time_sum = accum_time_sum + accum_time / 3600
+    return accum_time_sum
+
+def get_daily_stand_temp(df, status):
+    data_number_list = sorted(list(set(df[df['data_status'].isin([status])]['data_split_by_status'])))
+    res_single = pd.DataFrame(columns = ['avr_tem', 'avr_tem_rate'])
+    cycle = 0
+    avr_tem_sum = 0
+    avr_tem_rate_sum =0
+    avr_tem = 0
+    avr_tem_rate = 0
+    for data_number in data_number_list[0:]:
+        cycle = cycle + 1
+        df_sel_bms = df[df['data_split_by_status'] == data_number]
+        df_sel_bms = df_sel_bms.reset_index(drop=True)
+        avr_tem = np.mean(df_sel_bms['单体温度1'])
+        avr_tem_rate = abs(df_sel_bms.loc[len(df_sel_bms)-1, '单体温度1'] - df_sel_bms.loc[0, '单体温度1'])/\
+                   (df_sel_bms.loc[len(df_sel_bms)-1, '时间戳'] - df_sel_bms.loc[0, '时间戳']).seconds * 3600
+        avr_tem_sum = avr_tem_sum + avr_tem
+        avr_tem_rate_sum = avr_tem_rate_sum + avr_tem_rate
+    if cycle > 0:
+        avr_tem = avr_tem_sum / cycle
+        avr_tem_rate = avr_tem_rate_sum / cycle
+    return avr_tem, avr_tem_rate
+
+def get_daily_max_pwr(df, status):
+    data_number_list = sorted(list(set(df[df['data_status'].isin([status])]['data_split_by_status'])))
+    max_pwr = 0
+    res_pwr = pd.DataFrame(columns=['pwr'])
+    for data_number in data_number_list[0:]:
+        df_sel_bms = df[df['data_split_by_status'] == data_number]
+        df_sel_bms = df_sel_bms.reset_index(drop=True)
+        for index in df_sel_bms.index:
+            res_pwr = res_pwr.append({'pwr':df_sel_bms.loc[index, '总电流[A]'] * df_sel_bms.loc[index, '总电压[V]'] / 1000},
+                             ignore_index=True )
+        max_pwr_single = np.max(res_pwr['pwr'])
+        max_pwr = max(max_pwr, max_pwr_single)
+    return max_pwr
+
+def get_daily_regen(df, status):
+    data_number_list = sorted(list(set(df[df['data_status'].isin([status])]['data_split_by_status'])))
+    regen_flag = 0
+    regen_rate = 0
+    regen_count = 0
+    total_count = 0
+    res_pwr = pd.DataFrame(columns=['pwr'])
+    for data_number in data_number_list[0:]:
+        df_sel_bms = df[df['data_split_by_status'] == data_number]
+        df_sel_bms = df_sel_bms.reset_index(drop=True)
+        regen_count = regen_count + len(df_sel_bms[df_sel_bms['总电流[A]'] < -1])
+        total_count = total_count + len(df_sel_bms)
+    if regen_count > 10:
+        regen_flag = 1
+        regen_rate = regen_count / total_count * 100
+    return regen_flag, regen_rate
+
+def get_working_scope(df,df_gps,status):
+    data_number_list = sorted(list(set(df[df['data_status'].isin([status])]['data_split_by_status'])))
+    dis_single = []
+    rad = 3
+    df_sel_gps = pd.DataFrame(columns=['时间戳','经度','纬度','海拔m','速度[km/h]','odo','speed'])
+    for data_number in data_number_list[0:]:
+        df_sel_bms = df[df['data_split_by_status'] == data_number]
+        df_sel_bms = df_sel_bms.reset_index(drop=True)
+        df_sel_gps_single = df_gps[(df_gps['时间戳']>df_sel_bms.loc[0,'时间戳']) & (df_gps['时间戳']<df_sel_bms.loc[len(df_sel_bms)-1,'时间戳'])]
+        df_sel_gps = df_sel_gps.append(df_sel_gps_single)
+    df_sel_gps = df_sel_gps.reset_index(drop=True)
+    center_long = np.mean(df_sel_gps['经度'])
+    center_lat = np.mean(df_sel_gps['纬度'])
+    for i in range(1, len(df_sel_gps)):
+        dis_single.append(math.sqrt(math.pow((df_sel_gps.loc[i, '经度'] - center_long),2) \
+                         + math.pow((df_sel_gps.loc[i, '纬度'] -center_lat),2)) * 111)
+    dis = sorted(dis_single)
+    if len(dis) > 100:
+        rad = dis[math.floor(len(dis) * 0.99)]
+    else:
+        rad = -1
+    return center_long, center_lat, rad
+
+def get_isc(df, status):
+    total_len = 10
+    data_number_list = sorted(list(set(df[df['data_status'].isin([status])]['data_split_by_status'])))
+#     df_res = pd.DataFrame(columns=['time','limit','t1', 't2','t3', 't4','t5', 't6','t7', 't8','t9', 't10','t11', 't12','t13', 't14','tmean',
+#                           'isc1','isc2','isc3','isc4','isc5','isc6','isc7','isc8','isc9','isc10','isc11','isc12','isc13','isc14',
+#                           'res1','res2','res3','res4','res5','res6','res7','res8','res9','res10','res11','res12','res13','res14'])
+    df_res = pd.DataFrame(columns=['time','limit','t1', 't2','t3', 't4','t5', 't6','t7', 't8','t9', 't10','tmean',
+                          'isc1','isc2','isc3','isc4','isc5','isc6','isc7','isc8','isc9','isc10',
+                          'res1','res2','res3','res4','res5','res6','res7','res8','res9','res10'])
+
+    limits = [3360,3361,3362,3363,3364,3365,3366, 3367, 3368, 3369, 3370]
+    num = len(limits)
+    index = 0
+    dd = -1
+    timestamp = 1545730073
+    base_time = datetime.fromtimestamp(timestamp)
+    for data_number in data_number_list[0:]:
+        dd = dd + 1
+        df_sel_bms = df[df['data_split_by_status'] == data_number]
+        df_sel_bms = df_sel_bms.reset_index(drop=True)
+#         current = np.mean(df_sel_bms[df_sel_bms['总电压[V]']>=limits[0]*14 and df_sel_bms['总电压[V]']<=limits[-1]*14]['总电流[A]'])
+        current = 9
+        if df_sel_bms.loc[0, 'SOC[%]'] > 40:
+#             print('delete_data={},time={},soc={}'.format(dd,df_sel_bms.loc[0, '时间戳'],df_sel_bms.loc[0, 'SOC[%]']))
+            continue
+        else:
+            k = -1
+            for limit in limits:
+                k = k + 1
+                df_res.loc[index,'time'] = df_sel_bms.loc[0, '时间戳']
+                for i in range(1,total_len+1):
+#                     print('data={},index={},limit{}={},cell={},time={}'.format(dd,index,k,limit,i,df_sel_bms.loc[0, '时间戳']))
+                    time_list = sorted(list(set(df_sel_bms[df_sel_bms['单体电压'+ str(i)]==limit]['时间戳'])))
+                    time_list1 = list(df_sel_bms[df_sel_bms['单体电压'+ str(i)]==limit]['时间戳'])
+                    
+#                     print(df_sel_bms['单体电压'+ str(i)])
+#                     print('index={},limit{}={},cell={},time={}'.format(index,k,limit,i,time_list[0]))
+                    df_res.loc[index,'limit'] = limit
+                    if len(time_list) > 0:
+                        time_counter = Counter(time_list1)
+                        most_counterNum = time_counter.most_common(2)
+                        time_raw = most_counterNum[0]
+#                         print('value={},type={}'.format(most_counterNum,type(time_raw)))
+                        time = (time_list[-1] - base_time).seconds
+#                     print('limit={},i={},time={}'.format(limit, i ,time))
+                        df_res.loc[index,'t'+str(i)] = time_list[-1]
+                        df_res.loc[index,'isc'+str(i)] = time
+#                         print('data={},index={},limit{}={},cell={},time={}'.format(dd,index,k,limit,i,time_list[-1]))
+                        if i == total_len:
+                            print(df_res.loc[index,'t1':'t'+str(total_len)])
+                            df_res.loc[index,'tmean'] = np.mean(df_res.loc[index,'isc1':'isc'+str(total_len)])
+                            df_res.loc[index,'isc1':'isc'+str(total_len)] = df_res.loc[index,'isc1':'isc'+str(total_len)] -                                                                       df_res.loc[index,'tmean']
+#                             print('data={},k={},index={}'.format(dd,k,index))
+                            total_index = index
+                            index = index + 1
+#                             df_res.loc[index*num+k,'isc1':'isc14'] = df_res.loc[index*num+k,'t1':'t14'] -                                                                              df_res.loc[index*num+k,'tmean']
+
+                    else:
+#                         print('NoValue_data={},time={},soc={},limit{}={},cell={}'.
+#                               format(dd,df_sel_bms.loc[0, '时间戳'],df_sel_bms.loc[0, 'SOC[%]'],k,limit,i))
+                        break
+    for limit in limits:
+#         print(df_res)
+        data_number_list =  sorted(list(set(df_res[df_res['limit']==limit].index)))
+#         print(data_number_list)
+        df_res.loc[data_number_list[0],'res1':'res'+str(total_len)]=0
+        index = 1
+        for data_number in data_number_list[1:]:
+            for i in range(1,total_len+1):
+                df_res.loc[data_number_list[index],'res'+str(i)]=(df_res.loc[data_number_list[index],'isc'+str(i)] -                                                                    df_res.loc[data_number_list[index-1],'isc'+str(i)])*1000*current /                                                                (df_res.loc[data_number_list[index],'time'] -                                                                          df_res.loc[data_number_list[index-                                                                                         1],'time']).total_seconds()
+            index = index + 1
+    result=[]
+    for i in range(1,total_len+1):
+#         result.append(np.mean(df_res[11:total_index,'res'+str(i)]))
+        mean_value = df_res['res'+str(i)][11:total_index+1].mean()
+        result.append(mean_value)
+#         print('i{}={},total_index={}'.format(i,df_res['res'+str(i)][11:total_index+1],total_index))
+        
+    return df_res,result
+
+
+def get_charge_statics(df, status):
+    # 计算充电行为
+    df_res = pd.DataFrame(columns=['time', 'num','duration','Capacity'])
+    df_res_single = pd.DataFrame(columns=['time','cycle','start_time','stop_time','start_soc','stop_soc','gps_long','gps_lat',])
+    start_time = df_bms.loc[3771, '时间戳']
+    timeDelta = datetime.timedelta(days=1)
+    end_time = start_time + timeDelta
+    while end_time < df_bms.loc[len(df_bms)-1, '时间戳']:
+#     import pdb;pdb.set_trace()
+        cycle = 0
+        df_res_temp = pd.DataFrame(columns=['time', 'num'])
+        df_sel = df_bms[(df_bms['时间戳']>=start_time) & (df_bms['时间戳']<=end_time)]
+        origin_index = list(df_sel.index)
+#     print(origin_index[0])
+        data_number_list = sorted(list(set(df_sel[df_sel['data_status'].isin(['charge'])]['data_split_by_status'])))
+        if (df_bms.loc[origin_index[0], 'data_status'] == df_bms.loc[origin_index[0]-1, 'data_status'] == ['charge']):
+            charge_num = len(data_number_list)-1
+            start = 1
+        else:
+            charge_num = len(data_number_list)
+            start = 0
+    
+        for data_number in data_number_list[start:]:
+        
+            df_sel_bms = df_sel[df_sel['data_split_by_status'] == data_number]
+            df_sel_bms = df_sel_bms.reset_index(drop=True)
+            df_sel_gps = df_gps[(df_gps['时间戳']>df_sel_bms.loc[0,'时间戳']) & (df_gps['时间戳']<df_sel_bms.loc[len(df_sel_bms)-1,'时间戳'])]
+            df_sel_gps = df_sel_gps.reset_index(drop=True)
+        
+            if data_number != data_number_list[start]:
+#             startTime= datetime.datetime.strptime(df_sel_bms.loc[0, '时间戳'],"%Y-%m-%d %H:%M:%S")
+                startTime= df_sel_bms.loc[0, '时间戳']
+                startSoc= df_sel_bms.loc[0, 'SOC[%]']
+                if (startTime - endTime).seconds < 5*60 or abs(endSoc - startSoc) < 5:
+                    reconn = 1
+                else:
+                    reconn = 0
+            else:
+                reconn = 0
+        
+
+#         endTime= datetime.datetime.strptime(df_sel_bms.loc[len(df_sel_bms)-1, '时间戳'],"%Y-%m-%d %H:%M:%S")
+            endTime= df_sel_bms.loc[len(df_sel_bms)-1, '时间戳']
+            endSoc= df_sel_bms.loc[len(df_sel_bms)-1, 'SOC[%]']
+#         index = sorted(np.where(df_sel['data_split_by_union'] == data_number))[0]
+#         print(index)
+#         min_index = index[0]
+#         print(data_number_list)
+#         print(df_sel)
+#          print('start={},index={},data_num={},value={}'.format(start,min_index,data_number,df_sel.loc[min_index+1, '时间戳']))
+#         if ((df_sel_bms.loc[len(df_sel_bms)-1, 'SOC[%]'] - df_sel_bms.loc[0, 'SOC[%]']) > 10.0) and reconn==0:
+            if 1:
+                cycle = cycle + 1
+#             print('cycle = {}, delta = {}'.format(cycle, df_sel_bms.loc[len(df_sel_bms)-1, 'SOC[%]'] - df_sel_bms.loc[0, 'SOC[%]']))
+                df_res_single = df_res_single.append({'time': df_sel.loc[origin_index[0], '时间戳'], 
+                                              'cycle': cycle,
+                                              'start_time': df_sel_bms.loc[0, '时间戳'],
+                                              'stop_time': df_sel_bms.loc[len(df_sel_bms)-1, '时间戳'],
+                                              'start_soc': df_sel_bms.loc[0, 'SOC[%]'],
+                                              'stop_soc': df_sel_bms.loc[len(df_sel_bms)-1, 'SOC[%]'],
+                                              'gps_long': np.mean(df_sel_gps['经度']),
+                                              'gps_lat': np.mean(df_sel_gps['纬度'])}, ignore_index=True)
+#     print(df_sel_bms)
+        df_res = df_res.append({'time': df_sel.loc[origin_index[0], '时间戳'], 
+                            'num': charge_num}, ignore_index=True)
+        start_time = end_time
+        end_time = start_time + timeDelta
+    print(df_res_single)
+
+
+
+
+def get_soh(df_bms, sn):
+    # 计算SOH和一致性
+    df_res = pd.DataFrame(columns=['sn','time', 'accum_ah','soh_cell01','soh_cell02','soh_cell03',
+                               'soh_cell04','soh_cell05','soh_cell06','soh_cell07',
+                               'soh_cell08','soh_cell09','soh_cell10','soh_cell11',
+                               'soh_cell12','soh_cell13','soh_cell14','soh_cell15',
+                               'soh_cell16','soh_cell17','soh_cell18','soh_cell19',
+                               'soh_cell20'])
+    df_cell_res = pd.DataFrame(columns=['sn','time','status','volt_cell01','volt_cell02','volt_cell03',
+                               'volt_cell04','volt_cell05','volt_cell06','volt_cell07',
+                               'volt_cell08','volt_cell09','volt_cell10','volt_cell11',
+                               'volt_cell12','volt_cell13','volt_cell14','volt_cell15',
+                               'volt_cell16','volt_cell17','volt_cell18','volt_cell19',
+                               'volt_cell20','volt_max','volt_min', 'volt_avr','soc_diff','soc_diff_div','over_discharge'])
+
+    df_sel = df_bms
+    # print(sn[0][0:2])
+    if sn[0][0:5] == 'PK504':
+        soc_ocv_table = pd.read_excel(r'D:\Work\Interior\Cloud_BMS\Overall\产品信息\电池OCV表格.xlsx', '60AH')
+        cellcap = 55 # Capacity
+    elif sn[0][0:5] == 'PK501':
+        soc_ocv_table = pd.read_excel(r'D:\Work\Interior\Cloud_BMS\Overall\产品信息\电池OCV表格.xlsx', '40AH')
+        cellcap = 40  # Capacity
+    elif sn[0][0:2] == 'UD':
+        soc_ocv_table = pd.read_excel(r'D:\Work\Interior\Cloud_BMS\Overall\产品信息\电池OCV表格.xlsx', '50AH')
+        cellcap = 50  # Capacity
+
+    cellsoh_list = []
+    data_number_list = sorted(list(set(df_sel[df_sel['data_status'].isin(['charge'])]['data_split_by_status'])))
+    start = 1
+    for data_number in data_number_list[start:-2]:
+        ## 充电以及前后数据全部获取
+        df_sel_bms_relax_start = df_sel[df_sel['data_split_by_status'] == data_number-1]
+        df_sel_bms = df_sel[df_sel['data_split_by_status'] == data_number]
+        df_sel_bms_relax_end = df_sel[df_sel['data_split_by_status'] == data_number+1]
+        origin_index = list(df_sel_bms.index)
+        origin_index_relax_start = list(df_sel_bms_relax_start.index)
+        origin_index_relax_end = list(df_sel_bms_relax_end.index)
+        df_sel_bms_relax_start = df_sel_bms_relax_start.reset_index(drop=True)
+        df_sel_bms = df_sel_bms.reset_index(drop=True)
+        df_sel_bms_relax_end = df_sel_bms_relax_end.reset_index(drop=True)
+        ## 充电前后静置时间
+#         delta_time_start = (df_sel_bms_relax_start.loc[len(df_sel_bms_relax_start)-1,'时间戳'] - df_sel_bms_relax_start.loc[0,'时间戳']).seconds
+        delta_time_end = (df_sel_bms_relax_end.loc[len(df_sel_bms_relax_end)-1,'时间戳'] - df_sel_bms_relax_end.loc[0,'时间戳']).seconds
+#         print(df_sel_bms_relax_start.loc[len(df_sel_bms_relax_start)-1,'时间戳'],
+#               df_sel_bms_relax_start.loc[0,'时间戳'],
+#               df_sel_bms_relax_start.loc[len(df_sel_bms_relax_start)-1,'data_status'],
+#               df_sel_bms_relax_end.loc[len(df_sel_bms_relax_end)-1,'data_status'],
+#               df_sel_bms.loc[0,'时间戳'],
+#               delta_time_start,
+#               delta_time_end)
+        ##  充电前后静置并且充电前静置超过10min,充电后静置超过3h
+        if (df_sel_bms_relax_start.loc[len(df_sel_bms_relax_start)-1,'data_status'] == 'stand' or \
+            df_sel_bms_relax_start.loc[len(df_sel_bms_relax_start)-1,'data_status'] == 'drive') and \
+            df_sel_bms_relax_end.loc[len(df_sel_bms_relax_end)-1,'data_status'] == 'stand' and\
+            delta_time_end > 18000:
+            ## 记录充电相关信息
+            start_time = df_sel_bms.loc[0,'时间戳']
+            end_time = df_sel_bms.loc[len(df_sel_bms)-1,'时间戳']
+            relax_time = df_sel_bms_relax_end.loc[len(df_sel_bms_relax_end)-1,'时间戳']
+            start_current = df_sel_bms_relax_start.loc[len(df_sel_bms_relax_start)-1,'总电流[A]']
+            end_current = df_sel_bms_relax_end.loc[len(df_sel_bms_relax_end)-1,'总电流[A]']
+#             print(start_time,end_time,relax_time,start_current,end_current)
+            ## 记录充电开始前信息
+            start_volt_class = df_sel.loc[origin_index[0]-3,'单体电压1':'单体电压20']
+            start_index = start_volt_class
+            start_index = start_index.apply(lambda x: 1 if x<3.279 or (x > 3.292 and x < 3.307) else 0)
+            start_index = np.array(start_index)
+            start_soc,start_cellsoc_list = getcellsoc(start_volt_class,soc_ocv_table)
+            if np.min(start_volt_class) < 3182:
+                over_discharge = 1
+            else:
+                over_discharge = 0
+            if np.max(start_volt_class) > 3640:
+                over_charge = 1
+            else:
+                over_charge = 0
+            df_cell_res = df_cell_res.append({'sn':sn,
+                                              'time':df_sel.loc[origin_index[0]-3,'时间戳'],
+                                              'status':'start',
+                                              'volt_cell01':start_volt_class[0],'volt_cell02':start_volt_class[1],
+                                              'volt_cell03':start_volt_class[2],'volt_cell04':start_volt_class[3],
+                                              'volt_cell05':start_volt_class[4],'volt_cell06':start_volt_class[5],
+                                              'volt_cell07':start_volt_class[6],'volt_cell08':start_volt_class[7],
+                                              'volt_cell09':start_volt_class[8],'volt_cell10':start_volt_class[9],
+                                              'volt_cell11':start_volt_class[10],'volt_cell12':start_volt_class[11],
+                                              'volt_cell13':start_volt_class[12],'volt_cell14':start_volt_class[13],
+                                              'volt_cell15':start_volt_class[14],'volt_cell16':start_volt_class[15],
+                                              'volt_cell17':start_volt_class[16],'volt_cell18':start_volt_class[17],
+                                              'volt_cell19':start_volt_class[18],'volt_cell20':start_volt_class[19],
+                                              'volt_max':np.max(start_volt_class),
+                                              'volt_min':np.min(start_volt_class), 
+                                              'volt_avr':np.mean(start_volt_class),
+                                              'soc_diff':np.max(start_cellsoc_list)-np.min(start_cellsoc_list),
+                                              'soc_diff_div':np.mean(start_volt_class[0:9])-np.mean(start_volt_class[10:19]),
+                                              'over_discharge':over_discharge,'over_charge':over_charge}, ignore_index=True)
+            ## 记录充电结束信息
+            end_volt_class = df_sel_bms_relax_end.loc[len(df_sel_bms_relax_end)-3,'单体电压1':'单体电压20']
+            end_index = end_volt_class
+            end_index = end_index.apply(lambda x: 1 if x>3.346 or (x > 3.292 and x < 3.307) else 0)
+            end_index = np.array(end_index)
+            end_soc,end_cellsoc_list = getcellsoc(end_volt_class,soc_ocv_table)
+            if np.min(end_volt_class) < 3182:
+                over_discharge = 1
+            else:
+                over_discharge = 0
+            if np.max(end_volt_class) > 3640:
+                over_charge = 1
+            else:
+                over_charge = 0
+            df_cell_res = df_cell_res.append({'sn':sn,
+                                              'time':df_sel_bms_relax_end.loc[len(df_sel_bms_relax_end)-3,'时间戳'],
+                                              'status':'end',
+                                              'volt_cell01':end_volt_class[0],'volt_cell02':end_volt_class[1],
+                                              'volt_cell03':end_volt_class[2],'volt_cell04':end_volt_class[3],
+                                              'volt_cell05':end_volt_class[4],'volt_cell06':end_volt_class[5],
+                                              'volt_cell07':end_volt_class[6],'volt_cell08':end_volt_class[7],
+                                              'volt_cell09':end_volt_class[8],'volt_cell10':end_volt_class[9],
+                                              'volt_cell11':end_volt_class[10],'volt_cell12':end_volt_class[11],
+                                              'volt_cell13':end_volt_class[12],'volt_cell14':end_volt_class[13],
+                                              'volt_cell15':end_volt_class[14],'volt_cell16':end_volt_class[15],
+                                              'volt_cell17':end_volt_class[16],'volt_cell18':end_volt_class[17],
+                                              'volt_cell19':end_volt_class[18],'volt_cell20':end_volt_class[19],
+                                              'volt_max':np.max(end_volt_class),
+                                              'volt_min':np.min(end_volt_class), 
+                                              'volt_avr':np.mean(end_volt_class),
+                                              'soc_diff':np.max(end_cellsoc_list)-np.min(end_cellsoc_list),
+                                              'soc_diff_div':np.mean(end_volt_class[0:9])-np.mean(end_volt_class[10:19]),
+                                              'over_discharge':over_discharge,'over_charge':over_charge}, ignore_index=True)
+            ## 计算过程量,deltaSOC和deltaAh
+            delta_cellsoc_list = np.array(end_cellsoc_list) - np.array(start_cellsoc_list)
+            
+            accum = 0
+            for time_num in range(1,len(df_sel_bms)):
+                delta_time = (df_sel_bms.loc[time_num,'时间戳'] - df_sel_bms.loc[time_num-1,'时间戳']).seconds
+                accum = accum - df_sel_bms.loc[time_num,'总电流[A]']* delta_time/3600
+            ## 单次SOC间隔超过10%,计算SOH
+            if np.mean(delta_cellsoc_list) > 10:
+                cellsoh=accum/delta_cellsoc_list*100/cellcap*100
+#                 cellsoh=cellsoh*start_index*end_index
+#                 print(cellsoh)
+                df_res = df_res.append({'sn':sn,
+                                        'time':df_sel_bms.loc[0,'时间戳'],
+                                        'accum_ah':accum,
+                                        'soh_cell01':cellsoh[0],'soh_cell02':cellsoh[1],'soh_cell03':cellsoh[2],
+                                        'soh_cell04':cellsoh[3],'soh_cell05':cellsoh[4],'soh_cell06':cellsoh[5],
+                                        'soh_cell07':cellsoh[6],'soh_cell08':cellsoh[7],'soh_cell09':cellsoh[8],
+                                        'soh_cell10':cellsoh[9],'soh_cell11':cellsoh[10],'soh_cell12':cellsoh[11],
+                                        'soh_cell13':cellsoh[12],'soh_cell14':cellsoh[13],'soh_cell15':cellsoh[14],
+                                        'soh_cell16':cellsoh[15],'soh_cell17':cellsoh[16],'soh_cell18':cellsoh[17],
+                                        'soh_cell19':cellsoh[18],'soh_cell20':cellsoh[19]},ignore_index=True)
+                cellsoh_list_single=cellsoh.tolist()
+                cellsoh_list.append(cellsoh_list_single)
+                
+    return df_res, df_cell_res
+
+
+def get_charge_start_time(df,status):
+    data_number_list = sorted(list(set(df[df['data_status'].isin([status])]['data_split_by_status'])))
+    for data_number in data_number_list[0:]:
+        df_sel_bms = df[df['data_split_by_status'] == data_number]
+        df_sel_bms = df_sel_bms.reset_index(drop=True)
+        start_time = df_sel_bms.loc[0,'时间戳']
+        start_time = datetime.strftime(start_time, "%H:%M:%S")
+        limit_time = datetime.strptime("20:00:00", "%H:%M:%S")
+        print('start_time{}>20:00:{}'.format(start_time,limit_time))

+ 152 - 0
demo.ipynb

@@ -0,0 +1,152 @@
+{
+ "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']"
+   ],
+   "outputs": [
+    {
+     "output_type": "stream",
+     "name": "stdout",
+     "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",
+      "\n"
+     ]
+    }
+   ],
+   "metadata": {}
+  },
+  {
+   "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'])"
+   ],
+   "outputs": [],
+   "metadata": {}
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "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",
+    "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,
+   "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",
+    "    break"
+   ],
+   "outputs": [],
+   "metadata": {}
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "source": [
+    "# 生成pydoc 说明文档\r\n",
+    "! python -m pydoc -w LIB\\BACKEND\\Tools.py"
+   ],
+   "outputs": [],
+   "metadata": {}
+  }
+ ],
+ "metadata": {
+  "interpreter": {
+   "hash": "b3ba2566441a7c06988d0923437866b63cedc61552a5af99d1f4fb67d367b25f"
+  },
+  "kernelspec": {
+   "name": "python3",
+   "display_name": "Python 3.8.8 64-bit ('base': conda)"
+  },
+  "language_info": {
+   "name": "python",
+   "version": "3.8.8",
+   "mimetype": "text/x-python",
+   "codemirror_mode": {
+    "name": "ipython",
+    "version": 3
+   },
+   "pygments_lexer": "ipython3",
+   "nbconvert_exporter": "python",
+   "file_extension": ".py"
+  },
+  "orig_nbformat": 4
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}

+ 111 - 0
函数说明/DBManager.html

@@ -0,0 +1,111 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module DBManager</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong>DBManager</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:f%3A%5Cwork%5Cqx%5Cdata_analyze_platform%5Clib%5Cbackend%5Cdbmanager.py">f:\work\qx\data_analyze_platform\lib\backend\dbmanager.py</a></font></td></tr></table>
+    <p><tt>暂时采用http方式获取历史数据。<br>
+&nbsp;<br>
+预留:后期若改用通过访问数据库的形式进行数据的获取,则本文件负责数据库的连接,sql指令的执行,数据获取等功能。</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+    
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="datetime.html">datetime</a><br>
+<a href="json.html">json</a><br>
+<a href="numpy.html">numpy</a><br>
+</td><td width="25%" valign=top><a href="os.html">os</a><br>
+<a href="pandas.html">pandas</a><br>
+<a href="pdb.html">pdb</a><br>
+</td><td width="25%" valign=top><a href="requests.html">requests</a><br>
+<a href="time.html">time</a><br>
+<a href="urllib.html">urllib</a><br>
+</td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+    
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="builtins.html#object">builtins.object</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="DBManager.html#DBManager">DBManager</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="DBManager">class <strong>DBManager</strong></a>(<a href="builtins.html#object">builtins.object</a>)</font></td></tr>
+    
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
+<td colspan=2><tt><a href="#DBManager">DBManager</a>(host='',&nbsp;port='',&nbsp;auth='',&nbsp;db='',&nbsp;username='',&nbsp;password='')<br>
+&nbsp;<br>
+#&nbsp;import&nbsp;http.client<br>
+#&nbsp;http.client.HTTPConnection._http_vsn&nbsp;=&nbsp;10<br>
+#&nbsp;http.client.HTTPConnection._http_vsn_str&nbsp;=&nbsp;'HTTP/1.1'<br>&nbsp;</tt></td></tr>
+<tr><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="DBManager-__enter__"><strong>__enter__</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="DBManager-__exit__"><strong>__exit__</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="DBManager-__init__"><strong>__init__</strong></a>(self, host='', port='', auth='', db='', username='', password='')</dt><dd><tt>Initialize&nbsp;self.&nbsp;&nbsp;See&nbsp;help(type(self))&nbsp;for&nbsp;accurate&nbsp;signature.</tt></dd></dl>
+
+<dl><dt><a name="DBManager-close"><strong>close</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="DBManager-connect"><strong>connect</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="DBManager-get_data"><strong>get_data</strong></a>(self, url='http://172.16.126.13/store/load?dataType={}&amp;limit=0&amp;sn={}', sn='', start_time='', end_time='', data_groups=['bms', 'gps'])</dt><dd><tt>获取指定&nbsp;sn&nbsp;和起止日期的bms和gps数据.<br>
+添加了重试机制。<br>
+&nbsp;<br>
+--------------输入参数------------<br>
+url:数据获取url,&nbsp;可采用默认值<br>
+sn:&nbsp;str,&nbsp;电池sn号<br>
+start_time:&nbsp;str,&nbsp;开始时间<br>
+end_time:&nbsp;str,&nbsp;结束时间<br>
+data_groups:&nbsp;&nbsp;选择需要获取的数据组,可填入多个字符串(默认只获取bms和gps数据)<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bms:&nbsp;bms数据<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;gps:gps数据<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;system:system数据<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;accum:accum数据<br>
+&nbsp;<br>
+&nbsp;<br>
+--------------输出参数------------<br>
+df_data:&nbsp;{'bms':dataframe,&nbsp;'gps':dataframe,&nbsp;'system':dataframe,&nbsp;;accum':dataframe}</tt></dd></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#55aa55">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Data</strong></big></font></td></tr>
+    
+<tr><td bgcolor="#55aa55"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><strong>S</strong> = &lt;RegexFlag.DOTALL: 16&gt;</td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#7799ee">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Author</strong></big></font></td></tr>
+    
+<tr><td bgcolor="#7799ee"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%">wlm</td></tr></table>
+</body></html>

+ 151 - 0
函数说明/DataPreProcess.html

@@ -0,0 +1,151 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module DataPreProcess</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong>DataPreProcess</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:d%3A%5Cplatform%5Cplatform%5Cbackend%5Cdatapreprocess.py">d:\platform\platform\backend\datapreprocess.py</a></font></td></tr></table>
+    <p><tt>数据预处理类</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+    
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="PathSetting.html">PathSetting</a><br>
+<a href="Tools.html">Tools</a><br>
+</td><td width="25%" valign=top><a href="numpy.html">numpy</a><br>
+<a href="pandas.html">pandas</a><br>
+</td><td width="25%" valign=top><a href="pdb.html">pdb</a><br>
+<a href="sys.html">sys</a><br>
+</td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+    
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="builtins.html#object">builtins.object</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="DataPreProcess.html#DataPreProcess">DataPreProcess</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="DataPreProcess">class <strong>DataPreProcess</strong></a>(<a href="builtins.html#object">builtins.object</a>)</font></td></tr>
+    
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="DataPreProcess-__init__"><strong>__init__</strong></a>(self)</dt><dd><tt>Initialize&nbsp;self.&nbsp;&nbsp;See&nbsp;help(type(self))&nbsp;for&nbsp;accurate&nbsp;signature.</tt></dd></dl>
+
+<dl><dt><a name="DataPreProcess-cal_stand_time"><strong>cal_stand_time</strong></a>(self, dfin)</dt><dd><tt>#&nbsp;计算静置时间<br>
+#&nbsp;将每次行车或充电的前后静置时间,赋值给stand_time&nbsp;列,&nbsp;单位为分钟<br>
+&nbsp;<br>
+----------------输入参数---------<br>
+dfin:&nbsp;调用data_split_by_status()后输出的bms数据<br>
+&nbsp;<br>
+----------------输出参数----------<br>
+在输入数据后面,增加stand_time列<br>
+stand_time&nbsp;:&nbsp;在行车段或充电段的起止两个位置处,表明开始前和结束后的静置时长,单位为分钟</tt></dd></dl>
+
+<dl><dt><a name="DataPreProcess-combine_drive_stand"><strong>combine_drive_stand</strong></a>(self, dfin)</dt><dd><tt>合并放电和静置段:将两次充电之间的所有数据段合并为一段,&nbsp;状态分为&nbsp;charge&nbsp;和not&nbsp;charge<br>
+---------------输入----------<br>
+dfin:&nbsp;调用data_split_by_status()后输出的bms数据<br>
+&nbsp;<br>
+---------------输出----------<br>
+在输入数据后面,增加data_split_by_status_after_combine,&nbsp;data_status_after_combine&nbsp;两列<br>
+data_split_by_status_after_combine:&nbsp;将两次充电间的数据合并后的段序号<br>
+data_status_after_combine:&nbsp;每段数据的状态标识</tt></dd></dl>
+
+<dl><dt><a name="DataPreProcess-data_gps_judge_after_combine"><strong>data_gps_judge_after_combine</strong></a>(self, df_bms, df_gps, time_diff_thre=600, odo_sum_thre=200, drive_spd_thre=80, parking_spd_thre=2)</dt><dd><tt>GPS数据可靠性判断函数2&nbsp;(基于combine后的分段)&nbsp;判别方式同data_gps_judge</tt></dd></dl>
+
+<dl><dt><a name="DataPreProcess-data_split_by_status"><strong>data_split_by_status</strong></a>(self, dfin, drive_interval_threshold=120, charge_interval_threshold=300, drive_stand_threshold=120, charge_stand_threshold=300)</dt><dd><tt>#&nbsp;数据预处理分段,&nbsp;将原始数据段分为&nbsp;charge、drive、stand、none段<br>
+#&nbsp;状态判断<br>
+#&nbsp;1、drive:(状态为2或3&nbsp;且&nbsp;存在电流&gt;0&nbsp;)&nbsp;或&nbsp;(电流持续为0&nbsp;且&nbsp;持续时间&lt;阈值&nbsp;且&nbsp;上一段数据为行车)<br>
+#&nbsp;2、charge:(状态为2或3&nbsp;且&nbsp;不存在电流&gt;0&nbsp;)&nbsp;或&nbsp;(电流持续为0&nbsp;且&nbsp;持续时间&lt;阈值&nbsp;且&nbsp;上一段数据为充电)<br>
+#&nbsp;3、stand:(电流持续为0&nbsp;且&nbsp;是数据段的第一段)&nbsp;或&nbsp;(电流持续为0&nbsp;且&nbsp;持续时间&gt;阈值)<br>
+#&nbsp;4、none:&nbsp;其他<br>
+&nbsp;<br>
+--------------输入参数-------------:<br>
+drive_interval_threshold:&nbsp;行车段拼接阈值,如果两段行车的间隔时间小于该值,则两段行车合并。<br>
+charge_interval_threshold:&nbsp;充电段拼接阈值,如果两段充电的间隔时间小于该值,则两段充电合并。<br>
+drive_stand_threshold:&nbsp;静置段合并至行车段阈值,如果静置时间小于该值,则合并到上一段的行车中。<br>
+charge_stand_threshold:&nbsp;静置段合并至充电段阈值,如果静置时间小于该值,则合并到上一段的充电中。<br>
+&nbsp;<br>
+--------------输出-----------------:<br>
+在原始数据后面,增加data_split_by_crnt,&nbsp;data_split_by_status,&nbsp;data_status&nbsp;三列<br>
+data_split_by_crnt:&nbsp;按电流分段的序号<br>
+data_split_by_status:按电流和状态分段的序号<br>
+data_status:&nbsp;状态标识</tt></dd></dl>
+
+<dl><dt><a name="DataPreProcess-data_split_by_time"><strong>data_split_by_time</strong></a>(self, dfin, default_time_threshold=300, drive_time_threshold=300, charge_time_threshold=300, stand_time_threshold=1800)</dt><dd><tt>#&nbsp;该函数用来解决数据丢失问题导致的分段序号异常,<br>
+#&nbsp;将经过data_split_by_status分段后的数据,每个段内两行数据的时间跳变如果超过阈值,则继续分为两段<br>
+&nbsp;<br>
+--------------输入参数-------------:<br>
+dfin:&nbsp;&nbsp;调用data_split_by_status之后的函数<br>
+default_time_threshold:&nbsp;默认时间阈值,如果状态内部时间跳变大于该值,则划分为两段<br>
+drive_time_threshold:&nbsp;行车时间阈值,如果行车状态内部时间跳变大于该值,则划分为两段<br>
+charge_time_threshold:&nbsp;充电时间阈值,如果充电状态内部时间跳变大于该值,则划分为两段<br>
+stand_time_threshold:静置时间阈值,如果静置状态内部时间跳变大于该值,则划分为两段<br>
+&nbsp;<br>
+--------------输出-----------------:<br>
+在输入数据后面,增加data_split_by_status_time&nbsp;一列<br>
+data_split_by_status_time:&nbsp;按照状态和时间分段后的序号</tt></dd></dl>
+
+<dl><dt><a name="DataPreProcess-gps_data_judge"><strong>gps_data_judge</strong></a>(self, df_bms, df_gps, time_diff_thre=300, odo_sum_thre=200, drive_spd_thre=80, parking_spd_thre=2)</dt><dd><tt>GPS数据可靠性判断函数(基于combine前的分段)<br>
+&nbsp;<br>
+GPS数据出现以下情况时,判定为不可靠:<br>
+1)如果该段对应的地理位置数据&nbsp;少于2&nbsp;个,则认为不可靠<br>
+2)如果截取的GPS数据的起止时间,与BMS数据段的起止时间相差超过阈值,则认为不可靠<br>
+3)如果行车段&nbsp;累积里程超过阈值,车速超过阈值<br>
+4)&nbsp;如果非行车段&nbsp;车速超过阈值<br>
+&nbsp;<br>
+--------------输入参数--------------:<br>
+time_diff_thre:&nbsp;时间差阈值<br>
+odo_sum_thre:&nbsp;累积里程阈值<br>
+drive_spd_thre:&nbsp;行车车速阈值<br>
+parking_spd_thre:&nbsp;非行车状态车速阈值<br>
+&nbsp;<br>
+--------------输出参数--------------:<br>
+df_bms&nbsp;增加一列gps_rely,&nbsp;表明对应的GPS数据是否可靠。<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1:可靠<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;0:&nbsp;表示不可靠的原因<br>
+df_gps&nbsp;增加两列odo,&nbsp;speed,&nbsp;分别表示前后两点间的距离和速度</tt></dd></dl>
+
+<dl><dt><a name="DataPreProcess-time_filter"><strong>time_filter</strong></a>(self, df_bms, df_gps)</dt><dd><tt>#&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'''</tt></dd></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#55aa55">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Data</strong></big></font></td></tr>
+    
+<tr><td bgcolor="#55aa55"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><strong>CONF_PATH</strong> = r'D:\Platform\platform\CONFIGURE\'<br>
+<strong>defpath</strong> = r'.;C:\bin'</td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#7799ee">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Author</strong></big></font></td></tr>
+    
+<tr><td bgcolor="#7799ee"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%">wlm</td></tr></table>
+</body></html>

+ 145 - 0
函数说明/IndexStaByOneCycle.html

@@ -0,0 +1,145 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module IndexStaByOneCycle</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong>IndexStaByOneCycle</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:d%3A%5Cplatform%5Cplatform%5Cmiddle%5Cindexstabyonecycle.py">d:\platform\platform\middle\indexstabyonecycle.py</a></font></td></tr></table>
+    <p><tt>基于单一状态(一次行车、一次静置、一次充电)的指标统计库</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+    
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="PathSetting.html">PathSetting</a><br>
+<a href="Tools.html">Tools</a><br>
+</td><td width="25%" valign=top><a href="datetime.html">datetime</a><br>
+<a href="numpy.html">numpy</a><br>
+</td><td width="25%" valign=top><a href="pandas.html">pandas</a><br>
+<a href="sys.html">sys</a><br>
+</td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+    
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="builtins.html#object">builtins.object</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="IndexStaByOneCycle.html#IndexStaByOneCycle">IndexStaByOneCycle</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="IndexStaByOneCycle">class <strong>IndexStaByOneCycle</strong></a>(<a href="builtins.html#object">builtins.object</a>)</font></td></tr>
+    
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="IndexStaByOneCycle-__init__"><strong>__init__</strong></a>(self)</dt><dd><tt>Initialize&nbsp;self.&nbsp;&nbsp;See&nbsp;help(type(self))&nbsp;for&nbsp;accurate&nbsp;signature.</tt></dd></dl>
+
+<dl><dt><a name="IndexStaByOneCycle-acc_time_sta"><strong>acc_time_sta</strong></a>(self, time_array)</dt><dd><tt>一个cycle的持续时间<br>
+---------输入参数------------<br>
+time_array&nbsp;:&nbsp;一次cycle对应的time数据<br>
+---------输出参数------------<br>
+本cycle的持续时间,单位&nbsp;h</tt></dd></dl>
+
+<dl><dt><a name="IndexStaByOneCycle-capacity_sta"><strong>capacity_sta</strong></a>(self, cap, soc_array, soh_array)</dt><dd><tt>一个cycle净累积ah统计<br>
+---------输入参数------------<br>
+cap&nbsp;:&nbsp;标称容量<br>
+soc_array&nbsp;:&nbsp;一个cycle对应的soc数据<br>
+soh_array&nbsp;:&nbsp;一个cycle对应的soh数据<br>
+---------输出参数------------<br>
+本次行车的累积ah</tt></dd></dl>
+
+<dl><dt><a name="IndexStaByOneCycle-chrg_max_pwr_sta"><strong>chrg_max_pwr_sta</strong></a>(self, volt_array, crnt_array)</dt><dd><tt>一个cycle的充电功率最大值<br>
+---------输入参数------------<br>
+volt_array&nbsp;:&nbsp;一个cycle对应的volt数据<br>
+crnt_array&nbsp;:&nbsp;一个cycle对应的crnt数据<br>
+---------输出参数------------<br>
+本cycle的充电功率最大值</tt></dd></dl>
+
+<dl><dt><a name="IndexStaByOneCycle-dischrg_max_pwr_sta"><strong>dischrg_max_pwr_sta</strong></a>(self, volt_array, crnt_array)</dt><dd><tt>一个cycle的放电功率最大值<br>
+---------输入参数------------<br>
+volt_array&nbsp;:&nbsp;一个cycle对应的volt数据<br>
+crnt_array&nbsp;:&nbsp;一个cycle对应的crnt数据<br>
+---------输出参数------------<br>
+本cycle的放电功率最大值</tt></dd></dl>
+
+<dl><dt><a name="IndexStaByOneCycle-energy_sta"><strong>energy_sta</strong></a>(self, cap, soc_array, soh_array, volt_array)</dt><dd><tt>一个cycle净累积能量统计<br>
+---------输入参数------------<br>
+cap&nbsp;:&nbsp;标称容量<br>
+soc_array&nbsp;:&nbsp;一个cycle对应的soc数据<br>
+soh_array&nbsp;:&nbsp;一个cycle对应的soh数据<br>
+volt_array&nbsp;:&nbsp;一个cycle对应的volt数据<br>
+---------输出参数------------<br>
+本次行车的累积能量</tt></dd></dl>
+
+<dl><dt><a name="IndexStaByOneCycle-mean_temp_sta"><strong>mean_temp_sta</strong></a>(self, temp_array)</dt><dd><tt>一个cycle的单体平均温度<br>
+---------输入参数------------<br>
+temp_array&nbsp;:&nbsp;一个cycle对应的某个单体的temp数据<br>
+---------输出参数------------<br>
+本cycle的单体平均温度</tt></dd></dl>
+
+<dl><dt><a name="IndexStaByOneCycle-odo_sta"><strong>odo_sta</strong></a>(self, odo_array)</dt><dd><tt>一次行车行驶里程统计<br>
+---------输入参数------------<br>
+odo_array&nbsp;:&nbsp;一次行车对应的odo数据<br>
+---------输出参数------------<br>
+如果gps&nbsp;可信,则输出本次行车的累积行驶里程;<br>
+否则,输出None</tt></dd></dl>
+
+<dl><dt><a name="IndexStaByOneCycle-regen_count_sta"><strong>regen_count_sta</strong></a>(self, crnt_array)</dt><dd><tt>一个行车cycle的regen&nbsp;行数<br>
+---------输入参数------------<br>
+crnt_array&nbsp;:&nbsp;一个行车cycle对应的crnt数据<br>
+---------输出参数------------<br>
+本行车cycle的regen行数,&nbsp;总行数</tt></dd></dl>
+
+<dl><dt><a name="IndexStaByOneCycle-speed_sta"><strong>speed_sta</strong></a>(self, sum_odo, acc_time, speed_array)</dt><dd><tt>一个行车cycle的平均速度和最大瞬时速度<br>
+---------输入参数------------<br>
+sum_odo&nbsp;:&nbsp;一个行车cycle对应的累积odo数据<br>
+acc_time&nbsp;:&nbsp;一个行车cycle对应的累积time数据<br>
+speed_array&nbsp;:&nbsp;一个行车cycle对应的speed数据<br>
+---------输出参数------------<br>
+本行车cycle的平均速度和最大速度</tt></dd></dl>
+
+<dl><dt><a name="IndexStaByOneCycle-temp_change_rate_sta"><strong>temp_change_rate_sta</strong></a>(self, time_array, temp_array)</dt><dd><tt>一个cycle的单体温度变化率<br>
+---------输入参数------------<br>
+time_array&nbsp;:&nbsp;一个cycle对应的time数据<br>
+temp_array&nbsp;:&nbsp;一个cycle对应的temp数据<br>
+---------输出参数------------<br>
+本cycle的单体温度变化率</tt></dd></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#55aa55">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Data</strong></big></font></td></tr>
+    
+<tr><td bgcolor="#55aa55"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><strong>CONF_PATH</strong> = r'D:\Platform\platform\CONFIGURE\'</td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#7799ee">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Author</strong></big></font></td></tr>
+    
+<tr><td bgcolor="#7799ee"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%">wlm</td></tr></table>
+</body></html>

+ 115 - 0
函数说明/IndexStaByPeriod.html

@@ -0,0 +1,115 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module IndexStaByPeriod</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong>IndexStaByPeriod</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:d%3A%5Cplatform%5Cplatform%5Cmiddle%5Cindexstabyperiod.py">d:\platform\platform\middle\indexstabyperiod.py</a></font></td></tr></table>
+    <p><tt>基于某个周期(一天,一周...)的指标统计库</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+    
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="IndexStaByOneCycle.html">IndexStaByOneCycle</a><br>
+<a href="PathSetting.html">PathSetting</a><br>
+</td><td width="25%" valign=top><a href="Tools.html">Tools</a><br>
+<a href="datetime.html">datetime</a><br>
+</td><td width="25%" valign=top><a href="numpy.html">numpy</a><br>
+<a href="pandas.html">pandas</a><br>
+</td><td width="25%" valign=top><a href="sys.html">sys</a><br>
+</td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+    
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="builtins.html#object">builtins.object</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="IndexStaByPeriod.html#IndexStaByPeriod">IndexStaByPeriod</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="IndexStaByPeriod">class <strong>IndexStaByPeriod</strong></a>(<a href="builtins.html#object">builtins.object</a>)</font></td></tr>
+    
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="IndexStaByPeriod-__init__"><strong>__init__</strong></a>(self)</dt><dd><tt>Initialize&nbsp;self.&nbsp;&nbsp;See&nbsp;help(type(self))&nbsp;for&nbsp;accurate&nbsp;signature.</tt></dd></dl>
+
+<dl><dt><a name="IndexStaByPeriod-drive_capacity_sta"><strong>drive_capacity_sta</strong></a>(self, cap, df_bms)</dt><dd><tt>计算周期内行车净累积ah<br>
+---------输入参数------------<br>
+cap&nbsp;:&nbsp;标称容量<br>
+df_bms&nbsp;:&nbsp;一段周期内的预处理后的bms数据<br>
+df_gps&nbsp;:&nbsp;一段周期内的预处理后的gps数据<br>
+---------输出参数------------<br>
+sum_ah&nbsp;:&nbsp;本周期的净累积ah</tt></dd></dl>
+
+<dl><dt><a name="IndexStaByPeriod-drive_energy_sta"><strong>drive_energy_sta</strong></a>(self, cap, df_bms)</dt><dd><tt>计算周期内行车净累积能量<br>
+---------输入参数------------<br>
+cap&nbsp;:&nbsp;标称容量<br>
+df_bms&nbsp;:&nbsp;一段周期内的预处理后的bms数据<br>
+df_gps&nbsp;:&nbsp;一段周期内的预处理后的gps数据<br>
+---------输出参数------------<br>
+sum_ah&nbsp;:&nbsp;本周期的净累积能量</tt></dd></dl>
+
+<dl><dt><a name="IndexStaByPeriod-drive_odo_sta"><strong>drive_odo_sta</strong></a>(self, df_bms, df_gps)</dt><dd><tt>计算周期内行车累积行驶里程<br>
+---------输入参数------------<br>
+df_bms&nbsp;:&nbsp;一段周期内的预处理后的bms数据<br>
+df_gps&nbsp;:&nbsp;一段周期内的预处理后的gps数据<br>
+---------输出参数------------<br>
+sum_odo&nbsp;:&nbsp;累积里程,&nbsp;如果该周期内gps均无效,则返回None<br>
+invalid_rate&nbsp;:&nbsp;该周期内gps无效的bms数据行所占比例</tt></dd></dl>
+
+<dl><dt><a name="IndexStaByPeriod-drive_soc_sta"><strong>drive_soc_sta</strong></a>(self, df_bms)</dt><dd><tt>计算周期内行车净累积soc<br>
+---------输入参数------------<br>
+cap&nbsp;:&nbsp;标称容量<br>
+df_bms&nbsp;:&nbsp;一段周期内的预处理后的bms数据<br>
+df_gps&nbsp;:&nbsp;一段周期内的预处理后的gps数据<br>
+---------输出参数------------<br>
+sum_ah&nbsp;:&nbsp;本周期的净累积soc</tt></dd></dl>
+
+<dl><dt><a name="IndexStaByPeriod-drive_time_sta"><strong>drive_time_sta</strong></a>(self, df_bms)</dt><dd><tt>计算周期内累计行车时长/h<br>
+---------输入参数------------<br>
+cap&nbsp;:&nbsp;标称容量<br>
+df_bms&nbsp;:&nbsp;一段周期内的预处理后的bms数据<br>
+df_gps&nbsp;:&nbsp;一段周期内的预处理后的gps数据<br>
+---------输出参数------------<br>
+sum_ah&nbsp;:&nbsp;本周期的累计行车时长</tt></dd></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#55aa55">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Data</strong></big></font></td></tr>
+    
+<tr><td bgcolor="#55aa55"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><strong>CONF_PATH</strong> = r'D:\Platform\platform\CONFIGURE\'</td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#7799ee">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Author</strong></big></font></td></tr>
+    
+<tr><td bgcolor="#7799ee"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%">wlm</td></tr></table>
+</body></html>

+ 80 - 0
函数说明/Log.html

@@ -0,0 +1,80 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module Log</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong>Log</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:d%3A%5Cplatform%5Cplatform%5Cbackend%5Clog.py">d:\platform\platform\backend\log.py</a></font></td></tr></table>
+    <p><tt>Log类</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+    
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="logging.html">logging</a><br>
+</td><td width="25%" valign=top><a href="os.html">os</a><br>
+</td><td width="25%" valign=top></td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+    
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="builtins.html#object">builtins.object</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="Log.html#Mylog">Mylog</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="Mylog">class <strong>Mylog</strong></a>(<a href="builtins.html#object">builtins.object</a>)</font></td></tr>
+    
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
+<td colspan=2><tt><a href="#Mylog">Mylog</a>(log_name='this_log',&nbsp;log_level='')<br>
+&nbsp;<br>
+<br>&nbsp;</tt></td></tr>
+<tr><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="Mylog-__init__"><strong>__init__</strong></a>(self, log_name='this_log', log_level='')</dt><dd><tt>Initialize&nbsp;self.&nbsp;&nbsp;See&nbsp;help(type(self))&nbsp;for&nbsp;accurate&nbsp;signature.</tt></dd></dl>
+
+<dl><dt><a name="Mylog-get_logger"><strong>get_logger</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="Mylog-set_file_hl"><strong>set_file_hl</strong></a>(self, file_name='all.log', log_level='info')</dt></dl>
+
+<dl><dt><a name="Mylog-set_stream_hl"><strong>set_stream_hl</strong></a>(self, log_level='info')</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#55aa55">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Data</strong></big></font></td></tr>
+    
+<tr><td bgcolor="#55aa55"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><strong>CONF_PATH</strong> = r'D:\Platform\platform\CONFIGURE\'</td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#7799ee">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Author</strong></big></font></td></tr>
+    
+<tr><td bgcolor="#7799ee"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%">wlm</td></tr></table>
+</body></html>

+ 86 - 0
函数说明/Tools.html

@@ -0,0 +1,86 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module Tools</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong>Tools</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:f%3A%5Cwork%5Cqx%5Cdata_analyze_platform%5Clib%5Cbackend%5Ctools.py">f:\work\qx\data_analyze_platform\lib\backend\tools.py</a></font></td></tr></table>
+    <p><tt>工具类</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+    
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="DBManager.html">DBManager</a><br>
+<a href="CONFIGURE.PathSetting.html">CONFIGURE.PathSetting</a><br>
+<a href="datetime.html">datetime</a><br>
+</td><td width="25%" valign=top><a href="math.html">math</a><br>
+<a href="numpy.html">numpy</a><br>
+<a href="os.html">os</a><br>
+</td><td width="25%" valign=top><a href="pandas.html">pandas</a><br>
+<a href="pdb.html">pdb</a><br>
+<a href="sys.html">sys</a><br>
+</td><td width="25%" valign=top><a href="warnings.html">warnings</a><br>
+</td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+    
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="builtins.html#object">builtins.object</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="Tools.html#Tools">Tools</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="Tools">class <strong>Tools</strong></a>(<a href="builtins.html#object">builtins.object</a>)</font></td></tr>
+    
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="Tools-__init__"><strong>__init__</strong></a>(self)</dt><dd><tt>Initialize&nbsp;self.&nbsp;&nbsp;See&nbsp;help(type(self))&nbsp;for&nbsp;accurate&nbsp;signature.</tt></dd></dl>
+
+<dl><dt><a name="Tools-cal_distance"><strong>cal_distance</strong></a>(self, latitude1, longitude1, latitude2, longitude2, radius=6371)</dt><dd><tt>输入两个地点的经纬度,输出两点间的距离</tt></dd></dl>
+
+<dl><dt><a name="Tools-data_download"><strong>data_download</strong></a>(self, write_path='', sn='', start_time='', end_time='', data_groups=['bms', 'gps'])</dt><dd><tt>数据下载函数<br>
+--------------输入参数------------<br>
+write_path:&nbsp;文件保存路径,不需要指定文件名<br>
+sn:&nbsp;str,&nbsp;电池sn号<br>
+start_time:&nbsp;str,&nbsp;开始时间<br>
+end_time:&nbsp;str,&nbsp;结束时间<br>
+gps_switch:&nbsp;True:获取gps数据;&nbsp;False:不获取gps数据<br>
+mode:&nbsp;0:正常取数;&nbsp;1:7255&nbsp;取数<br>
+&nbsp;<br>
+--------------输出参数------------<br>
+bms_data:&nbsp;获取到的bms数据<br>
+gps_data:&nbsp;获取到的gps数据</tt></dd></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#7799ee">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Author</strong></big></font></td></tr>
+    
+<tr><td bgcolor="#7799ee"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%">wlm</td></tr></table>
+</body></html>