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