cms_class_20241201.py 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758
  1. import numpy as np
  2. from scipy.signal import hilbert
  3. from scipy.fft import ifft
  4. import plotly.graph_objs as go
  5. import pandas as pd
  6. from sqlalchemy import create_engine, text
  7. import sqlalchemy
  8. import json
  9. import ast
  10. import math
  11. '''
  12. # 输入:
  13. {
  14. "ids":[12345,121212],
  15. "windCode":"xxxx",
  16. "analysisType":"xxxxx",
  17. "fmin":int(xxxx) (None),
  18. "fmax":"int(xxxx) (None),
  19. }
  20. [{id:xxxx,"time":xxx},{}]
  21. id[123456]
  22. # 通过id,读取mysql,获取数据
  23. engine = create_engine('mysql+pymysql://root:admin123456@192.168.50.235:30306/energy_data')
  24. def get_by_id(table_name,id):
  25. lastday_df_sql = f"SELECT * FROM {table_name} where id = {id} "
  26. # print(lastday_df_sql)
  27. df = pd.read_sql(lastday_df_sql, engine)
  28. return df
  29. select distinct id, timeStamp from table_name group by ids
  30. ids time
  31. 1 xxx
  32. 2 xxxx
  33. df_data = []
  34. # for id in ids:
  35. # sql_data = get_by_id('SKF001_wave',id)
  36. # df_data.append(sql_data)
  37. # print(sql_data)
  38. [df1,df2]
  39. '''
  40. '''
  41. 数据库字段:
  42. "samplingFrequency"
  43. "timeStamp"
  44. "mesureData"
  45. '''
  46. # %%
  47. # %%
  48. # 主要的类
  49. class CMSAnalyst:
  50. def __init__(self, fmin, fmax, table_name, ids):
  51. # envelope_spectrum_analysis
  52. # datas是[df1,df2,.....]
  53. #从数据库获取原始数据
  54. self.datas = self._get_by_id(table_name,ids)
  55. self.datas = [df[['mesure_data','time_stamp','sampling_frequency','wind_turbine_number','rotational_speed','mesure_point_name']] for df in self.datas]
  56. # 只输入一个id,返回一个[df],所以拿到self.data[0]
  57. self.data_filter = self.datas[0]
  58. # print(self.data_filter)
  59. # 取数据列
  60. self.data = np.array(ast.literal_eval(self.data_filter['mesure_data'][0]))
  61. self.envelope_spectrum_m = self.data.shape[0]
  62. self.envelope_spectrum_n = 1
  63. #设置分析参数
  64. self.fs = int(self.data_filter['sampling_frequency'].iloc[0])
  65. self.envelope_spectrum_t = np.arange(self.envelope_spectrum_m) / self.fs
  66. self.fmin = fmin if fmin is not None else 0
  67. self.fmax = fmax if fmax is not None else float('inf')
  68. self.envelope_spectrum_y = self._bandpass_filter(self.data)
  69. self.f, self.HP = self._calculate_envelope_spectrum(self.envelope_spectrum_y)
  70. #设备信息
  71. self.wind_code = self.data_filter['wind_turbine_number'].iloc[0]
  72. self.rpm_Gen = self.data_filter['rotational_speed'].iloc[0]
  73. self.mesure_point_name = self.data_filter['mesure_point_name'].iloc[0]
  74. self.fn_Gen = round(self.rpm_Gen/60,2)
  75. self.CF = self.Characteristic_Frequency()
  76. print(self.CF)
  77. self.CF = pd.DataFrame(self.CF,index=[0])
  78. print(self.CF)
  79. print(self.rpm_Gen)
  80. #if self.CF['type'].iloc[0] == 'bearing':
  81. n_rolls_m = self.CF['n_rolls'].iloc[0]
  82. d_rolls_m = self.CF['d_rolls'].iloc[0]
  83. D_diameter_m = self.CF['D_diameter'].iloc[0]
  84. theta_deg_m = self.CF['theta_deg'].iloc[0]
  85. print(n_rolls_m)
  86. print(d_rolls_m)
  87. print(D_diameter_m)
  88. print(theta_deg_m)
  89. self.bearing_frequencies = self.calculate_bearing_frequencies(n_rolls_m, d_rolls_m, D_diameter_m, theta_deg_m, self.rpm_Gen)
  90. print(self.bearing_frequencies)
  91. self.bearing_frequencies = pd.DataFrame(self.bearing_frequencies,index=[0])
  92. print(self.bearing_frequencies)
  93. # frequency_domain_analysis
  94. (
  95. self.frequency_domain_analysis_t,
  96. self.frequency_domain_analysis_f,
  97. self.frequency_domain_analysis_m,
  98. self.frequency_domain_analysis_mag,
  99. self.frequency_domain_analysis_Xrms,
  100. ) = self._calculate_spectrum(self.data)
  101. # time_domain_analysis
  102. self.time_domain_analysis_t = np.arange(self.data.shape[0]) / self.fs
  103. def _get_by_id(self, windcode, ids):
  104. df_res = []
  105. engine = create_engine('mysql+pymysql://root:admin123456@192.168.50.235:30306/energy_data_prod')
  106. # engine = create_engine('mysql+pymysql://root:admin123456@106.120.102.238:10336/energy_data_prod')
  107. for id in ids:
  108. table_name=windcode+'_wave'
  109. lastday_df_sql = f"SELECT * FROM {table_name} where id = {id} "
  110. # print(lastday_df_sql)
  111. df = pd.read_sql(lastday_df_sql, engine)
  112. df_res.append(df)
  113. return df_res
  114. # envelope_spectrum_analysis 包络谱分析
  115. def _bandpass_filter(self, data):
  116. """带通滤波"""
  117. m= data.shape[0]
  118. ni = round(self.fmin * self.envelope_spectrum_m / self.fs + 1)
  119. # na = round(self.fmax * self.envelope_spectrum_m / self.fs + 1)
  120. if self.fmax == float('inf'):
  121. na = m
  122. else:
  123. na = round(self.fmax * m / self.fs + 1)
  124. col = 1
  125. y = np.zeros((self.envelope_spectrum_m, col))
  126. # for p in range(col):
  127. # print(data.shape,p)
  128. z = np.fft.fft(data)
  129. a = np.zeros(self.envelope_spectrum_m, dtype=complex)
  130. a[ni:na] = z[ni:na]
  131. a[self.envelope_spectrum_m - na + 1 : self.envelope_spectrum_m - ni + 1] = z[
  132. self.envelope_spectrum_m - na + 1 : self.envelope_spectrum_m - ni + 1
  133. ]
  134. z = np.fft.ifft(a)
  135. y[:, 0] = np.real(z)
  136. return y
  137. def _calculate_envelope_spectrum(self, y):
  138. """计算包络谱"""
  139. m, n = y.shape
  140. HP = np.zeros((m, n))
  141. col = 1
  142. for p in range(col):
  143. H = np.abs(hilbert(y[:, p] - np.mean(y[:, p])))
  144. HP[:, p] = np.abs(np.fft.fft(H - np.mean(H))) * 2 / m
  145. f = np.fft.fftfreq(m, d=1 / self.fs)
  146. return f, HP
  147. def envelope_spectrum(self):
  148. """绘制包络谱"""
  149. # 只取正频率部分
  150. positive_frequencies = self.f[: self.envelope_spectrum_m // 2]
  151. positive_HP = self.HP[: self.envelope_spectrum_m // 2, 0]
  152. x = positive_frequencies
  153. y = positive_HP
  154. title = "包络谱"
  155. xaxis = "频率(Hz)"
  156. yaxis = "加速度(m/s^2)"
  157. Xrms = np.sqrt(np.mean(y**2)) # 加速度均方根值(有效值)
  158. rpm_Gen = round(self.rpm_Gen, 2)
  159. BPFI_1X = round(self.bearing_frequencies['BPFI'].iloc[0], 2)
  160. BPFO_1X = round(self.bearing_frequencies['BPFO'].iloc[0], 2)
  161. BSF_1X = round(self.bearing_frequencies['BSF'].iloc[0], 2)
  162. FTF_1X = round(self.bearing_frequencies['FTF'].iloc[0], 2)
  163. fn_Gen = round(self.fn_Gen, 2)
  164. _3P_1X = round(self.fn_Gen, 2) * 3
  165. # if self.CF['type'].iloc[0] == 'bearing':
  166. result = {
  167. "fs":self.fs,
  168. "Xrms":round(Xrms, 2),
  169. "x":list(x),
  170. "y":list(y),
  171. "title":title,
  172. "xaxis":xaxis,
  173. "yaxis":yaxis,
  174. "rpm_Gen": round(rpm_Gen, 2), # 转速r/min
  175. "BPFI": [{"Xaxis": BPFI_1X ,"val": "1BPFI"},{"Xaxis": BPFI_1X*2 ,"val": "2BPFI"},
  176. {"Xaxis": BPFI_1X*3, "val": "3BPFI"}, {"Xaxis": BPFI_1X*4, "val": "4BPFI"},
  177. {"Xaxis": BPFI_1X*5, "val": "5BPFI"}, {"Xaxis": BPFI_1X*6, "val": "6BPFI"}],
  178. "BPFO": [{"Xaxis": BPFO_1X ,"val": "1BPFO"},{"Xaxis": BPFO_1X*2 ,"val": "2BPFO"},
  179. {"Xaxis": BPFO_1X*3, "val": "3BPFO"}, {"Xaxis": BPFO_1X*4, "val": "4BPFO"},
  180. {"Xaxis": BPFO_1X*5, "val": "5BPFO"}, {"Xaxis": BPFO_1X*6, "val": "6BPFO"}],
  181. "BSF": [{"Xaxis": BSF_1X ,"val": "1BSF"},{"Xaxis": BSF_1X*2 ,"val": "2BSF"},
  182. {"Xaxis": BSF_1X*3, "val": "3BSF"}, {"Xaxis": BSF_1X*4, "val": "4BSF"},
  183. {"Xaxis": BSF_1X*5, "val": "5BSF"}, {"Xaxis": BSF_1X*6, "val": "6BSF"}],
  184. "FTF": [{"Xaxis": FTF_1X ,"val": "1FTF"},{"Xaxis": FTF_1X*2 ,"val": "2FTF"},
  185. {"Xaxis": FTF_1X*3, "val": "3FTF"}, {"Xaxis": FTF_1X*4, "val": "4FTF"},
  186. {"Xaxis": FTF_1X*5, "val": "5FTF"}, {"Xaxis": FTF_1X*6, "val": "6FTF"}],
  187. "fn_Gen":[{"Xaxis": fn_Gen ,"val": "1X"},{"Xaxis": fn_Gen*2 ,"val": "2X"},
  188. {"Xaxis": fn_Gen*3, "val": "3X"}, {"Xaxis": fn_Gen*4, "val": "4X"},
  189. {"Xaxis": fn_Gen*5, "val": "5X"}, {"Xaxis": fn_Gen*6, "val": "6X"}],
  190. "B3P":_3P_1X,
  191. }
  192. # result = json.dumps(result, ensure_ascii=False)
  193. reslut = self.replace_nan(reslut)
  194. return result
  195. # frequency_domain_analysis 频谱分析
  196. def _calculate_spectrum(self, data):
  197. """计算频谱"""
  198. m = data.shape[0]
  199. n = 1
  200. t = np.arange(m) / self.fs
  201. mag = np.zeros((m, n))
  202. Xrms = np.sqrt(np.mean(data**2)) # 加速度均方根值(有效值)
  203. # col=1
  204. # for p in range(col):
  205. mag = np.abs(np.fft.fft(data - np.mean(data))) * 2 / m
  206. f = np.fft.fftfreq(m, d=1 / self.fs)
  207. return t, f, m, mag, Xrms
  208. def frequency_domain(self):
  209. """绘制频域波形参数"""
  210. # 只取正频率部分
  211. positive_frequencies = self.frequency_domain_analysis_f[
  212. : self.frequency_domain_analysis_m // 2
  213. ]
  214. positive_mag = self.frequency_domain_analysis_mag[
  215. : self.frequency_domain_analysis_m // 2
  216. ]
  217. x = positive_frequencies
  218. y = positive_mag
  219. title = "频域信号"
  220. xaxis = "频率(Hz)"
  221. yaxis = "加速度(m/s^2)"
  222. Xrms = self.frequency_domain_analysis_Xrms
  223. rpm_Gen = round(self.rpm_Gen, 2)
  224. BPFI_1X = round(self.bearing_frequencies['BPFI'].iloc[0], 2)
  225. BPFO_1X = round(self.bearing_frequencies['BPFO'].iloc[0], 2)
  226. BSF_1X = round(self.bearing_frequencies['BSF'].iloc[0], 2)
  227. FTF_1X = round(self.bearing_frequencies['FTF'].iloc[0], 2)
  228. fn_Gen = round(self.fn_Gen, 2)
  229. _3P_1X = round(self.fn_Gen, 2) * 3
  230. # if self.CF['type'].iloc[0] == 'bearing':
  231. result = {
  232. "fs":self.fs,
  233. "Xrms":round(Xrms, 2),
  234. "x":list(x),
  235. "y":list(y),
  236. "title":title,
  237. "xaxis":xaxis,
  238. "yaxis":yaxis,
  239. "rpm_Gen": round(rpm_Gen, 2), # 转速r/min
  240. "BPFI": [{"Xaxis": BPFI_1X ,"val": "1BPFI"},{"Xaxis": BPFI_1X*2 ,"val": "2BPFI"},
  241. {"Xaxis": BPFI_1X*3, "val": "3BPFI"}, {"Xaxis": BPFI_1X*4, "val": "4BPFI"},
  242. {"Xaxis": BPFI_1X*5, "val": "5BPFI"}, {"Xaxis": BPFI_1X*6, "val": "6BPFI"}],
  243. "BPFO": [{"Xaxis": BPFO_1X ,"val": "1BPFO"},{"Xaxis": BPFO_1X*2 ,"val": "2BPFO"},
  244. {"Xaxis": BPFO_1X*3, "val": "3BPFO"}, {"Xaxis": BPFO_1X*4, "val": "4BPFO"},
  245. {"Xaxis": BPFO_1X*5, "val": "5BPFO"}, {"Xaxis": BPFO_1X*6, "val": "6BPFO"}],
  246. "BSF": [{"Xaxis": BSF_1X ,"val": "1BSF"},{"Xaxis": BSF_1X*2 ,"val": "2BSF"},
  247. {"Xaxis": BSF_1X*3, "val": "3BSF"}, {"Xaxis": BSF_1X*4, "val": "4BSF"},
  248. {"Xaxis": BSF_1X*5, "val": "5BSF"}, {"Xaxis": BSF_1X*6, "val": "6BSF"}],
  249. "FTF": [{"Xaxis": FTF_1X ,"val": "1FTF"},{"Xaxis": FTF_1X*2 ,"val": "2FTF"},
  250. {"Xaxis": FTF_1X*3, "val": "3FTF"}, {"Xaxis": FTF_1X*4, "val": "4FTF"},
  251. {"Xaxis": FTF_1X*5, "val": "5FTF"}, {"Xaxis": FTF_1X*6, "val": "6FTF"}],
  252. "fn_Gen":[{"Xaxis": fn_Gen ,"val": "1X"},{"Xaxis": fn_Gen*2 ,"val": "2X"},
  253. {"Xaxis": fn_Gen*3, "val": "3X"}, {"Xaxis": fn_Gen*4, "val": "4X"},
  254. {"Xaxis": fn_Gen*5, "val": "5X"}, {"Xaxis": fn_Gen*6, "val": "6X"}],
  255. "B3P":_3P_1X,
  256. }
  257. reslut = self.replace_nan(reslut)
  258. result = json.dumps(result, ensure_ascii=False)
  259. return result
  260. # time_domain_analysis 时域分析
  261. def time_domain(self):
  262. """绘制时域波形参数"""
  263. x = self.time_domain_analysis_t
  264. y = self.data
  265. rpm_Gen =self.rpm_Gen
  266. title = "时间域信号"
  267. xaxis = "时间(s)"
  268. yaxis = "加速度(m/s^2)"
  269. # 图片右侧统计量
  270. mean_value = np.mean(y)#平均值
  271. max_value = np.max(y)#最大值
  272. min_value = np.min(y)#最小值
  273. Xrms = np.sqrt(np.mean(y**2)) # 加速度均方根值(有效值)
  274. Xp = (max_value - min_value) / 2 # 峰值(单峰最大值) # 峰值
  275. Xpp=max_value-min_value#峰峰值
  276. Cf = Xp / Xrms # 峰值指标
  277. Sf = Xrms / mean_value # 波形指标
  278. If = Xp / np.mean(np.abs(y)) # 脉冲指标
  279. Xr = np.mean(np.sqrt(np.abs(y))) ** 2 # 方根幅值
  280. Ce = Xp / Xr # 裕度指标
  281. # 计算每个数据点的绝对值减去均值后的三次方,并求和
  282. sum_abs_diff_cubed_3 = np.mean((np.abs(y) - mean_value) ** 3)
  283. # 计算偏度指标
  284. Cw = sum_abs_diff_cubed_3 / (Xrms**3)
  285. # 计算每个数据点的绝对值减去均值后的四次方,并求和
  286. sum_abs_diff_cubed_4 = np.mean((np.abs(y) - mean_value) ** 4)
  287. # 计算峭度指标
  288. Cq = sum_abs_diff_cubed_4 / (Xrms**4)
  289. result = {
  290. "x":list(x),
  291. "y":list(y),
  292. "title":title,
  293. "xaxis":xaxis,
  294. "yaxis":yaxis,
  295. "fs":self.fs,
  296. "Xrms":round(Xrms, 2),#有效值
  297. "mean_value":round(mean_value, 2),# 均值
  298. "max_value":round(max_value, 2),# 最大值
  299. "min_value":round(min_value, 2), # 最小值
  300. "Xp":round(Xp, 2),# 峰值
  301. "Xpp":round(Xpp, 2),# 峰峰值
  302. "Cf":round(Cf, 2),# 峰值指标
  303. "Sf":round(Sf, 2),# 波形因子
  304. "If":round(If, 2),# 脉冲指标
  305. "Ce":round(Ce, 2),# 裕度指标
  306. "Cw":round(Cw, 2) ,# 偏度指标
  307. "Cq":round(Cq, 2) ,# 峭度指标
  308. "rpm_Gen": round(rpm_Gen, 2), # 转速r/min
  309. }
  310. reslut = self.replace_nan(reslut)
  311. result = json.dumps(result, ensure_ascii=False)
  312. return result
  313. # trend_analysis 趋势图
  314. def trend_analysis(self):
  315. all_stats = []
  316. # 定义积分函数
  317. def _integrate(data, dt):
  318. return np.cumsum(data) * dt
  319. # 定义计算统计指标的函数
  320. def _calculate_stats(data):
  321. mean_value = np.mean(data)
  322. max_value = np.max(data)
  323. min_value = np.min(data)
  324. Xrms = np.sqrt(np.mean(data**2)) # 加速度均方根值(有效值)
  325. # Xrms = filtered_acceleration_rms # 加速度均方根值(有效值)
  326. Xp = (max_value - min_value) / 2 # 峰值(单峰最大值) # 峰值
  327. Cf = Xp / Xrms # 峰值指标
  328. Sf = Xrms / mean_value # 波形指标
  329. If = Xp / np.mean(np.abs(data)) # 脉冲指标
  330. Xr = np.mean(np.sqrt(np.abs(data))) ** 2 # 方根幅值
  331. Ce = Xp / Xr # 裕度指标
  332. # 计算每个数据点的绝对值减去均值后的三次方,并求和
  333. sum_abs_diff_cubed_3 = np.mean((np.abs(data) - mean_value) ** 3)
  334. # 计算偏度指标
  335. Cw = sum_abs_diff_cubed_3 / (Xrms**3)
  336. # 计算每个数据点的绝对值减去均值后的四次方,并求和
  337. sum_abs_diff_cubed_4 = np.mean((np.abs(data) - mean_value) ** 4)
  338. # 计算峭度指标
  339. Cq = sum_abs_diff_cubed_4 / (Xrms**4)
  340. #
  341. return {
  342. "fs":self.fs,#采样频率
  343. "Mean": round(mean_value, 2),#平均值
  344. "Max": round(max_value, 2),#最大值
  345. "Min": round(min_value, 2),#最小值
  346. "Xrms": round(Xrms, 2),#有效值
  347. "Xp": round(Xp, 2),#峰值
  348. "If": round(If, 2), # 脉冲指标
  349. "Cf": round(Cf, 2),#峰值指标
  350. "Sf": round(Sf, 2),#波形指标
  351. "Ce": round(Ce, 2),#裕度指标
  352. "Cw": round(Cw, 2) ,#偏度指标
  353. "Cq": round(Cq, 2),#峭度指标
  354. #velocity_rms :速度有效值
  355. #time_stamp:时间戳
  356. }
  357. for data in self.datas:
  358. fs=int(self.data_filter['sampling_frequency'].iloc[0])
  359. dt = 1 / fs
  360. time_stamp=data['time_stamp'][0]
  361. print(time_stamp)
  362. data=np.array(ast.literal_eval(data['mesure_data'][0]))
  363. velocity = _integrate(data, dt)
  364. velocity_rms = np.sqrt(np.mean(velocity**2))
  365. stats = _calculate_stats(data)
  366. stats["velocity_rms"] = round(velocity_rms, 2)#速度有效值
  367. stats["time_stamp"] = str(time_stamp)#时间戳
  368. all_stats.append(stats)
  369. # df = pd.DataFrame(all_stats)
  370. all_stats = [self.replace_nan(stats) for stats in all_stats]
  371. all_stats = json.dumps(all_stats, ensure_ascii=False)
  372. return all_stats
  373. # def Characteristic_Frequency(self):
  374. # """提取轴承、齿轮等参数"""
  375. # # 1、从测点名称中提取部件名称(计算特征频率的部件)
  376. # str1 = self.mesure_point_name
  377. # # str2 = ["main_bearing", "front_main_bearing", "rear_main_bearing", "generator_non_drive_end"]
  378. # str2 = ["main_bearing", "front_main_bearing", "rear_main_bearing", "generator","stator","gearbox"]
  379. # for str in str2:
  380. # if str in str1:
  381. # parts = str
  382. # if parts == "front_main_bearing":
  383. # parts = "front_bearing"
  384. # elif parts == "rear_main_bearing":
  385. # parts = "rear_bearing"
  386. # print(parts)
  387. def Characteristic_Frequency(self):
  388. """提取轴承、齿轮等参数"""
  389. # 1、从测点名称中提取部件名称(计算特征频率的部件)
  390. str1 = self.mesure_point_name
  391. # str2 = ["main_bearing", "front_main_bearing", "rear_main_bearing", "generator_non_drive_end"]
  392. # str2 = ["main_bearing", "front_main_bearing", "rear_main_bearing", "generator","stator","gearbox"]
  393. # for str in str2:
  394. # if str in str1:
  395. # parts = str
  396. # # if parts == "front_main_bearing":
  397. # # parts = "front_bearing"
  398. # # elif parts == "rear_main_bearing":
  399. # # parts = "rear_bearing"
  400. print(str1)
  401. # 2、连接233的数据库'energy_show',从表'wind_engine_group'查找风机编号'engine_code'对应的机型编号'mill_type_code'
  402. engine_code = self.wind_code
  403. print(engine_code)
  404. Engine = create_engine('mysql+pymysql://admin:admin123456@192.168.50.233:3306/energy_show')
  405. #Engine2 = create_engine('mysql+pymysql://admin:admin123456@106.120.102.238:16306/energy_show')
  406. # df_sql2 = f"SELECT * FROM {'wind_engine_group'} where engine_code = {'engine_code'} "
  407. df_sql2 = f"SELECT * FROM wind_engine_group WHERE engine_code = '{engine_code}'"
  408. df2 = pd.read_sql(df_sql2, Engine)
  409. mill_type_code = df2['mill_type_code'].iloc[0]
  410. print(mill_type_code)
  411. # # 3、从表'unit_bearings'中通过机型编号'mill_type_code'查找部件'brand'、'model'的参数信息
  412. # Engine3 = create_engine('mysql+pymysql://admin:admin123456@106.120.102.238:16306/energy_show')
  413. # #unit_bearings是主轴承的参数
  414. # df_sql3 = f"SELECT * FROM {'unit_bearings'} where mill_type_code = {'mill_type_code'} "
  415. # df3 = pd.read_sql(df_sql3, Engine3)
  416. # brand = 'front_bearing' + '_brand' # parts代替'front_bearing'
  417. # model = 'front_bearing' + '_model' # parts代替'front_bearing'
  418. # print(brand)
  419. # _brand = df3[brand].iloc[0]
  420. # _model = df3[model].iloc[0]
  421. # print(_brand)
  422. # print(_model)
  423. # 3、从相关的表中通过机型编号'mill_type_code'或者齿轮箱编号gearbox_code查找部件'brand'、'model'的参数信息
  424. # Engine3 = create_engine('mysql+pymysql://admin:admin123456@106.120.102.238:16306/energy_show')
  425. #unit_bearings主轴承参数表 关键词"main_bearing"
  426. if 'main_bearing' in str1:
  427. print("main_bearing")
  428. # df_sql3 = f"SELECT * FROM {'unit_bearings'} where mill_type_code = {'mill_type_code'} "
  429. df_sql3 = f"SELECT * FROM unit_bearings WHERE mill_type_code = '{mill_type_code}' "
  430. df3 = pd.read_sql(df_sql3, Engine)
  431. if df3.empty:
  432. print("警告: 没有找到有效的机型信息")
  433. if 'front' in str1:
  434. brand = 'front_bearing' + '_brand'
  435. model = 'front_bearing' + '_model'
  436. front_has_value = not pd.isna(df3[brand].iloc[0]) and not pd.isna(df3[model].iloc[0])
  437. if not front_has_value:
  438. print("警告: 没有找到有效的品牌信息")
  439. elif 'rear' in str1:
  440. brand = 'rear_bearing' + '_brand'
  441. model = 'rear_bearing' + '_model'
  442. end_has_value = not pd.isna(df3[brand].iloc[0]) and not pd.isna(df3[model].iloc[0])
  443. if not end_has_value:
  444. print("警告: 没有找到有效的品牌信息")
  445. else:
  446. # 当没有指定 front 或 end 时,自动选择有值的轴承信息
  447. front_brand_col = 'front_bearing_brand'
  448. front_model_col = 'front_bearing_model'
  449. rear_brand_col = 'rear_bearing_brand'
  450. rear_model_col = 'rear_bearing_model'
  451. # 检查 front_bearing 是否有值
  452. front_has_value = not pd.isna(df3[front_brand_col].iloc[0]) and not pd.isna(df3[front_model_col].iloc[0])
  453. # 检查 end_bearing 是否有值
  454. end_has_value = not pd.isna(df3[rear_brand_col].iloc[0]) and not pd.isna(df3[rear_model_col].iloc[0])
  455. # 根据检查结果选择合适的列
  456. if front_has_value and end_has_value:
  457. # 如果两者都有值,默认选择 front
  458. brand = front_brand_col
  459. model = front_model_col
  460. elif front_has_value:
  461. brand = front_brand_col
  462. model = front_model_col
  463. elif end_has_value:
  464. brand = rear_brand_col
  465. model = rear_model_col
  466. else:
  467. # 如果两者都没有有效值,设置默认值或抛出异常
  468. print("警告: 没有找到有效的轴承信息")
  469. brand = front_brand_col # 默认使用 front
  470. model = front_model_col # 默认使用 front
  471. print(brand)
  472. _brand = df3[brand].iloc[0]
  473. _model = df3[model].iloc[0]
  474. print(_brand)
  475. print(_model)
  476. #unit_dynamo 发电机参数表 关键词generator stator
  477. elif 'generator'in str1 or 'stator' in str1:
  478. print("generator or 'stator'")
  479. # df_sql3 = f"SELECT * FROM {'unit_dynamo'} where mill_type_code = {'mill_type_code'} "
  480. df_sql3 = f"SELECT * FROM unit_dynamo WHERE mill_type_code = '{mill_type_code}' "
  481. df3 = pd.read_sql(df_sql3, Engine)
  482. if 'non' in str1:
  483. brand = 'non_drive_end_bearing' + '_brand'
  484. model = 'non_drive_end_bearing' + '_model'
  485. else:
  486. brand = 'drive_end_bearing' + '_brand'
  487. model = 'drive_end_bearing' + '_model'
  488. print(brand)
  489. _brand = df3[brand].iloc[0]
  490. _model = df3[model].iloc[0]
  491. print(_brand)
  492. print(_model)
  493. #齿轮箱区分行星轮/平行轮 和 轴承两个表
  494. elif 'gearbox' in str1:
  495. print("gearbox")
  496. #根据mill_type_code从unit_gearbox表中获得gearbox_code
  497. df_sql3 = f"SELECT * FROM unit_gearbox WHERE mill_type_code = '{mill_type_code}' "
  498. df3 = pd.read_sql(df_sql3, Engine)
  499. gearbox_code =df3['code'].iloc[0]
  500. print(gearbox_code)
  501. #Engine33 = create_engine('mysql+pymysql://admin:admin123456@106.120.102.238:16306/energy_show')
  502. #如果是行星轮/平行轮 则从unit_gearbox_structure 表中取数据
  503. if 'planet'in str1 or 'sun' in str1:
  504. print("'planet' or 'sun' ")
  505. gearbox_structure =1 if 'planet'in str1 else 2
  506. planetary_gear_grade =1
  507. if 'first' in str1:
  508. planetary_gear_grade =1
  509. elif 'second'in str1:
  510. planetary_gear_grade =2
  511. elif 'third'in str1:
  512. planetary_gear_grade =3
  513. # df_sql33 = f"SELECT * FROM unit_gearbox_structure WHERE gearbox_code = '{gearbox_code}' "
  514. df_sql33 = f"""
  515. SELECT bearing_brand, bearing_model
  516. FROM unit_gearbox_structure
  517. WHERE gearbox_code = '{gearbox_code}'
  518. AND gearbox_structure = '{gearbox_structure}'
  519. AND planetary_gear_grade = '{planetary_gear_grade}'
  520. """
  521. df33 = pd.read_sql(df_sql33, Engine)
  522. if df33.empty:
  523. print("unit_gearbox_structure没有该测点的参数")
  524. else:
  525. brand = 'bearing' + '_brand'
  526. model = 'bearing' + '_model'
  527. print(brand)
  528. _brand = df33[brand].iloc[0]
  529. _model = df33[model].iloc[0]
  530. has_value = not pd.isna(df33[brand].iloc[0]) and not pd.isna(df33[model].iloc[0])
  531. if has_value:
  532. print(_brand)
  533. print(_model)
  534. else:
  535. print("警告: 没有找到有效的轴承信息")
  536. #如果是齿轮箱轴承 则从unit_gearbox_bearings 表中取数据
  537. elif 'shaft' in str1 or'input' in str1:
  538. print("'shaft'or'input'")
  539. # df_sql33 = f"SELECT * FROM unit_gearbox_bearings WHERE gearbox_code = '{gearbox_code}' "
  540. # df33 = pd.read_sql(df_sql33, Engine33)
  541. #高速轴 低速中间轴 取bearing_rs/gs均可
  542. parallel_wheel_grade=1
  543. if 'low_speed' in str1:
  544. parallel_wheel_grade =1
  545. elif 'low_speed_intermediate' in str1:
  546. parallel_wheel_grade =2
  547. elif 'high_speed' in str1:
  548. parallel_wheel_grade =3
  549. # df_sql33 = f"SELECT * FROM unit_gearbox_bearings WHERE gearbox_code = '{gearbox_code}' "
  550. df_sql33 = f"""
  551. SELECT bearing_rs_brand, bearing_rs_model, bearing_gs_brand, bearing_gs_model
  552. FROM unit_gearbox_bearings
  553. WHERE gearbox_code = '{gearbox_code}'
  554. AND parallel_wheel_grade = '{parallel_wheel_grade}'
  555. """
  556. df33 = pd.read_sql(df_sql33, Engine)
  557. if not df33.empty:
  558. if 'high_speed' in str1 or 'low_speed_intermediate' in str1:
  559. rs_brand = 'bearing_rs' + '_brand'
  560. rs_model = 'bearing_rs' + '_model'
  561. gs_brand = 'bearing_gs' + '_brand'
  562. gs_model = 'bearing_gs' + '_model'
  563. rs_has_value = not pd.isna(df33[rs_brand].iloc[0]) and not pd.isna(df33[rs_model].iloc[0])
  564. gs_has_value = not pd.isna(df33[gs_brand].iloc[0]) and not pd.isna(df33[gs_model].iloc[0])
  565. if rs_has_value and gs_has_value:
  566. brand = rs_brand
  567. model = rs_model
  568. elif rs_has_value:
  569. brand = rs_brand
  570. model = rs_model
  571. elif gs_has_value:
  572. brand = gs_brand
  573. model = gs_model
  574. else:
  575. print("警告: 没有找到有效的品牌信息")
  576. brand = rs_brand
  577. model = rs_model
  578. #低速轴 取bearing_model
  579. elif 'low_speed'in str1:
  580. brand = 'bearing' + '_brand'
  581. model = 'bearing' + '_model'
  582. else:
  583. print("警告: 没有找到有效的轴承信息")
  584. print(brand)
  585. _brand = df33[brand].iloc[0]
  586. _model = df33[model].iloc[0]
  587. print(_brand)
  588. print(_model)
  589. # # 4、从表'unit_dict_brand_model'中通过'_brand'、'_model'查找部件的参数信息
  590. # Engine4 = create_engine('mysql+pymysql://admin:admin123456@106.120.102.238:16306/energy_show')
  591. # df_sql4 = f"SELECT * FROM unit_dict_brand_model where manufacture = %s AND model_number = %s"
  592. # params = [(_brand, _model)]
  593. # df4 = pd.read_sql(df_sql4, Engine4, params=params)
  594. # if 'bearing' in parts:
  595. # n_rolls = df4['rolls_number'].iloc[0]
  596. # d_rolls = df4['rolls_diameter'].iloc[0]
  597. # D_diameter = df4['circle_diameter'].iloc[0]
  598. # theta_deg = df4['theta_deg'].iloc[0]
  599. # result = {
  600. # "type":'bearing',
  601. # "n_rolls":round(n_rolls, 2),
  602. # "d_rolls":round(d_rolls, 2),
  603. # "D_diameter":round(D_diameter, 2),
  604. # "theta_deg":round(theta_deg, 2),
  605. # }
  606. # # result = json.dumps(result, ensure_ascii=False)
  607. # return result
  608. # 4、从表'unit_dict_brand_model'中通过'_brand'、'_model'查找部件的参数信息
  609. df_sql4 = f"SELECT * FROM unit_dict_brand_model where manufacture = %s AND model_number = %s"
  610. params = [(_brand, _model)]
  611. df4 = pd.read_sql(df_sql4, Engine, params=params)
  612. n_rolls = df4['rolls_number'].iloc[0]
  613. d_rolls = df4['rolls_diameter'].iloc[0]
  614. D_diameter = df4['circle_diameter'].iloc[0]
  615. theta_deg = df4['theta_deg'].iloc[0]
  616. result = {
  617. "type":'bearing',
  618. "n_rolls":round(n_rolls, 2),
  619. "d_rolls":round(d_rolls, 2),
  620. "D_diameter":round(D_diameter, 2),
  621. "theta_deg":round(theta_deg, 2),
  622. }
  623. # result = json.dumps(result, ensure_ascii=False)
  624. return result
  625. def calculate_bearing_frequencies(self, n, d, D, theta_deg, rpm):
  626. """
  627. 计算轴承各部件特征频率
  628. 参数:
  629. n (int): 滚动体数量
  630. d (float): 滚动体直径(单位:mm)
  631. D (float): 轴承节圆直径(滚动体中心圆直径,单位:mm)
  632. theta_deg (float): 接触角(单位:度)
  633. rpm (float): 转速(转/分钟)
  634. 返回:
  635. dict: 包含各特征频率的字典(单位:Hz)
  636. """
  637. # 转换角度为弧度
  638. theta = math.radians(theta_deg)
  639. # 转换直径单位为米(保持单位一致性,实际计算中比值抵消单位影响)
  640. # 注意:由于公式中使用的是比值,单位可以保持mm不需要转换
  641. ratio = d / D
  642. # 基础频率计算(转/秒)
  643. f_r = rpm / 60.0
  644. # 计算各特征频率
  645. BPFI = n / 2 * (1 + ratio * math.cos(theta)) * f_r # 内圈故障频率
  646. BPFO = n / 2 * (1 - ratio * math.cos(theta)) * f_r # 外圈故障频率
  647. BSF = (D / (2 * d)) * (1 - (ratio ** 2) * (math.cos(theta) ** 2)) * f_r # 滚动体故障频率
  648. FTF = 0.5 * (1 - ratio * math.cos(theta)) * f_r # 保持架故障频率
  649. return {
  650. "BPFI": round(BPFI, 2),
  651. "BPFO": round(BPFO, 2),
  652. "BSF": round(BSF, 2),
  653. "FTF": round(FTF, 2),
  654. }
  655. #检查返回结果是否有nan 若有,则替换成none
  656. def replace_nan(self, obj):
  657. if isinstance(obj, dict):
  658. return {k: self.replace_nan(v) for k, v in obj.items()}
  659. elif isinstance(obj, list):
  660. return [self.replace_nan(item) for item in obj]
  661. elif isinstance(obj, float) and math.isnan(obj):
  662. return None
  663. return obj
  664. if __name__ == "__main__":
  665. # table_name = "SKF001_wave"
  666. # ids = [67803,67804]
  667. # fmin, fmax = None, None
  668. cms = CMSAnalyst(fmin, fmax,table_name,ids)
  669. time_domain = cms.time_domain()
  670. # print(time_domain)
  671. '''
  672. trace = go.Scatter(
  673. x=time_domain['x'],
  674. y=time_domain['y'],
  675. mode="lines",
  676. name=time_domain['title'],
  677. )
  678. layout = go.Layout(
  679. title= time_domain['title'],
  680. xaxis=dict(title=time_domain["xaxis"]),
  681. yaxis=dict(title=time_domain["yaxis"]),
  682. )
  683. fig = go.Figure(data=[trace], layout=layout)
  684. fig.show()
  685. '''
  686. # data_path_lsit = ["test1.csv", "test2.csv"]
  687. # trend_analysis_test = cms.trend_analysis(data_path_lsit, fmin, fmax)
  688. # print(trend_analysis_test)