make temperature proxy host and port configurable in the configuration tab

This commit is contained in:
markusro committed 2026-10-23 11:11:18 +02:00
1 parent f562255c75
commit 5f558e4f03
4 files changed
+62 -12

No files matched your search

+3 -2
View File
@@ -51,12 +51,13 @@ Following is a short description of the options:
10. Filename of the data pool file
11. Write interval after which the data pool is rewritten
12. Compression settings
13. Authors, License and version numbers of used components
13. Host and port of the temperature proxy service
14. Authors, License and version numbers of used components
Temperature History
===================
DAMARIS automatically retrieves one temperature history for the complete experiment from the local ``tempproxy`` service at ``http://localhost:8000/v1/readings`` after the experiment finishes. The proxy controls the temperature device; no controller, serial device, or polling interval needs to be configured in DAMARIS. Successful readings are stored under the ``temperature`` DataPool key with elapsed seconds on the x-axis and the proxy's ``pv`` values unchanged on the y-axis, so units depend on the configured controller. If the proxy is unavailable or has no readings for the experiment, the history is omitted and the experiment's other data is still saved.
DAMARIS automatically retrieves one temperature history for the complete experiment from the ``tempproxy`` service at ``http://<host>:<port>/v1/readings`` after the experiment finishes. Host and port are configured in the Configuration tab, the defaults are ``127.0.0.1`` and ``18007``. The proxy controls the temperature device; no controller, serial device, or polling interval needs to be configured in DAMARIS. Successful readings are stored under the ``temperature`` DataPool key with elapsed seconds on the x-axis and the proxy's ``pv`` values unchanged on the y-axis, so units depend on the configured controller. If the proxy is unavailable or has no readings for the experiment, the history is omitted and the experiment's other data is still saved.
Experiment Script
=================
+32 -2
View File
@@ -871,7 +871,10 @@ class DamarisGUI:
temperature_history_start = self.temperature_history_start
self.temperature_history_start = None
self.data.pop("temperature", None)
temperature = TemperatureProxyClient().get_history(
proxy_config = self.config.get( )
temperature = TemperatureProxyClient(
host=proxy_config["tempproxy_host"],
port=proxy_config["tempproxy_port"]).get_history(
temperature_history_start, time.time())
if temperature is not None:
self.data["temperature"] = temperature
@@ -2379,6 +2382,27 @@ class ConfigTab:
backend_vbox.pack_start(self.config_adc_bit_depth_hbox, False, False, 0)
self.config_adc_bit_depth_hbox.show_all()
# temperature proxy settings
self.config_tempproxy_hbox = gtk.Box(orientation=gtk.Orientation.HORIZONTAL, spacing=6)
self.config_tempproxy_host_label = gtk.Label(label="Temp proxy host:")
self.config_tempproxy_host_entry = gtk.Entry()
self.config_tempproxy_host_entry.set_text("127.0.0.1")
self.config_tempproxy_host_entry.set_tooltip_text("Host of the tempproxy service reading the temperature controller")
self.config_tempproxy_host_entry.connect("key-press-event", self.config_keypress)
self.config_tempproxy_port_label = gtk.Label(label="port:")
self.config_tempproxy_port_spinbutton = gtk.SpinButton.new_with_range(1, 65535, 1)
self.config_tempproxy_port_spinbutton.set_value(18007)
self.config_tempproxy_port_spinbutton.set_tooltip_text("Port of the tempproxy service, /v1/readings is requested there")
self.config_tempproxy_port_spinbutton.connect("key-press-event", self.config_keypress)
self.config_tempproxy_hbox.pack_start(self.config_tempproxy_host_label, False, False, 0)
self.config_tempproxy_hbox.pack_start(self.config_tempproxy_host_entry, False, False, 0)
self.config_tempproxy_hbox.pack_start(self.config_tempproxy_port_label, False, False, 0)
self.config_tempproxy_hbox.pack_start(self.config_tempproxy_port_spinbutton, False, False, 0)
frontend_vbox = self.xml_gui.get_object("vbox7")
if frontend_vbox:
frontend_vbox.pack_start(self.config_tempproxy_hbox, False, False, 0)
self.config_tempproxy_hbox.show_all()
# insert version informations
components_text = """
operating system %(os)s
@@ -2485,7 +2509,9 @@ pygobject version %(pygobject)s
"data_pool_complib": complib,
"data_pool_comprate": self.config_data_pool_comprate.get_value_as_int( ),
"script_font": self.config_script_font_button.get_font_name( ),
"adc_bit_depth": self.config_adc_bit_depth_spinbutton.get_value_as_int()
"adc_bit_depth": self.config_adc_bit_depth_spinbutton.get_value_as_int(),
"tempproxy_host": self.config_tempproxy_host_entry.get_text( ),
"tempproxy_port": self.config_tempproxy_port_spinbutton.get_value_as_int( )
}
ADC_Result.default_bit_depth = actual_config["adc_bit_depth"]
return actual_config
@@ -2520,6 +2546,10 @@ pygobject version %(pygobject)s
ADC_Result.default_bit_depth = int(config["adc_bit_depth"])
except (ValueError, TypeError):
pass
if "tempproxy_host" in config:
self.config_tempproxy_host_entry.set_text( str( config[ "tempproxy_host" ] ) )
if "tempproxy_port" in config:
self.config_tempproxy_port_spinbutton.set_value( float( config[ "tempproxy_port" ] ) )
if "data_pool_complib" in config:
# find combo-box entry and make it active...
+12 -5
View File
@@ -1,7 +1,7 @@
"""Read experiment temperature history from the local tempproxy service.
"""Read experiment temperature history from the tempproxy service.
Example:
client = TemperatureProxyClient()
client = TemperatureProxyClient() # defaults to http://127.0.0.1:18007
temperature = client.get_history(start_epoch, end_epoch)
"""
@@ -18,11 +18,18 @@ logger = logging.getLogger(__name__)
class TemperatureProxyClient:
"""Retrieve experiment-bounded readings from ``localhost:8000``."""
"""Retrieve experiment-bounded readings from a configurable tempproxy host/port."""
URL = "http://localhost:8000/v1/readings"
TIMEOUT = 5
def __init__(self, host: str = "127.0.0.1", port: int = 18007):
"""Create a client for ``http://<host>:<port>/v1/readings``.
Example:
client = TemperatureProxyClient(host="192.168.1.5", port=18007)
"""
self.url = f"http://{host}:{port}/v1/readings"
def get_history(self, start_epoch: float, end_epoch: float) -> TemperatureResult | None:
"""Return temperature history relative to the experiment start, or ``None``.
@@ -33,7 +40,7 @@ class TemperatureProxyClient:
temperature = TemperatureProxyClient().get_history(1000.0, 1060.0)
"""
query = urlencode({"start": start_epoch, "end": end_epoch})
url = f"{self.URL}?{query}"
url = f"{self.url}?{query}"
try:
with urlopen(url, timeout=self.TIMEOUT) as response:
+15 -3
View File
@@ -22,7 +22,7 @@ class TestTemperatureProxyClient(unittest.TestCase):
return io.BytesIO(json.dumps(payload).encode("utf-8"))
@patch("damaris.gui.TemperatureProxyClient.urlopen")
def test_get_history_uses_fixed_endpoint_and_converts_readings(self, mock_urlopen):
def test_get_history_uses_default_endpoint_and_converts_readings(self, mock_urlopen):
mock_urlopen.return_value = self.response({
"readings": [
{"t": 101.5, "pv": 293.15},
@@ -35,13 +35,25 @@ class TestTemperatureProxyClient(unittest.TestCase):
args, kwargs = mock_urlopen.call_args
parsed_url = urlparse(args[0])
self.assertEqual(parsed_url.scheme, "http")
self.assertEqual(parsed_url.netloc, "localhost:8000")
self.assertEqual(parsed_url.netloc, "127.0.0.1:18007")
self.assertEqual(parsed_url.path, "/v1/readings")
self.assertEqual(parse_qs(parsed_url.query), {"start": ["100.0"], "end": ["110.0"]})
self.assertEqual(kwargs, {"timeout": TemperatureProxyClient.TIMEOUT})
self.assertEqual(result.x, [1.5, 4.0])
self.assertEqual(result.y, [293.15, 294.25])
@patch("damaris.gui.TemperatureProxyClient.urlopen")
def test_custom_host_and_port_are_used(self, mock_urlopen):
mock_urlopen.return_value = self.response({"readings": [{"t": 101.0, "pv": 293.0}]})
client = TemperatureProxyClient(host="proxy.example.org", port=9000)
client.get_history(100.0, 110.0)
args, _ = mock_urlopen.call_args
parsed_url = urlparse(args[0])
self.assertEqual(parsed_url.netloc, "proxy.example.org:9000")
self.assertEqual(parsed_url.path, "/v1/readings")
@patch("damaris.gui.TemperatureProxyClient.urlopen")
def test_empty_readings_return_none(self, mock_urlopen):
mock_urlopen.return_value = self.response({"readings": []})
@@ -62,7 +74,7 @@ class TestTemperatureProxyClient(unittest.TestCase):
OSError("connection refused"),
TimeoutError("request timed out"),
http.client.BadStatusLine("not an HTTP response"),
HTTPError(TemperatureProxyClient.URL, 500, "server error", {}, None),
HTTPError(self.client.url, 500, "server error", {}, None),
)
for failure in failures:
with self.subTest(failure=failure):