Skip to content

Commit

Permalink
Merge pull request #387 from linien-org/feature/use-systemd
Browse files Browse the repository at this point in the history
Use systemd instead of screen to run the server
  • Loading branch information
bleykauf authored Apr 5, 2024
2 parents e95e8f3 + 3ffe1a5 commit 535674d
Show file tree
Hide file tree
Showing 12 changed files with 123 additions and 100 deletions.
5 changes: 3 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]

### Added
* Use features of Python 3.10 available on RedPitaya OS 2.0 for `linien-server` by @bleykauf in https://github.com/linien-org/linien/pull/366
* Use features of Python 3.10 available on RedPitaya OS 2.0 for `linien-server` by @bleykauf in https://github.com/linien-org/linien/pull/366
* Add ability to start the server upon startup by @bleykauf in https://github.com/linien-org/linien/pull/387

### Changed

* Use systemd instead of screen for running the server by @bleykauf in https://github.com/linien-org/linien/pull/387
* Use json to store devices and parameters by @bleykauf in https://github.com/linien-org/linien/pull/357
* Better error handling by @bleykauf in https://github.com/linien-org/linien/pull/350
* Improve startup and installation process by @bleykauf in https://github.com/linien-org/linien/pull/372
Expand Down
16 changes: 11 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ In case you are using the `linien-client`, the server can be installed with
from linien_client.device import Device
from linien_client.deploy import install_remote_server

dev = dev = Device(
device = Device(
host="rp-xxxxxx.local",
user="root",
password="root"
Expand All @@ -102,14 +102,20 @@ then running
pip install linien-server
```

In order for the server to be started in a persistent way additional requirements must
be installed by running
The server can then be started as a systemd service by running

```bash
linien-server init
linien-server start
```

For running the server manually, see
on the RedPitaya. To check the status of the server, run


```bash
linien-server status
```

For more options, run

```bash
linien-server --help
Expand Down
1 change: 0 additions & 1 deletion linien-client/linien_client/deploy.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,6 @@ def install_remote_server(
"pip3 uninstall linien-server -y",
"pip3 uninstall linien-common -y",
f"pip3 install linien-server=={local_version} --no-cache-dir",
"linien-server init",
]
for cmd in cmds:
out_stream.write(f">> {cmd}\n")
Expand Down
77 changes: 27 additions & 50 deletions linien-common/linien_common/communication.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,86 +39,63 @@


class LinienControlService(Protocol):
def exposed_get_server_version(self) -> str:
...
def exposed_get_server_version(self) -> str: ...

def exposed_get_param(self, param_name: str) -> bytes:
...
def exposed_get_param(self, param_name: str) -> bytes: ...

def exposed_set_param(self, param_name: str, value: bytes) -> None:
...
def exposed_set_param(self, param_name: str, value: bytes) -> None: ...

def exposed_reset_param(self, param_name: str) -> None:
...
def exposed_reset_param(self, param_name: str) -> None: ...

def exposed_init_parameter_sync(
self, uuid: str
) -> List[Tuple[str, Any, bool, bool, bool, bool]]:
...
) -> List[Tuple[str, Any, bool, bool, bool, bool]]: ...

def exposed_register_remote_listener(self, uuid: str, param_name: str) -> None:
...
def exposed_register_remote_listener(self, uuid: str, param_name: str) -> None: ...

def exposed_register_remote_listeners(
self, uuid: str, param_names: List[str]
) -> None:
...
) -> None: ...

def exposed_get_changed_parameters_queue(self, uuid: str) -> List[Tuple[str, Any]]:
...
def exposed_get_changed_parameters_queue(
self, uuid: str
) -> List[Tuple[str, Any]]: ...

def exposed_write_registers(self) -> None:
...
def exposed_write_registers(self) -> None: ...

def exposed_start_optimization(self, x0, x1, spectrum) -> None:
...
def exposed_start_optimization(self, x0, x1, spectrum) -> None: ...

def exposed_start_psd_acquisition(self) -> None:
...
def exposed_start_psd_acquisition(self) -> None: ...

def exposed_start_pid_optimization(self) -> None:
...
def exposed_start_pid_optimization(self) -> None: ...

def exposed_start_sweep(self) -> None:
...
def exposed_start_sweep(self) -> None: ...

def exposed_start_lock(self) -> None:
...
def exposed_start_lock(self) -> None: ...

def exposed_shutdown(self) -> None:
...
def exposed_shutdown(self) -> None: ...

def exposed_pause_acquisition(self) -> None:
...
def exposed_pause_acquisition(self) -> None: ...

def exposed_continue_acquisition(self) -> None:
...
def exposed_continue_acquisition(self) -> None: ...

def exposed_set_csr_direct(self, key: str, value: int) -> None:
...
def exposed_set_csr_direct(self, key: str, value: int) -> None: ...

def exposed_set_parameter_log(self, param_name: str, value: bool) -> None:
...
def exposed_set_parameter_log(self, param_name: str, value: bool) -> None: ...

def exposed_get_parameter_log(self, param_name: str) -> bool:
...
def exposed_get_parameter_log(self, param_name: str) -> bool: ...

def exposed_update_influxdb_credentials(
self, credentials: InfluxDBCredentials
) -> Tuple[bool, int, str]:
...
) -> Tuple[bool, int, str]: ...

def exposed_get_influxdb_credentials(self) -> InfluxDBCredentials:
...
def exposed_get_influxdb_credentials(self) -> InfluxDBCredentials: ...

def exposed_start_logging(self, interval: float) -> None:
...
def exposed_start_logging(self, interval: float) -> None: ...

def exposed_stop_logging(self) -> None:
...
def exposed_stop_logging(self) -> None: ...

def exposed_get_logging_status(self) -> bool:
...
def exposed_get_logging_status(self) -> bool: ...


def pack(value: ParameterValues) -> Union[bytes, ParameterValues]:
Expand Down
6 changes: 3 additions & 3 deletions linien-gui/linien_gui/ui/spectroscopy_panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,9 +153,9 @@ def change_signal_offset(self):
self.control.exposed_write_registers()

def change_demod_phase(self):
self.get_param(
"demodulation_phase"
).value = self.demodulationPhaseSpinBox.value()
self.get_param("demodulation_phase").value = (
self.demodulationPhaseSpinBox.value()
)
self.control.exposed_write_registers()

def change_demod_multiplier(self, idx):
Expand Down
10 changes: 7 additions & 3 deletions linien-server/linien_server/acquisition.py
Original file line number Diff line number Diff line change
Expand Up @@ -239,9 +239,13 @@ def program_acquisition_and_rearm(self, trigger_delay=16384):

self.red_pitaya.scope.rearm(trigger_source=TriggerSource.ext_posedge)

def exposed_return_data(
self, last_hash: Optional[float]
) -> tuple[bool, float | None, bool | None, bytes | None, float | None,]:
def exposed_return_data(self, last_hash: Optional[float]) -> tuple[
bool,
float | None,
bool | None,
bytes | None,
float | None,
]:
no_data_available = self.data_hash is None
data_not_changed = self.data_hash == last_hash
if data_not_changed or no_data_available or self.pause_event.is_set():
Expand Down
43 changes: 32 additions & 11 deletions linien-server/linien_server/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@
# along with Linien. If not, see <http://www.gnu.org/licenses/>.

import logging
import shutil
import subprocess
from pathlib import Path
from typing import Optional

import fire
Expand All @@ -36,30 +38,36 @@
logger.setLevel(logging.DEBUG)


def copy_systemd_service_file() -> None:
"""Copy systemd service to /etc/systemd/system."""
src = Path(__file__).parent / "linien-server.service"
dst = Path("/etc/systemd/system/linien-server.service")
shutil.copyfile(src, dst)
logger.debug("Copied linien-server.service to /etc/systemd/system")


class LinienServerCLI:
def version(self) -> str:
"""Return the version of the Linien server."""
return __version__

def init(self) -> None:
"""Install the required packages for the Linien server."""
logger.info("Installing Linien server dependencies")
subprocess.run(["apt", "install", "-y", "screen"])
logger.info("Installed Linien server dependencies")

def start(self) -> None:
"""Start the Linien server in a screen session."""
self.stop()
"""Start the Linien server as a systemd service."""
copy_systemd_service_file()
logger.info("Starting Linien server")
subprocess.run(["screen", "-dmS", "linien-server", "linien-server", "run"])
subprocess.run(["systemctl", "start", "linien-server.service"])
logger.info("Started Linien server")

def stop(self) -> None:
"""Stop the Linien server and its screen session."""
"""Stop the Linien server running as a systemd service."""
logger.info("Stopping Linien server")
subprocess.run(["screen", "-XS", "linien-server", "quit"])
subprocess.run(["systemctl", "stop", "linien-server.service"])
logger.info("Stopped Linien server")

def status(self) -> None:
"""Check the status of the Linien server."""
subprocess.run(["journalctl", "-u", "linien-server.service"])

def run(self, fake: bool = False, host: Optional[str] = None) -> None:
"""
Run the Linien server.
Expand All @@ -86,6 +94,19 @@ def run(self, fake: bool = False, host: Optional[str] = None) -> None:
if not (fake or host): # only available on RP
mdio_tool.enable_ethernet_blinking()

def enable(self) -> None:
"""Enable the Linien server to start on boot."""
copy_systemd_service_file()
logger.info("Enabling Linien server")
subprocess.run(["systemctl", "enable", "linien-server.service"])
logger.info("Enabled Linien server")

def disable(self) -> None:
"""Disable the Linien server from starting on boot."""
logger.info("Disabling Linien server")
subprocess.run(["systemctl", "disable", "linien-server.service"])
logger.info("Disabled Linien server")


def main() -> None:
fire.Fire(LinienServerCLI)
Expand Down
10 changes: 10 additions & 0 deletions linien-server/linien_server/linien-server.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[Unit]
Description=Spectroscopy lock server for RedPitaya
Wants=network-online.target
After=network-online.target

[Service]
ExecStart=/usr/bin/env linien-server run

[Install]
WantedBy=multi-user.target
42 changes: 23 additions & 19 deletions linien-server/linien_server/registers.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,13 +102,17 @@ def phase_to_delay(phase):
# NOTE: Sweep center is set by `logic_out_offset`.
logic_sweep_min=-1 * max_(self.parameters.sweep_amplitude.value * 8191),
logic_sweep_max=max_(self.parameters.sweep_amplitude.value * 8191),
logic_mod_freq=self.parameters.modulation_frequency.value
if not self.parameters.pid_only_mode.value
else 0,
logic_mod_amp=self.parameters.modulation_amplitude.value
if (self.parameters.modulation_frequency.value > 0)
and (not self.parameters.pid_only_mode.value)
else 0,
logic_mod_freq=(
self.parameters.modulation_frequency.value
if not self.parameters.pid_only_mode.value
else 0
),
logic_mod_amp=(
self.parameters.modulation_amplitude.value
if (self.parameters.modulation_frequency.value > 0)
and (not self.parameters.pid_only_mode.value)
else 0
),
logic_dual_channel=int(self.parameters.dual_channel.value),
logic_pid_only_mode=int(self.parameters.pid_only_mode.value),
logic_chain_a_factor=factor_a,
Expand Down Expand Up @@ -139,24 +143,24 @@ def phase_to_delay(phase):
logic_autolock_robust_time_scale=self.parameters.autolock_time_scale.value,
logic_autolock_robust_final_wait_time=self.parameters.autolock_final_wait_time.value, # noqa: E501
# channel A
fast_a_demod_delay=phase_to_delay(
self.parameters.demodulation_phase_a.value
)
if (self.parameters.modulation_frequency.value > 0)
and (not self.parameters.pid_only_mode.value)
else 0,
fast_a_demod_delay=(
phase_to_delay(self.parameters.demodulation_phase_a.value)
if (self.parameters.modulation_frequency.value > 0)
and (not self.parameters.pid_only_mode.value)
else 0
),
fast_a_demod_multiplier=self.parameters.demodulation_multiplier_a.value,
fast_a_dx_sel=csrmap.signals.index("zero"),
fast_a_y_tap=2,
fast_a_dy_sel=csrmap.signals.index("zero"),
fast_a_invert=int(self.parameters.invert_a.value),
# channel B
fast_b_demod_delay=phase_to_delay(
self.parameters.demodulation_phase_b.value
)
if (self.parameters.modulation_frequency.value > 0)
and (not self.parameters.pid_only_mode.value)
else 0,
fast_b_demod_delay=(
phase_to_delay(self.parameters.demodulation_phase_b.value)
if (self.parameters.modulation_frequency.value > 0)
and (not self.parameters.pid_only_mode.value)
else 0
),
fast_b_demod_multiplier=self.parameters.demodulation_multiplier_b.value,
fast_b_dx_sel=csrmap.signals.index("zero"),
fast_b_y_tap=1,
Expand Down
8 changes: 5 additions & 3 deletions linien-server/linien_server/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -275,9 +275,11 @@ def exposed_start_autolock(self, x0, x1, spectrum, additional_spectra=None):
spectrum,
should_watch_lock=start_watching,
auto_offset=auto_offset,
additional_spectra=pickle.loads(additional_spectra)
if additional_spectra is not None
else None,
additional_spectra=(
pickle.loads(additional_spectra)
if additional_spectra is not None
else None
),
)

def exposed_start_optimization(self, x0, x1, spectrum):
Expand Down
2 changes: 1 addition & 1 deletion linien-server/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,4 @@ linien-server = "linien_server.cli:main"
namespaces = false

[tool.setuptools.package-data]
data = ["gateware.bin", "mdio-tool"]
data = ["gateware.bin", "mdio-tool", "linien-server.service"]
3 changes: 1 addition & 2 deletions tests/test_pid_transfer.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,7 @@ def plot_transfer(x, y, label=None):
def plot_theory(f, p, i, d, plot_color):
plt.plot(
f,
20
* np.log10(np.abs(p / 4096 + 10 * i / f + d * (f / 125e6) / (2**6))),
20 * np.log10(np.abs(p / 4096 + 10 * i / f + d * (f / 125e6) / (2**6))),
color=plot_color,
linestyle="dashed",
)
Expand Down

0 comments on commit 535674d

Please sign in to comment.