Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Development: Current state #10

Merged
merged 166 commits into from
Jan 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
166 commits
Select commit Hold shift + click to select a range
3de8021
Working version of Coordinator and message utils added.
BenediktBurger Feb 16, 2023
2d33557
Tests and code improved.
BenediktBurger Feb 20, 2023
98f159f
Data protocol Proxy server added.
BenediktBurger Feb 20, 2023
a6e3172
Data control publishing facility added.
BenediktBurger Feb 20, 2023
669b4a7
A pymeasure Actor, "Controller" added.
BenediktBurger Feb 20, 2023
258bd6f
Coordinator improved an Error enum added.
BenediktBurger Feb 24, 2023
e4f58df
Controller update.
BenediktBurger Feb 24, 2023
fee4432
Several improvements in code and tests.
BenediktBurger Mar 27, 2023
b3e33ac
Major overhaul: A new message object is added.
BenediktBurger May 30, 2023
f775b63
Folder structure introduced. Elements restructured.
BenediktBurger Jun 1, 2023
974fcc5
Changed to json message style.
Jun 27, 2023
6e1eb10
Merge branch 'main' into transfer-layer
Jul 19, 2023
392b6dc
Merge branch 'CI' into transfer-layer
Jul 19, 2023
b25d420
Adjust to recent changes.
Jul 19, 2023
a74a5cc
Fix type errors and ensure good bytes in logs.
Jul 19, 2023
3e1761f
Listener fixed.
BenediktBurger Jul 19, 2023
e80bd92
Event renamed.
BenediktBurger Jul 19, 2023
4f9b6ff
Typing improved
BenediktBurger Jul 19, 2023
a17faf8
Typing improved.
BenediktBurger Jul 19, 2023
a20a73d
Fix starter
BenediktBurger Jul 19, 2023
8268b9b
Merge branch 'main' into transfer-layer
BenediktBurger Sep 21, 2023
1e79966
Many improvements.
BenediktBurger Sep 21, 2023
478d361
Merge branch 'transfer-layer' into development
BenediktBurger Oct 11, 2023
406c595
Documentation added to readme.
BenediktBurger Oct 11, 2023
49f2176
Documenation improved.
BenediktBurger Oct 11, 2023
017eeb5
DataLogger refactored and DataLoggerDirector added.
BenediktBurger Oct 11, 2023
45b5eb1
DataLogger adjusted for not using Numpy and StrEnum.
BenediktBurger Oct 11, 2023
86e94fb
Adjust for named log levels (instead of integers).
BenediktBurger Oct 11, 2023
f50a399
Improve code according to mypy linting.
BenediktBurger Oct 11, 2023
1aec32b
More type hinting fixed.
BenediktBurger Oct 12, 2023
f915784
Documentation fixes.
BenediktBurger Oct 12, 2023
9cf93d4
Move BaseController to actor.py
BenediktBurger Oct 12, 2023
c864979
Fix internal dependency on BaseController.
BenediktBurger Oct 12, 2023
71d6118
Readme expanded
BenediktBurger Oct 18, 2023
32f4e2d
Initial version of DataMessage added.
BenediktBurger Oct 19, 2023
e6950b7
Fix message and dataMessage representation.
BenediktBurger Oct 20, 2023
76c9617
Add initial version of data publisher.
BenediktBurger Oct 20, 2023
010d924
Change fullname to full_name
BenediktBurger Oct 20, 2023
5d1fd68
Small changes.
BenediktBurger Oct 20, 2023
060bcad
Extended message handler and qt_listener adapted to new publisher.
BenediktBurger Oct 20, 2023
a294ebd
ext message handler and publisher use 3 frames.
BenediktBurger Oct 20, 2023
abe7f54
Tests adjusted.
BenediktBurger Oct 20, 2023
207f5e2
Merge branch 'main' into development
BenediktBurger Oct 23, 2023
3afb146
Fix linting issues.
BenediktBurger Oct 23, 2023
0095063
Fix line length.
BenediktBurger Oct 23, 2023
71f02e8
Switch to "data_port"
BenediktBurger Oct 25, 2023
7bf0b02
Initial (untested) version of a log logger added
BenediktBurger Oct 25, 2023
bf08d48
Fix internal dependency, switch datalogger to new data protocol.
BenediktBurger Oct 25, 2023
bd21a7c
Make created parser default.
BenediktBurger Oct 25, 2023
0505755
Fix linting in log_logger
BenediktBurger Oct 25, 2023
f762cca
Improve documentation.
BenediktBurger Oct 25, 2023
6234185
Add message types.
BenediktBurger Oct 26, 2023
9c802e1
Coordinator uses message types.
BenediktBurger Oct 26, 2023
1fe5829
Communicator and MessageHandler use MessageType
BenediktBurger Oct 26, 2023
6cfc3a8
Directors use MessageType
BenediktBurger Oct 26, 2023
b6e99bc
Listener uses MessageTypes.
BenediktBurger Oct 26, 2023
a814ea4
Make message_type int, move MessageTypes to serialization.
BenediktBurger Oct 26, 2023
52e7bb3
Improve checks.
BenediktBurger Oct 26, 2023
3f1be59
Use MessageType for recognition. Adjust tests.
BenediktBurger Oct 26, 2023
cc6eb76
Add byteorder for backward compatibility.
BenediktBurger Oct 26, 2023
0f9223b
Fix typing issue.
BenediktBurger Oct 26, 2023
8624282
Fix more bytes conversion.
BenediktBurger Oct 26, 2023
0130432
Add used assumptions.
BenediktBurger Oct 27, 2023
130b863
Expand test coverage
BenediktBurger Oct 27, 2023
d44cede
Message Handler tests expanded
BenediktBurger Oct 30, 2023
669d651
Add tests for extended message handler
BenediktBurger Oct 30, 2023
8b077f8
Expand PipeHandler tests
BenediktBurger Oct 30, 2023
8e7b95f
Fix linting issues.
BenediktBurger Oct 30, 2023
a72d022
Add Channel capabilities to actor.
BenediktBurger Oct 31, 2023
fc01c0b
Improve RemoteCall
BenediktBurger Oct 31, 2023
8952e56
Fix Actor according to LECO definitions
BenediktBurger Nov 1, 2023
9050b8d
Rework TransparentDirector (with device, adding tests)
BenediktBurger Nov 1, 2023
8e28454
Change from Instrument to Device (according to LECO)
BenediktBurger Nov 1, 2023
c520510
Fix call_action call in Director
BenediktBurger Nov 1, 2023
8dea49c
Modify Actor to use DataPublisher
BenediktBurger Nov 1, 2023
7746359
Remove motorController and Director as being too specific
BenediktBurger Nov 1, 2023
f581895
Make qtListener use qtpy.
BenediktBurger Nov 2, 2023
8662229
Fix MessageBuffer for real thread_safety
BenediktBurger Nov 2, 2023
73f32ca
Rework PipeHandler to offer a Communicator interface
BenediktBurger Nov 3, 2023
4cd2405
Fix Listener to use new PipeHandler interface
BenediktBurger Nov 3, 2023
59643a9
Fix linting.
BenediktBurger Nov 3, 2023
7ec783c
Add timeout and read_message to CommunicatorProtocol
BenediktBurger Nov 3, 2023
7a2926d
Add ask_rpc to CommunciatorProtocol
BenediktBurger Nov 3, 2023
45c7c63
Restructure pipe_handler and listener
BenediktBurger Nov 3, 2023
475a3b0
Add tests for internal protocols.
BenediktBurger Nov 3, 2023
fbfe1b0
Fix typing issues.
BenediktBurger Nov 3, 2023
00b3450
Add tests for data_logger and pipe_handler
BenediktBurger Nov 3, 2023
3e55f79
Add CoordinatorDirector to Coordinator live test.
BenediktBurger Nov 6, 2023
251763a
Add datalogger tests.
BenediktBurger Nov 6, 2023
ea4e831
Add SubscriberProtocol
BenediktBurger Nov 6, 2023
27dce93
Rename in director call_method_rpc to ask_rpc
BenediktBurger Nov 6, 2023
7759c34
Fix type errors and numpy
BenediktBurger Nov 6, 2023
ac0caf2
Add namespace signal to qt_listener.
BenediktBurger Nov 8, 2023
3374d16
Add documentation to qt_listener
BenediktBurger Nov 9, 2023
24c3d27
Add timeout for sign out message response to message handler.
BenediktBurger Nov 9, 2023
c8eaec9
Add register_rpc_method to message_handler
BenediktBurger Nov 9, 2023
d8d7dcf
Cleanup Listener and pipe_handler
BenediktBurger Nov 9, 2023
13ba3ea
Reorganize extended message handler
BenediktBurger Nov 13, 2023
6611820
Remove sql datalogger
BenediktBurger Nov 13, 2023
41a93b9
Fix error message in director.
BenediktBurger Nov 13, 2023
e2daf1c
Error handling improvement.
BenediktBurger Nov 13, 2023
ae3d72c
Improve documentation.
BenediktBurger Nov 15, 2023
bf40c9b
Use list.remove.
BenediktBurger Nov 16, 2023
ca5b885
Improve type hints
BenediktBurger Nov 17, 2023
d4c026d
Add new data messages to datalogger.
BenediktBurger Nov 17, 2023
b958a69
Modify qt_listener signals
BenediktBurger Nov 17, 2023
28f08fd
Remove print messages.
BenediktBurger Nov 21, 2023
13f90af
Add local communication to PipeHandler
BenediktBurger Nov 22, 2023
92f15fd
Rename datalogger datapoint
BenediktBurger Nov 22, 2023
ab57b90
Fix data_logger
BenediktBurger Nov 23, 2023
9467dea
Switch to if main then main() style
BenediktBurger Nov 27, 2023
62ce218
DataLogger tests expanded
BenediktBurger Nov 27, 2023
105e202
Rework datalogger
BenediktBurger Nov 28, 2023
ec027ba
Fix data_logger_director
BenediktBurger Dec 1, 2023
8571475
Add test for starter director
BenediktBurger Dec 1, 2023
f010887
Add test for coordinator director
BenediktBurger Dec 4, 2023
7e00260
Modify live test.
BenediktBurger Dec 4, 2023
bd1c8c2
Add serialization test.
BenediktBurger Dec 4, 2023
958a0cd
Add environment variable to readme.
BenediktBurger Dec 5, 2023
7e10883
Add close and context management to DataPublisher
BenediktBurger Dec 6, 2023
72c9296
Fix starter to indicate dead tasks.
BenediktBurger Dec 6, 2023
ce1c15b
Fix linting
BenediktBurger Dec 6, 2023
416d7ec
Refactor message_handler and expand tests.
BenediktBurger Dec 11, 2023
4b14055
Change core elements to typing.union
BenediktBurger Dec 11, 2023
498df81
Change utils to typing.Union
BenediktBurger Dec 11, 2023
922c479
Move other files to typing.Union
BenediktBurger Dec 11, 2023
95f0717
Allow Python 3.9
BenediktBurger Dec 11, 2023
a8f8d73
Add test for parser
BenediktBurger Dec 11, 2023
6527c09
Increase test coverage.
BenediktBurger Dec 11, 2023
e38734b
Add changelog.
BenediktBurger Dec 12, 2023
dd95ea7
Merge branch 'main' into development
BenediktBurger Dec 13, 2023
cb48308
Improve log message in Coordinator.
BenediktBurger Dec 18, 2023
8e6d9c4
Add log for stopped task
BenediktBurger Dec 18, 2023
811f51a
Expand test coverage.
BenediktBurger Dec 18, 2023
4b6410b
Merge branch 'development' of https://github.com/pymeasure/pyleco int…
BenediktBurger Dec 18, 2023
505388d
Fix linting.
BenediktBurger Dec 19, 2023
e19996b
Fix typos.
BenediktBurger Dec 20, 2023
9883318
Rename adress to address in Coordinator.
BenediktBurger Dec 20, 2023
1dc255f
Fix more typos.
BenediktBurger Dec 20, 2023
249643c
Expand Readme with examples.
BenediktBurger Dec 20, 2023
eca86d6
Add set_full_name to datapublisher.
BenediktBurger Jan 2, 2024
3e6d38f
Create register on name change method in listener.
BenediktBurger Jan 2, 2024
34b7314
Merge remote-tracking branch 'origin/main' into development
BenediktBurger Jan 3, 2024
39babab
Prepare message handler for communicatorProtocol.
BenediktBurger Jan 5, 2024
9b0cc42
Make the MessageHandler distinguish requested messages.
BenediktBurger Jan 8, 2024
45913a5
Add ask_message to messagehandler.
BenediktBurger Jan 8, 2024
97d902b
Rework MessageHandler to comply with the Communicator.
BenediktBurger Jan 8, 2024
2e6eafe
Remove deprecated ask from director.
BenediktBurger Jan 8, 2024
dfe1750
Fix linting.
BenediktBurger Jan 8, 2024
498545a
Fix typo.
BenediktBurger Jan 10, 2024
0fa3732
Fix MessageHandler sign_in.
BenediktBurger Jan 11, 2024
f3564c0
Add full_name to communicator.
BenediktBurger Jan 11, 2024
22ce4cf
Add units to datalogger
BenediktBurger Jan 11, 2024
d3b6207
Fix type hints.
BenediktBurger Jan 11, 2024
5cc3039
Rename logHandler
BenediktBurger Jan 16, 2024
62523be
Add changelog entries.
BenediktBurger Jan 16, 2024
000245b
Add a getting started tutorial.
BenediktBurger Jan 18, 2024
8611d96
Fix links in getting started
BenediktBurger Jan 18, 2024
d3efbb1
Improve qt listener.
BenediktBurger Jan 18, 2024
17a09b7
Skip tests if qtpy is not installed.
BenediktBurger Jan 18, 2024
e2c0b99
Cleanup.
BenediktBurger Jan 19, 2024
f6b9442
Add Python 3.12
BenediktBurger Jan 22, 2024
a4b5a95
Skip acceptance tests under macOS, see #18
BenediktBurger Jan 22, 2024
75608ea
Bump pyzmq version.
BenediktBurger Jan 22, 2024
076dabd
Merge pull request #22 from pymeasure/new-ci
BenediktBurger Jan 22, 2024
088d743
Modify Readme and changelog for branch switch.
BenediktBurger Jan 24, 2024
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
15 changes: 10 additions & 5 deletions .github/workflows/pyleco_CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ jobs:
junitxml-title: Coverage Summary
- name: Check output coverage
run: |
echo "Coverage Percantage - ${{ steps.coverageComment.outputs.coverage }}"
echo "Coverage Percentage - ${{ steps.coverageComment.outputs.coverage }}"
echo "Coverage Color - ${{ steps.coverageComment.outputs.color }}"
echo "Coverage Html - ${{ steps.coverageComment.outputs.coverageHtml }}"

Expand Down Expand Up @@ -140,7 +140,7 @@ jobs:
fail-fast: true
matrix:
os: ["ubuntu-latest", "macos-latest", "windows-latest"]
python-version: ["3.9", "3.10", "3.11"]
python-version: ["3.9", "3.10", "3.11", "3.12"]
steps:
- uses: actions/checkout@v3
with:
Expand All @@ -159,13 +159,18 @@ jobs:
run: pip install .[dev]
- name: Pyleco version
run: python -c "import pyleco;print(pyleco.__version__)"
- name: Run pytest with xvfb
- name: Run pytest under Linux with xvfb
if: runner.os == 'Linux'
run: |
echo "::add-matcher::.github/pytest.json"
xvfb-run -a pytest
- name: Run pytest
if: runner.os != 'Linux'
- name: Run pytest under Windows
if: runner.os == 'Windows'
run: |
echo "::add-matcher::.github/pytest.json"
pytest
- name: Run pytest under Mac without acceptance tests
if: runner.os == 'macOS'
run: |
echo "::add-matcher::.github/pytest.json"
pytest --ignore=tests/acceptance_tests
25 changes: 25 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# CHANGELOG

## Upcoming version

### Changed

- Change message and protocols according to LECO change ([`9d74731da`](https://github.com/pymeasure/pyleco/commit/9d74731da06d147b1773f1f411bd943a36b4a83d))
- Coordinator has no `full_name` instead of `fname` ([`f3564c0`](https://github.com/pymeasure/pyleco/commit/f3564c08f04ed63bbab5b1100560e7b50239d83c)))

### Added
- Add compatibility with Python 3.9 ([`18abb87`](https://github.com/pymeasure/pyleco/commit/18abb87fea259f9e87411d88cca92a886bbd62b4))
- Add compatibility with Python 3.12 ([#22](https://github.com/pymeasure/pyleco/pull/22), @BenediktBurger)
- Add more tests.
- Add more functionality to internal protocol and test suite ([`42e107c5cb90`](https://github.com/pymeasure/pyleco/commit/42e107c5cb90704dbb99ef1c5a50be739f3acf85))
- Add Communicator functionality to the MessageHandler by distinguishing messages. (`9b0cc42`, `45913a5`, `97d902b`)


### Fixed

- Fix typos, also in variable / method names


## [alpha-0.0.1] - 2023-12-12

_Initial alpha version, complies with [LECO protocol alpha-0.0.1](https://github.com/pymeasure/leco-protocol/releases/tag/alpha-0.0.1)_
254 changes: 254 additions & 0 deletions GETTING_STARTED.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,254 @@
# Getting started

This tutorial gives an overview how to start a LECO setup in Python.

## Installation

Install PyLECO as described in the README.

Eventually, but not now yet, you can install PyLECO via pip or conda:
```pip install pyleco```

## Setup the Infrastructure

### The Coordinators

Core of the infrastructure are communication servers, called Coordinators.
As LECO consists in two parts, the control protocol and the data protocol, there are two servers:

1. The _Coordinator_ in [`coordinator.py`](pyleco/coordinators/coordinator.py) is the server of the control protocol.
2. [`proxy_server.py`](pyleco/coordinators/proxy_server.py) contains the server of the data protocol.

In order to start these Coordinators, just execute the files.
For example, change directory in the folder of this file and execute `python3 pyleco/coordinators/coordinator.py` under linux or `py pyleco/coordinators/coordinator.py` under Windows with the Windows Launcher installed.

If you need different settings than the defaults, you can use command line parameters.
The command line parameter `-h` or `--help` gives an overview of all available parameters.
For example `python3 pyleco/coordinators/coordinator.py -h` gives the information, while `python3 pyleco/coordinators/coordinator.py --port 12345` makes the Coordinator listen on tcp port 12345 instead of the default one.

### The Starter

LECO allows to have many small parts working together instead of one monolithic program.
In order to not have to start all these small parts individually in their own terminal window, there is another server, the [`Starter`](pyleco/management/starter.py).

The starter scans a directory (given as argument) for python files.
It will start, if told to do so, the method `task` of a given file name in a separate thread.
That allows to specify several different tasks, for example each one controlling one measurement instrument, and to start them by sending a command to the starter.

In order to start the starter itself, just execute its file with the path to the directory, for example `python3 pyleco/management/starter.py --directory ~/tasks` with the tasks being in the subfolder `tasks` of the home directory.

#### Define a Task File

The example file [`pymeasure_actor.py`](examples/pymeasure_actor.py) contains an example, how a task file in that directory could look like:

The first docstring of the file is going to be the description of that task.
The starter offers that docstring, if you query it for its available tasks.

You have to specify a `task` method with exactly one parameter, the `stop_event`.
The starter will give a `threading.Event` instance as an argument in order to tell the task when to stop.
You could write any `task` method, which checks regularly the `stop_event` and stops, if that event is set.
PyLECO offers helper methods to do most of the work for controlling an instrument.

If you have a python class you want to control remotely, for example a [pymeasure](https://pymeasure.readthedocs.io) instrument driver for a fiber laser called `YAR`, you can use the [`Actor`](pyleco/actors/actor.py).

This will be your task file `YAR_controller.py`:

```python
"""Example scheme for an Actor for pymeasure instruments. 'fiberAmp'"""

from pyleco.actors.actor import Actor
from pymeasure.instruments.ipgphotonics import YAR

# Parameters
adapter = "ASRL5" # VISA resource string, for example serial port COM5

def task(stop_event) -> None:
"""The task which is run by the starter."""
with Actor(
name="fiberAmp", # you can access it under this name
cls=YAR, # the class to instantiate later on
) as actor:
actor.connect(adapter) # create an instance `actor.device = YAR(adapter)`

actor.listen(stop_event=stop_event) # listen for commands
```

The `Actor` will listen under the name `fiberAmp` for incoming commands and handle them until the `stop_event` is set.
For example you can get or set properties of the `YAR` instance, or you can call methods.

#### Start / Stop a Task

Now we have our three servers (Coordinator, proxy_server, Starter) up and running, but the task is not yet started.
In order to start a task, we have to tell the Starter to do so.
The easiest way is to use the [`StarterDirector`](pyleco/directors/starter_director.py) (found in the `directors` directory) in a python console or script:
```python
from pyleco.directors.starter_director import StarterDirector
director = StarterDirector(actor="starter")
director.start_tasks(["YAR_controller"])
```

The `actor` parameter tells the Director the name of the `Starter` instance which defaults to `"starter"`.
As the task file is named `YAR_controller.py`, the task name is `"YAR_controller".
You can give a list of tasks to start.

The starter director has also methods to stop a task, give a list of available tasks, and to give a list of the state of the known tasks (running, stopped, crashed).


## Control an Experiment

### Control the Instrument: The Director

Now we have our severs running and also the task controlling our fiber amplifier is running.
In order to remotely control the fiber amplifier, we have to send messages to it.
Again we have a director to direct the actions of the fiber amplifier.

This time, the director is a more generic one, the [`TransparentDirector`](pyleco/directors/transparent_director.py) (also in the directors directory).
If you read or write any property of the the TransparentDirector's `device`, it will read or write to the remotely controlled instrument.
For example
```python
from pyleco.directors.transparent_director import TransparentDirector

director = TransparentDirector(actor="fiberAmp")

if not director.device.emission_enabled:
director.device.emission_enabled = True

```
will read, whether the emission of the fiber amplifier is enabled, if not, it will be enabled.

Behind the scenes, the transparent director sends a request to the Actor named `"fiberAmp"` (remember, that is the name we gave to the actor in the task file) to read the `emission_enabled` property of the `YAR` instance.
The Actor will read the `device.emission_enabled` property and return it to the director.

Alternatively, you could get/set the parameters manually.
The following lines are equivalent to the previous code:
```python
if not director.get_parameters(parameters=["emission_enabled"])["emission_enabled"]:
director.set_parameters({"emission_enabled": True})
```
The get/set parameters method allow to get/set more than one parameter in one message.

If you want to call the method `clear` of the `YAR` instance, you can use `director.call_action(action="clear")`.
Any positional or keyword arguments you give to the `call_action` method will be given to the `clear` method.
For example `director.call_action(action="set_power", power=5)` will cause the actor to call `device.set_power(power=5)`.


### Different Computers

LECO is not limited to a single computer, but you can use it in a computer network.

#### Single Coordinator Setup

Each Component (any program participating in LECO) needs to connect to a Coordinator.
Per default, the PyLECO components look for a Coordinator at the same computer (localhost).
If the Coordinator is on another computer or listens on another port, you can specify these value as arguments.
For example: `Actor(host="myserver.com", port=12345)` will connect to the Coordinator on a computer available (via DNS) as `myserver.com` which listens on the port `12345`.
You can also specify IP address instead of computer names.

#### Multi Coordinator Setup

##### Setup of the Coordinators

You can have more than one Coordinator, even on the same computer.
Each Coordinator needs its own combination of host name and port number.
That means, that they have at least to reside on different computers or have different port numbers.

You can tell a Coordinator about other Coordinators, either by specifying the `--coordinators` command line argument (a comma separated list of coordinator addresses) or by using the `CoordinatorDirector`'s `add_nodes({namespace: address})` command.
If you tell one Coordinator about a second one, it will connect to all other Coordinators, to which the second one is connected, thus creating a network automatically.

##### The namespace

Each Coordinator establishes a _Namespace_, which defaults to the name of the computer it resides on.
Each Component connected to that Coordinator belongs to that namespace.
The _full name_ of the Component consists of the namespace and its own name, joined by a period.
For example, let's say the Coordinator of our setup in the beginning has the namespace `N1`, then the fiber amplifier would be available under the name `N1.fiberAmp`.
If you do not specify the namespace, LECO assumes that the recipient's namespace is the same as the sender's namespace, similar to the area code of a phone number.

You can send from any Component connected to any Coordinator (which has to be connected to `N1` Coordinator or be `N1` Coordinator itself) a message to `N1.fiberAmp` and it will arrive there.
The response will always return as well, as you must specify the sender's namespace.

### Collect Data

If you're doing an experiment, you probably want to collect data as well.

You can publish data via the data protocol.
As a helper class, you can use the [`DataPublisher`](pyleco/utils/data_publisher.py):
```python
from pyleco.utils.data_publisher import DataPublisher

publisher = DataPublisher(full_name="N1.abc")
publisher.send_data("def")
```
That will publish the data `"def"` from the sender `"N1.abc"`.

Anyone connected to the same proxy_server can listen to that published data.
You have to subscribe to the sender `"N1.abc"` first, though.

The [`DataLogger`](pyleco/management/data_logger.py) (in the `management` directory) collects these data snippets (if they are in the form of dictionaries: `{variable: value}` with a variable name and an associated value) and creates datapoints.
Afterwards you can save the collected datapoints.


## Include LECO in your own Programs

### LECO Basics

Some basic information about LECO and its python implementation

#### JSON-RPC and Remote Procedure Calls

Default messages are based on Remote Procedure Calls (RPC) according to the [JSON-RPC](https://www.jsonrpc.org/specification) protocol.
Basically you request to execute a procedure call on a remote station and receive the response of that call.

#### Communicator

There are several tools in the `utils` directory, which behave as _Communicator_.
They can be used as an argument for any `communicator` parameter.
All these Communicators offer some convenience methods to send RPC requests and to deceipher the responses.
For example `communicator.ask_rpc(receiver="N1.fiberAmp", method="get_parameters", parameters=["emission_enabled"])` would call the `get_parameters` method of the actor called `"N1.fiberAmp"` with the keyword argument `parameters=["emission_enabled"]`.
The result of that method is the content, for example `{"emission_enabled": True}`.

That example is the code behind the call of the director example.

### Daemon Type

For a program which runs happily in the background listening for commands, executing them, you can base your code on the [`MessageHandler`](pyleco/utils/message_handler.py) (in `utils` directory).
The MessageHandler will listen to incoming messages and handle them in a continuous loop.
The `listen` method has three parts:
1. The method `_listen_setup`, where you can specify, what to do at the start of listening,
2. the method `_listen_loop_element`, which is executed in the loop until the `stop_event` is set.
Typically, it listens for incoming messages and handles them,
3. the method `_listen_close`, which finishes after having been told to stop.

If you want to make a method available for RPC calls, you can use the `register_rpc_method` method.
That allows any Component to use that method via `ask_rpc`.
For example `register_rpc_method(do_something)` would register the method `do_something`, such that someone else could do `ask_rpc(method="do_something")` calling that method.

The message handler (and its subclasses) have to be in their listening loop to do their work:
```python
from pyleco.utils.message_handler import MessageHandler

message_handler = MessageHandler("my_name")
message_handler.listen() # infinity loop
```

### In an Additional Thread

Sometimes, you want to have LECO communication, but do not want to block the thread, for example in a GUI.

The [`Listener`](pyleco/utils/listener.py) (in `utils` directory) starts a special form of the `MessageHandler` in another thread and offers a communicator:
```python
from pyleco.utils.listener import Listener
from pyleco.directors.transparent_director import TransparentDirector

listener = Listener("my_name")
listener.start_listen()
communicator = listener.get_communicator()

listener.register_rpc_method(my_method)

director = TransparentDirector(communicator=communicator)
```

In this example, the message handler will offer the `my_method` method via RPC (via the listener's `register_rpc_method`).
However, that method will be executed in the message handler thread!
You can send messages via the message handler by using the listener's `communciator.
In this example the director uses this communicator instead of creating its own one with its own name.
Loading
Loading