Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions PRINT.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,10 +131,13 @@

# create logfile and get path
logpath = fu.create_logfile()
pmp_log_name = f"pmp_data_{logpath.stem}.csv"
pmp_save_path = Path(logpath).parent / pmp_log_name
with open(pmp_save_path, 'x') as f:
f.write('time,pmp,freq,volt,amps,torq\n')
data_log_name = f"PRINT_data_{logpath.stem}.csv"
datalog_save_path = Path(logpath).parent / data_log_name
with open(datalog_save_path, 'x') as f:
f.write(
f"time,ID,X,Y,Z,XR,YR,ZR,TCP,freq_P1,volt_P1,amps_P1,torq_P1,freq_P2,"
f"volt_P2,amps_P2,torq_P2,mix_freq,temp_IN,temp_OUT\n"
)

print(f"writing log at: {logpath}")
print(f"connecting: ", end='')
Expand All @@ -148,7 +151,7 @@
app = 0
win = 0
app = QApplication(sys.argv)
win = Mainframe(logpath, dev_avail, pmp_save_path)
win = Mainframe(logpath, dev_avail, datalog_save_path)
win.show()
app.exec()
# sys.exit(app.exec())
Expand Down
6 changes: 5 additions & 1 deletion libs/data_utilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -1610,6 +1610,7 @@ class TCPSocket (yaml.YAMLObject):
close TCP/IP connection
"""
yaml_tag = u'!TCPSocket'
connected = False

def __init__(
self,
Expand Down Expand Up @@ -1692,6 +1693,9 @@ def connect(self) -> tuple[str, int] | Exception:
not possible
"""

if self.connected:
return

try:
server_address = (self.ip, int(self.port))
except ValueError:
Expand All @@ -1705,7 +1709,7 @@ def connect(self) -> tuple[str, int] | Exception:
self._Socket.settimeout(self.rw_tout)

except Exception as err:
self.connected = 0
self.connected = False
return err

return server_address
Expand Down
5 changes: 3 additions & 2 deletions libs/global_var.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@
'msp': { # Main Supply Pump
'ip': '192.168.178.36:17',
'err': False,
'temp': True,
'temp': False,
'pressure': False,
},
'imp': { # Inline Mixing Pump
Expand All @@ -194,8 +194,9 @@
'amps': False
},
'phc': { # Print Head Controller
'ip': '',
'ip': '192.168.178.58:17',
'err': False,
'temp': True,
'aircon': False,
'fdist': False,
'edist': False
Expand Down
101 changes: 64 additions & 37 deletions libs/threads.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

# python standard libraries
import os
import re
import cv2
import sys
import math as m
Expand All @@ -30,7 +31,7 @@
import libs.data_utilities as du
import libs.func_utilities as fu
import libs.pump_utilities as pu
from libs.win_mainframe_prearrange import GlobalMutex, PmpMutex
from libs.win_mainframe_prearrange import GlobalMutex, PmpMutex, PrhMutex



Expand Down Expand Up @@ -105,12 +106,11 @@ def send(self) -> None:
serial.keepAlive()
if pinch is not None and g.PRH_connected:
try:
ans = requests.post(f"{g.PRH_url}/pinch", data={'s': str(float(pinch))}, timeout=0.1)
print(ans.text)
except requests.Timeout as e:
requests.post(f"{g.PRH_url}/pinch", data={'s': str(float(pinch))}, timeout=1)
except:
log_txt = f"post to pinch valve failed! {g.PRH_url} not present!"
self.logEntry.emit('CONN', log_txt)
print(log_txt)
# print(log_txt)

# SEND TO MIXER
if g.PRH_connected and g.MIX_last_speed != g.MIX_speed:
Expand Down Expand Up @@ -492,42 +492,69 @@ def loc_request(loc:dict, key:str) -> None:
fu.store_sensor_data while its at it
"""

for sub_key in loc:
if sub_key == 'ip' or sub_key == 'err':
continue
# for sub_key in loc:
# if sub_key == 'ip' or sub_key == 'err':
# continue

if loc[sub_key]: # only check true-marked sensors
data = fu.sensor_req(loc["ip"], sub_key)
# if loc[sub_key]: # only check true-marked sensors
# data = fu.sensor_req(loc["ip"], sub_key)

if isinstance(data, list):
# to-do: write handling for legacy data
self.dataReceived.emit(loc['ip'])
# extract tuple from list: (val, uptime)
# newest entry is at the end of the list
latest_data = data[len(data) - 1]
loc['err'] = False

with QMutexLocker(GlobalMutex):
g.DBDataBlock.store(latest_data, key, sub_key)

elif data is not None:
# log recurring error from one location only once
if loc['err'] == False:
loc['err'] = True
self.logEntry.emit(
'SENS',
f"request error from {loc['ip']}: {data}"
)
self.logEntry.emit(
'SENS',
f"trying to reconnect to {loc['ip']}.."
)
# if isinstance(data, list):
# # to-do: write handling for legacy data
# self.dataReceived.emit(loc['ip'])
# # extract tuple from list: (val, uptime)
# # newest entry is at the end of the list
# latest_data = data[len(data) - 1]
# loc['err'] = False

# with QMutexLocker(GlobalMutex):
# g.DBDataBlock.store(latest_data, key, sub_key)

# elif data is not None:
# # log recurring error from one location only once
# if loc['err'] == False:
# loc['err'] = True
# self.logEntry.emit(
# 'SENS',
# f"request error from {loc['ip']}: {data}"
# )
# self.logEntry.emit(
# 'SENS',
# f"trying to reconnect to {loc['ip']}.."
# )

return None
# return None

# # main cycle
# for key in g.SEN_dict:
# loc_request(g.SEN_dict[key], key)

# overwrite for simplicity
try:
ans = requests.get(f"{g.PRH_url}/data", timeout=g.SEN_timeout)
ans.raise_for_status()
except:
# print(f"request failed: {err}!")
return

# main cycle
for key in g.SEN_dict:
loc_request(g.SEN_dict[key], key)
ans_str = ans.text
if 'no data available' in ans_str:
return None

data_loss_str, entry_str = ans_str.split('&')
if data_loss_str.find('true') != -1:
data_loss = True
else:
data_loss = False
entries = entry_str.split(';')
# use last entry
temps = re.findall('>(\d+\.\d+)', entries[-2])
try:
g.DBDataBlock.amb_temp = float(temps[0])
g.DBDataBlock.imp_temp = float(temps[1])
except:
pass
# print(f"New TEMP -- IN: {temps[0]} -- OUT: {temps[1]} ({entries} // {data_loss})")

self.cycleDone.emit()

Expand Down
37 changes: 25 additions & 12 deletions libs/win_daq.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,12 @@ class DAQWindow(QWidget, Ui_DAQWindow):
_db_active = True
_db_bucket = None
_influx_error = False
_log_to_file = ''


def __init__(self, parent=None) -> None:
def __init__(self, log_to_file:str, parent=None) -> None:
super().__init__(parent)
self._log_to_file = log_to_file

# UI setup
self.setupUi(self)
Expand All @@ -60,10 +62,9 @@ def __init__(self, parent=None) -> None:
)

# timer setup
self.time_update()
self._ClockTimer = QTimer()
self._ClockTimer.setInterval(1000)
self._ClockTimer.timeout.connect(self.time_update)
self._ClockTimer.setInterval(500)
self._ClockTimer.timeout.connect(self.data_update)
self._ClockTimer.start()

self._DBTimer = QTimer()
Expand Down Expand Up @@ -93,16 +94,12 @@ def __init__(self, parent=None) -> None:
self.PATH_disp_path.setText(g.DB_url)


def time_update(self) -> None:
"""clock update, signal from mainframe"""
def data_update(self) -> None:
"""data label update, signal from robo_recv"""

self.PATH_disp_datetime.setText(
f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"
)

def data_update(self) -> None:
"""data label update, signal from robo_recv"""

self.BASIC_disp_ambTemp.setText(f"{g.DBDataBlock.amb_temp} °C")
self.BASIC_disp_ambHum.setText(f"{g.DBDataBlock.amb_humidity} rH")
self.BASIC_disp_delivPumpTemp.setText(
Expand Down Expand Up @@ -208,6 +205,22 @@ def to_influx_db(self) -> None:
signal from (robo_recv or sensor_cycle?)
"""

# log to file
if self._log_to_file != '':
with open(self._log_to_file, 'a') as log:
Curr = g.DBDataBlock
Pos = Curr.Robo.Coor
Pmp1 = Curr.Pump1
Pmp2 = Curr.Pump2
log.write(
f"{datetime.now().strftime('%Y-%m-%d_%H%M%S')},"
f"{Curr.Robo.id},{Pos.x},{Pos.y},{Pos.z},"
f"{Pos.rx},{Pos.ry},{Pos.rz},{Curr.Robo.t_speed},"
f"{Pmp1.freq},{Pmp1.volt},{Pmp1.amps},{Pmp1.torq},"
f"{Pmp2.freq},{Pmp2.volt},{Pmp2.amps},{Pmp2.torq},"
f"{Curr.imp_freq},{Curr.amb_temp},{Curr.imp_temp}\n"
)

# upload to TCP Influx server
now = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
DBEntry = influxdb_client\
Expand Down Expand Up @@ -280,7 +293,7 @@ def closeEvent(self, event) -> None:

######################## DAQ WIN DIALOG ############################

def daq_window(standalone=False) -> 'DAQWindow':
def daq_window(standalone=False, log_to_file='') -> 'DAQWindow':
"""shows a dialog window, text and title can be set, returns the users
choice
"""
Expand All @@ -291,7 +304,7 @@ def daq_window(standalone=False) -> 'DAQWindow':
daq_app = 0
daq_app = QApplication(sys.argv)

daq_win = DAQWindow()
daq_win = DAQWindow(log_to_file)

if standalone:
daq_win.show()
Expand Down
2 changes: 1 addition & 1 deletion libs/win_mainframe.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@

# import PyQT UIs (converted from .ui to .py using Qt-Designer und pyuic5)
from libs.win_mainframe_prearrange import PreMainframe, Watchdog
from libs.win_mainframe_prearrange import GlobalMutex, PmpMutex
from libs.win_mainframe_prearrange import GlobalMutex, PmpMutex, PrhMutex


# import my own libs
Expand Down
29 changes: 19 additions & 10 deletions libs/win_mainframe_prearrange.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,10 @@ class PreMainframe(QMainWindow, Ui_MainWindow):
# SETUP #
#########################################################################

def __init__(self, lpath, testrun=False, p_log='', parent=None) -> None:
def __init__(self, lpath, testrun=False, log_to_file='', parent=None) -> None:

super().__init__(parent)
self._testrun = testrun
self._p_log = p_log

# UI SETUP
self.setupUi(self)
Expand Down Expand Up @@ -128,7 +127,7 @@ def __init__(self, lpath, testrun=False, p_log='', parent=None) -> None:
self.log_entry('GNRL', 'main GUI running.')

# SIDE WINDOW SETUP
self.Daq = daq_window()
self.Daq = daq_window(log_to_file=log_to_file)
self.CamCap = cam_cap_window()
for side_win in [self.Daq, self.CamCap]:
side_win.logEntry.connect(self.log_entry)
Expand Down Expand Up @@ -597,12 +596,6 @@ def p_recv(display:list, stt_data:du.PumpTelemetry, dump:str) -> None:
display[2].setText(f"{stt_data.amps} A")
display[3].setText(f"{stt_data.torq} Nm")
setattr(self, dump, telem)
if self._p_log != '':
with open(self._p_log, 'a') as p_log:
p_log.write(
f"{datetime.now().strftime('%Y-%m-%d_%H%M%S')},{source},"
f"{telem.freq},{telem.volt},{telem.amps},{telem.torq}\n"
)

match source:
case 'P1':
Expand Down Expand Up @@ -634,6 +627,7 @@ def prh_send(self, mixer_speed:float) -> None:

self.CONN_PRH_disp_writeBuffer.setText(str(mixer_speed))
self.CONN_PRH_disp_bytesWritten.setText("length of float")
g.DBDataBlock.imp_freq = g.MIX_last_speed
self.log_entry('PRTH', f"speed set to {mixer_speed}")


Expand Down Expand Up @@ -924,7 +918,7 @@ def pinch_valve_toggle(self, internal=False, val=0.0) -> None:
pinch_state = val
try:
requests.post(f"{g.PRH_url}/pinch", data={'s': pinch_state}, timeout=1)
except requests.Timeout as e:
except:
log_txt = f"post to pinch valve failed! {g.PRH_url} not present!"
self.log_entry('CONN', log_txt)
print(log_txt)
Expand Down Expand Up @@ -1016,6 +1010,20 @@ def set_range(self, source='') -> None:
self.CHKR_disp_ry.setText(f"{new_min.ry}/{new_max.ry}")
self.CHKR_disp_rz.setText(f"{new_min.rz}/{new_max.rz}")
self.CHKR_disp_ext.setText(f"{new_min.ext}/{new_max.ext}")
self.CHKR_float_x_min.setValue(new_min.x)
self.CHKR_float_y_min.setValue(new_min.y)
self.CHKR_float_z_min.setValue(new_min.z)
self.CHKR_float_rx_min.setValue(new_min.rx)
self.CHKR_float_ry_min.setValue(new_min.ry)
self.CHKR_float_rz_min.setValue(new_min.rz)
self.CHKR_float_ext_min.setValue(new_min.ext)
self.CHKR_float_x_max.setValue(new_max.x)
self.CHKR_float_y_max.setValue(new_max.y)
self.CHKR_float_z_max.setValue(new_max.z)
self.CHKR_float_rx_max.setValue(new_max.rx)
self.CHKR_float_ry_max.setValue(new_max.ry)
self.CHKR_float_rz_max.setValue(new_max.rz)
self.CHKR_float_ext_max.setValue(new_max.ext)


def set_zero(self, axis:list, source='') -> None:
Expand Down Expand Up @@ -1191,6 +1199,7 @@ def token(self):
# used to manage global data exchange of modbus shutdown
GlobalMutex = QMutex()
PmpMutex = QMutex()
PrhMutex = QMutex()

# only do the following if run as main program
if __name__ == "__main__":
Expand Down
Loading