measuring_window.py 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. import errno
  2. import threading
  3. import time
  4. import pandas as pd
  5. import wx
  6. from gui.config import *
  7. from gui.design_autogenerated import MeasuringDialog
  8. from modules.parsers.nbus_stream_parser import DataParser
  9. from nbus_api.nbus_module_slave import NBusSlaveModule
  10. from nbus_hal.nbus_serial.serial_config import NBusSerialConfig, NBusBaudrate, NBusParity
  11. from nbus_hal.nbus_serial.serial_port import NBusSerialPort
  12. from nbus_types.nbus_exceptions.nbus_network_exception import NBusErrorNetwork, NBusErrorNetworkType
  13. from serial import SerialException
  14. class MeasuringDialogFinal(MeasuringDialog):
  15. def __init__(self, parent):
  16. super().__init__(parent)
  17. self._df = pd.DataFrame()
  18. self._in_acquisition = False
  19. self._series_num = 0
  20. self._nbus_port = NBusSerialPort(NBusSerialConfig(**config))
  21. self._nbus_module = NBusSlaveModule(self._nbus_port, MODULE_ADDR, BRIDGE_ACQUIRE_WAIT)
  22. self._update_measurement_info(MeasuringPhase.IDLE.value)
  23. # start nbus logic after initialization
  24. wx.CallAfter(self._start_nbus)
  25. def GetDataFrame(self):
  26. return self._df
  27. def MainWindowOnClose(self, event):
  28. self._cleanup_and_close(save_data=False)
  29. def m_button_saveOnButtonClick(self, event):
  30. self._cleanup_and_close(save_data=True)
  31. def m_button_cancelOnButtonClick(self, event):
  32. self._cleanup_and_close(save_data=False)
  33. def _start_nbus(self):
  34. try:
  35. # download configuration from module
  36. self._nbus_module.init()
  37. # start data stream in listening mode
  38. self._nbus_module.start_streaming(send_start=False)
  39. # init loop variables
  40. last_phase = 0
  41. self._in_acquisition = True
  42. while self._in_acquisition:
  43. # 1. Spracujeme kliknutia na tlačidlá a prekreslenie UI
  44. wx.GetApp().Yield(onlyIfNeeded=True)
  45. if not self._in_acquisition:
  46. break
  47. # 2. Krátke čakanie
  48. time.sleep(TASK_NBUS_DELAY)
  49. # 3. Vyčítanie dát
  50. stream_chunk = self._nbus_module.fetch_stream_chunk()
  51. if not stream_chunk.empty:
  52. current_phase = int(stream_chunk[PHASE_SID].iloc[-1])
  53. if current_phase != last_phase:
  54. self._update_measurement_info(current_phase)
  55. last_phase = current_phase
  56. except NBusErrorNetwork as ex:
  57. if ex.args[0] in (NBusErrorNetworkType.DAMAGED_MESSAGE, NBusErrorNetworkType.MESSAGE_NOT_COMPLETE):
  58. self._show_error(
  59. "Ručný snímač nie je pripravený na meranie\n\n"
  60. "Prepnite ovládač do uzamknutého režimu a skúste to znova."
  61. )
  62. elif ex.args[0] == NBusErrorNetworkType.EMPTY_MESSAGE:
  63. self._show_error(
  64. "Ručný snímač nie je pripojený\n\n"
  65. "Skontrolujte či je zariadenie zapnuté a má nabitú batériu."
  66. )
  67. self._cleanup_and_close(save_data=False)
  68. except SerialException as ex:
  69. if ex.errno == errno.ENOENT or "FileNotFoundError" in str(ex):
  70. self._show_error(
  71. "Komunikačný port nebol nájdený\n\n"
  72. "Skontrolujte či je USB prijímač pripojený k PC a je zvolený správny komunikačný port."
  73. )
  74. elif ex.errno in (errno.EACCES, errno.EBUSY) or "PermissionError" in str(ex):
  75. self._show_error(
  76. "Komunikačný port je obsadený\n\n"
  77. "Zatvorte ostatné programy, ktoré port môžu používať, a skúste to znova."
  78. )
  79. else:
  80. self._show_error(
  81. "Chyba komunikácie so zariadením\n\n"
  82. "Skontrolujte pripojenie USB kábla a skúste akciu zopakovať."
  83. )
  84. self._cleanup_and_close(save_data=False)
  85. except Exception as ex:
  86. self._show_error(
  87. f"Nastala neočakávaná chyba pri meraní\n\n"
  88. f"Skontrolujte pripojenie zariadenia a skúste akciu zopakovať.\n"
  89. f"Detail chyby: {ex}"
  90. )
  91. self._cleanup_and_close(save_data=False)
  92. def _parse_data(self):
  93. if self._df is None or self._df.empty:
  94. self._show_error("nnnn")
  95. parser = DataParser(self._df)
  96. parser.remap_columns(NBUS_DATA_COLUMN_MAPPING)
  97. parser.remap_nans(NBUS_DATA_NAN_MAPPING)
  98. parser.validate_and_filter_series_by_zeros(CN_SER, CN_PHA, len(MeasuringPhase) - 1)
  99. parser.remove_specific_phases(CN_PHA, NBUS_DATA_PHASES_TO_REMOVE)
  100. parser.remap_phases(CN_PHA, NBUS_DATA_PHASE_MAPPING)
  101. parser.drop_rows_completely_null(NBUS_DATA_EMPTY_MAPPING)
  102. parser.clean_precision_noise(PRECISION)
  103. print("sasadassa", self._df)
  104. if self._df.empty:
  105. if self._df is None or self._df.empty:
  106. self._show_error("nnnn")
  107. self._df.to_csv("dataX.csv", index=False)
  108. def _update_measurement_info(self, new_phase):
  109. if new_phase not in MeasuringPhase:
  110. return
  111. if new_phase == MeasuringPhase.ACK.value:
  112. self._series_num += 1
  113. if new_phase == MeasuringPhase.IDLE.value:
  114. self.m_staticText_seriesVal.SetLabel(str(self._series_num))
  115. self.m_staticText_phaseVal.SetLabel(PHASES[new_phase])
  116. self.m_gauge_phase.SetValue(new_phase)
  117. def _show_error(self, message):
  118. wx.MessageBox(message, "Chyba", wx.OK | wx.ICON_ERROR)
  119. def _cleanup_and_close(self, save_data):
  120. # 1. Zastavíme slučku while
  121. self._in_acquisition = False
  122. # Zablokujeme okno, aby používateľ nemohol kliknúť znova
  123. self.Disable()
  124. def worker():
  125. try:
  126. # Pri force quit (save_data=False) sa neoplatí čakať na odpoveď zariadenia
  127. if save_data:
  128. self._nbus_module.stop_streaming(send_stop=False)
  129. time.sleep(0.2)
  130. self._df = self._nbus_module.fetch_full_stream()
  131. self._parse_data()
  132. else:
  133. self._df = None
  134. except Exception:
  135. self._df = None
  136. finally:
  137. try:
  138. # Ak port podporuje cancel_read / cancel_write, odblokuje to zamrznuté čítanie
  139. if hasattr(self._nbus_port, "cancel_read"):
  140. self._nbus_port.cancel_read()
  141. self._nbus_port.close()
  142. except Exception:
  143. pass
  144. # Bezpečné zatvorenie GUI okna z hlavného vlákna
  145. wx.CallAfter(self._finish_close)
  146. # Spustíme ako daemon vlákno, aby neblokovalo ukončenie programu
  147. threading.Thread(target=worker, daemon=True).start()
  148. def _finish_close(self):
  149. # Použi Destroy() namiesto Close(), aby sa znova nespustil EVT_CLOSE a nevznikla nekonečná slučka
  150. if self:
  151. self.Destroy()