Add a GUI text entry to set the ambient temperature live
New lineEdit_ambient next to the host/connect row - type a value and
press Enter to send {"System": {"AmbientTemp": ...}}. The server now
has a recv handler for the System channel (previously send-only):
updates the real Pot's ambient temperature and, where the controller
has an internal model (Smith), its model Pots too (new
set_ambient_temperature() on TempControllerSmith), then echoes the new
value back so the status bar label and entry itself stay in sync.
This commit is contained in:
+15
-2
@@ -96,11 +96,24 @@ if __name__ == '__main__':
|
|||||||
|
|
||||||
# Static, global info that doesn't belong to any one task - sent once;
|
# Static, global info that doesn't belong to any one task - sent once;
|
||||||
# a client connecting later still gets it via the dispatcher's replay
|
# a client connecting later still gets it via the dispatcher's replay
|
||||||
# of accumulated global_state on subscribe.
|
# of accumulated global_state on subscribe. AmbientTemp can also be
|
||||||
|
# changed live by a client (e.g. the GUI's ambient temperature field).
|
||||||
|
msg_system = dispatcher.msgio_get("System")
|
||||||
|
|
||||||
async def send_system_info():
|
async def send_system_info():
|
||||||
await dispatcher.msgio_get("System").send({'AmbientTemp': theta_amb, 'WarpFactor': DT / DT_TASK})
|
await msg_system.send({'AmbientTemp': theta_amb, 'WarpFactor': DT / DT_TASK})
|
||||||
asyncio.ensure_future(send_system_info())
|
asyncio.ensure_future(send_system_info())
|
||||||
|
|
||||||
|
async def on_system_recv(data):
|
||||||
|
global theta_amb
|
||||||
|
if 'AmbientTemp' in data:
|
||||||
|
theta_amb = data['AmbientTemp']
|
||||||
|
pot.set_ambient_temperature(theta_amb)
|
||||||
|
if hasattr(tc, 'set_ambient_temperature'):
|
||||||
|
tc.set_ambient_temperature(theta_amb)
|
||||||
|
await msg_system.send({'AmbientTemp': theta_amb})
|
||||||
|
msg_system.set_recv_handler(on_system_recv)
|
||||||
|
|
||||||
# Message dispatcher
|
# Message dispatcher
|
||||||
h_dispatcher = taskmgr.start()
|
h_dispatcher = taskmgr.start()
|
||||||
h_server = server.listen("0.0.0.0", 8765)
|
h_server = server.listen("0.0.0.0", 8765)
|
||||||
|
|||||||
@@ -3682,6 +3682,35 @@
|
|||||||
<string>Connect</string>
|
<string>Connect</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
|
<widget class="QLabel" name="label_ambient">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>520</x>
|
||||||
|
<y>500</y>
|
||||||
|
<width>91</width>
|
||||||
|
<height>31</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Ambient [°C]</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QLineEdit" name="lineEdit_ambient">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>620</x>
|
||||||
|
<y>500</y>
|
||||||
|
<width>70</width>
|
||||||
|
<height>31</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Set the simulated/assumed ambient temperature - press Enter to apply</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
<widget class="QLabel" name="label_8">
|
<widget class="QLabel" name="label_8">
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
|
|||||||
@@ -329,6 +329,7 @@ class Window(QtWidgets.QMainWindow, Ui_MainWindow):
|
|||||||
|
|
||||||
self.checkbox_heater_activate.stateChanged.connect(self.on_checkbox_changed)
|
self.checkbox_heater_activate.stateChanged.connect(self.on_checkbox_changed)
|
||||||
self.checkbox_stirrer_activate.stateChanged.connect(self.on_checkbox_stirrer_activate_changed)
|
self.checkbox_stirrer_activate.stateChanged.connect(self.on_checkbox_stirrer_activate_changed)
|
||||||
|
self.lineEdit_ambient.returnPressed.connect(self.on_ambient_entry_changed)
|
||||||
|
|
||||||
self.send_data = Queue()
|
self.send_data = Queue()
|
||||||
self.slider_pwr_initial_update = True
|
self.slider_pwr_initial_update = True
|
||||||
@@ -460,6 +461,7 @@ class Window(QtWidgets.QMainWindow, Ui_MainWindow):
|
|||||||
self.sud_state = None
|
self.sud_state = None
|
||||||
self.sud_user_message = None
|
self.sud_user_message = None
|
||||||
self.ambient_temp = None
|
self.ambient_temp = None
|
||||||
|
self.lineEdit_ambient.clear()
|
||||||
self.warp_factor = 1.0
|
self.warp_factor = 1.0
|
||||||
self.sud_start_time = None
|
self.sud_start_time = None
|
||||||
self.sud_paused_total = 0.0
|
self.sud_paused_total = 0.0
|
||||||
@@ -491,10 +493,22 @@ class Window(QtWidgets.QMainWindow, Ui_MainWindow):
|
|||||||
for key in msg:
|
for key in msg:
|
||||||
if "AmbientTemp" in key:
|
if "AmbientTemp" in key:
|
||||||
self.ambient_temp = msg['AmbientTemp']
|
self.ambient_temp = msg['AmbientTemp']
|
||||||
|
# Only sync the entry's text while the user isn't actively
|
||||||
|
# editing it, so a server echo doesn't clobber in-progress
|
||||||
|
# typing.
|
||||||
|
if not self.lineEdit_ambient.hasFocus():
|
||||||
|
self.lineEdit_ambient.setText("{:.1f}".format(self.ambient_temp))
|
||||||
elif "WarpFactor" in key:
|
elif "WarpFactor" in key:
|
||||||
self.warp_factor = msg['WarpFactor']
|
self.warp_factor = msg['WarpFactor']
|
||||||
self.update_status_env_label()
|
self.update_status_env_label()
|
||||||
|
|
||||||
|
def on_ambient_entry_changed(self):
|
||||||
|
try:
|
||||||
|
value = float(self.lineEdit_ambient.text())
|
||||||
|
except ValueError:
|
||||||
|
return
|
||||||
|
self.msg_system.send({'AmbientTemp': value})
|
||||||
|
|
||||||
def update_status_env_label(self):
|
def update_status_env_label(self):
|
||||||
ambient = "{:.1f}°C".format(self.ambient_temp) if self.ambient_temp is not None else "-"
|
ambient = "{:.1f}°C".format(self.ambient_temp) if self.ambient_temp is not None else "-"
|
||||||
self.status_label_env.setText("Ambient: {} Warp: {:.1f}x".format(ambient, self.warp_factor))
|
self.status_label_env.setText("Ambient: {} Warp: {:.1f}x".format(ambient, self.warp_factor))
|
||||||
|
|||||||
@@ -1230,6 +1230,13 @@ class Ui_MainWindow(object):
|
|||||||
self.btn_connect = QtWidgets.QPushButton(self.centralwidget)
|
self.btn_connect = QtWidgets.QPushButton(self.centralwidget)
|
||||||
self.btn_connect.setGeometry(QtCore.QRect(440, 500, 70, 31))
|
self.btn_connect.setGeometry(QtCore.QRect(440, 500, 70, 31))
|
||||||
self.btn_connect.setObjectName("btn_connect")
|
self.btn_connect.setObjectName("btn_connect")
|
||||||
|
self.label_ambient = QtWidgets.QLabel(self.centralwidget)
|
||||||
|
self.label_ambient.setGeometry(QtCore.QRect(520, 500, 91, 31))
|
||||||
|
self.label_ambient.setAlignment(QtCore.Qt.AlignCenter)
|
||||||
|
self.label_ambient.setObjectName("label_ambient")
|
||||||
|
self.lineEdit_ambient = QtWidgets.QLineEdit(self.centralwidget)
|
||||||
|
self.lineEdit_ambient.setGeometry(QtCore.QRect(620, 500, 70, 31))
|
||||||
|
self.lineEdit_ambient.setObjectName("lineEdit_ambient")
|
||||||
self.label_8 = QtWidgets.QLabel(self.centralwidget)
|
self.label_8 = QtWidgets.QLabel(self.centralwidget)
|
||||||
self.label_8.setGeometry(QtCore.QRect(200, 500, 67, 31))
|
self.label_8.setGeometry(QtCore.QRect(200, 500, 67, 31))
|
||||||
self.label_8.setAlignment(QtCore.Qt.AlignCenter)
|
self.label_8.setAlignment(QtCore.Qt.AlignCenter)
|
||||||
@@ -1298,6 +1305,8 @@ class Ui_MainWindow(object):
|
|||||||
self.label_state.setText(_translate("MainWindow", "State"))
|
self.label_state.setText(_translate("MainWindow", "State"))
|
||||||
self.plainTextUri.setPlainText(_translate("MainWindow", "ws://localhost:8765"))
|
self.plainTextUri.setPlainText(_translate("MainWindow", "ws://localhost:8765"))
|
||||||
self.btn_connect.setText(_translate("MainWindow", "Connect"))
|
self.btn_connect.setText(_translate("MainWindow", "Connect"))
|
||||||
|
self.label_ambient.setText(_translate("MainWindow", "Ambient [°C]"))
|
||||||
|
self.lineEdit_ambient.setToolTip(_translate("MainWindow", "Set the simulated/assumed ambient temperature - press Enter to apply"))
|
||||||
self.label_8.setText(_translate("MainWindow", "Host"))
|
self.label_8.setText(_translate("MainWindow", "Host"))
|
||||||
self.menu_File.setTitle(_translate("MainWindow", "&File"))
|
self.menu_File.setTitle(_translate("MainWindow", "&File"))
|
||||||
self.menu_Help.setTitle(_translate("MainWindow", "&Help"))
|
self.menu_Help.setTitle(_translate("MainWindow", "&Help"))
|
||||||
|
|||||||
@@ -28,6 +28,10 @@ class TempController(TempControllerBase):
|
|||||||
self.model.set_thermal_params(M, C)
|
self.model.set_thermal_params(M, C)
|
||||||
self.model_delay.set_thermal_params(M, C)
|
self.model_delay.set_thermal_params(M, C)
|
||||||
|
|
||||||
|
def set_ambient_temperature(self, theta_amb):
|
||||||
|
self.model.set_ambient_temperature(theta_amb)
|
||||||
|
self.model_delay.set_ambient_temperature(theta_amb)
|
||||||
|
|
||||||
def on_state_entered(self, state):
|
def on_state_entered(self, state):
|
||||||
if state == States.HEAT:
|
if state == States.HEAT:
|
||||||
self.model.initial(self.theta_ist)
|
self.model.initial(self.theta_ist)
|
||||||
|
|||||||
Reference in New Issue
Block a user