symetrie-hexapod 0.17.1__tar.gz → 0.17.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. {symetrie_hexapod-0.17.1 → symetrie_hexapod-0.17.3}/.gitignore +5 -0
  2. {symetrie_hexapod-0.17.1 → symetrie_hexapod-0.17.3}/PKG-INFO +1 -1
  3. {symetrie_hexapod-0.17.1 → symetrie_hexapod-0.17.3}/pyproject.toml +1 -1
  4. {symetrie_hexapod-0.17.1 → symetrie_hexapod-0.17.3}/src/egse/hexapod/symetrie/puna_ui.py +2 -3
  5. symetrie_hexapod-0.17.1/src/egse/hexapod/symetrie/puna_sim.py +0 -252
  6. {symetrie_hexapod-0.17.1 → symetrie_hexapod-0.17.3}/README.md +0 -0
  7. {symetrie_hexapod-0.17.1 → symetrie_hexapod-0.17.3}/src/egse/hexapod/__init__.py +0 -0
  8. {symetrie_hexapod-0.17.1 → symetrie_hexapod-0.17.3}/src/egse/hexapod/symetrie/__init__.py +0 -0
  9. {symetrie_hexapod-0.17.1 → symetrie_hexapod-0.17.3}/src/egse/hexapod/symetrie/alpha.py +0 -0
  10. {symetrie_hexapod-0.17.1 → symetrie_hexapod-0.17.3}/src/egse/hexapod/symetrie/dynalpha.py +0 -0
  11. {symetrie_hexapod-0.17.1 → symetrie_hexapod-0.17.3}/src/egse/hexapod/symetrie/hexapod.py +0 -0
  12. {symetrie_hexapod-0.17.1 → symetrie_hexapod-0.17.3}/src/egse/hexapod/symetrie/hexapod_ui.py +0 -0
  13. {symetrie_hexapod-0.17.1 → symetrie_hexapod-0.17.3}/src/egse/hexapod/symetrie/joran.py +0 -0
  14. {symetrie_hexapod-0.17.1 → symetrie_hexapod-0.17.3}/src/egse/hexapod/symetrie/joran.yaml +0 -0
  15. {symetrie_hexapod-0.17.1 → symetrie_hexapod-0.17.3}/src/egse/hexapod/symetrie/joran_cs.py +0 -0
  16. {symetrie_hexapod-0.17.1 → symetrie_hexapod-0.17.3}/src/egse/hexapod/symetrie/joran_protocol.py +0 -0
  17. {symetrie_hexapod-0.17.1 → symetrie_hexapod-0.17.3}/src/egse/hexapod/symetrie/joran_ui.py +0 -0
  18. {symetrie_hexapod-0.17.1 → symetrie_hexapod-0.17.3}/src/egse/hexapod/symetrie/pmac.py +0 -0
  19. {symetrie_hexapod-0.17.1 → symetrie_hexapod-0.17.3}/src/egse/hexapod/symetrie/pmac_regex.py +0 -0
  20. {symetrie_hexapod-0.17.1 → symetrie_hexapod-0.17.3}/src/egse/hexapod/symetrie/puna.py +0 -0
  21. {symetrie_hexapod-0.17.1 → symetrie_hexapod-0.17.3}/src/egse/hexapod/symetrie/puna.yaml +0 -0
  22. {symetrie_hexapod-0.17.1 → symetrie_hexapod-0.17.3}/src/egse/hexapod/symetrie/puna_cs.py +0 -0
  23. {symetrie_hexapod-0.17.1 → symetrie_hexapod-0.17.3}/src/egse/hexapod/symetrie/puna_protocol.py +0 -0
  24. {symetrie_hexapod-0.17.1 → symetrie_hexapod-0.17.3}/src/egse/hexapod/symetrie/punaplus.py +0 -0
  25. {symetrie_hexapod-0.17.1 → symetrie_hexapod-0.17.3}/src/egse/hexapod/symetrie/zonda.py +0 -0
  26. {symetrie_hexapod-0.17.1 → symetrie_hexapod-0.17.3}/src/egse/hexapod/symetrie/zonda.yaml +0 -0
  27. {symetrie_hexapod-0.17.1 → symetrie_hexapod-0.17.3}/src/egse/hexapod/symetrie/zonda_cs.py +0 -0
  28. {symetrie_hexapod-0.17.1 → symetrie_hexapod-0.17.3}/src/egse/hexapod/symetrie/zonda_devif.py +0 -0
  29. {symetrie_hexapod-0.17.1 → symetrie_hexapod-0.17.3}/src/egse/hexapod/symetrie/zonda_protocol.py +0 -0
  30. {symetrie_hexapod-0.17.1 → symetrie_hexapod-0.17.3}/src/egse/hexapod/symetrie/zonda_ui.py +0 -0
  31. {symetrie_hexapod-0.17.1 → symetrie_hexapod-0.17.3}/src/symetrie_hexapod/__init__.py +0 -0
  32. {symetrie_hexapod-0.17.1 → symetrie_hexapod-0.17.3}/src/symetrie_hexapod/cgse_explore.py +0 -0
  33. {symetrie_hexapod-0.17.1 → symetrie_hexapod-0.17.3}/src/symetrie_hexapod/cgse_services.py +0 -0
  34. {symetrie_hexapod-0.17.1 → symetrie_hexapod-0.17.3}/src/symetrie_hexapod/settings.yaml +0 -0
@@ -32,6 +32,11 @@ venv
32
32
 
33
33
  .idea
34
34
 
35
+ # VSCode IDE
36
+
37
+ .vscode
38
+ *.code-workspace
39
+
35
40
  # MKDOCS documentation site
36
41
 
37
42
  /site
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: symetrie-hexapod
3
- Version: 0.17.1
3
+ Version: 0.17.3
4
4
  Summary: Symetrie Hexapod implementation for CGSE
5
5
  Author: IvS KU Leuven
6
6
  Maintainer-email: Rik Huygen <rik.huygen@kuleuven.be>, Sara Regibo <sara.regibo@kuleuven.be>
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "symetrie-hexapod"
3
- version = "0.17.1"
3
+ version = "0.17.3"
4
4
  description = "Symetrie Hexapod implementation for CGSE"
5
5
  authors = [
6
6
  {name = "IvS KU Leuven"}
@@ -29,8 +29,6 @@ from PyQt5.QtWidgets import QFrame
29
29
  from PyQt5.QtWidgets import QHBoxLayout
30
30
  from PyQt5.QtWidgets import QMessageBox
31
31
  from PyQt5.QtWidgets import QVBoxLayout
32
- from dotenv import find_dotenv
33
- from dotenv import load_dotenv
34
32
 
35
33
  from egse.gui import show_warning_message
36
34
  from egse.gui.led import Indic
@@ -50,10 +48,11 @@ from egse.process import ProcessStatus
50
48
  from egse.resource import get_resource
51
49
  from egse.settings import Settings
52
50
  from egse.system import do_every
51
+ from dotenv import load_dotenv
53
52
 
54
53
  MODULE_LOGGER = logging.getLogger(__name__)
55
54
 
56
- load_dotenv(find_dotenv(usecwd=True), override=True)
55
+ load_dotenv(override=True)
57
56
 
58
57
 
59
58
  class DeviceControllerType(IntEnum):
@@ -1,252 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import contextlib
4
- import datetime
5
- import logging
6
- import re
7
- import socket
8
- import time
9
-
10
- import typer
11
- from egse.settings import Settings
12
- from egse.system import SignalCatcher
13
-
14
- logger = logging.getLogger("puna-sim")
15
-
16
- HOST = "localhost"
17
- PUNA_SETTINGS = Settings.load("Hexapod Controller")
18
-
19
-
20
- device_time = datetime.datetime.now(datetime.timezone.utc)
21
- reference_time = device_time
22
-
23
-
24
- app = typer.Typer(help="PUNA Simulator")
25
-
26
- error_msg: str | None = None
27
- """Global error message, always contains the last error. Reset in the inner loop of run_simulator."""
28
-
29
-
30
- def create_datetime(year, month, day, hour, minute, second):
31
- global device_time, reference_time
32
- device_time = datetime.datetime(year, month, day, hour, minute, second, tzinfo=datetime.timezone.utc)
33
- reference_time = datetime.datetime.now(datetime.timezone.utc)
34
-
35
-
36
- def nothing():
37
- return None
38
-
39
-
40
- def set_time(year, month, day, hour, minute, second):
41
- logger.info(f"TIME {year}, {month}, {day}, {hour}, {minute}, {second}")
42
- create_datetime(int(year), int(month), int(day), int(hour), int(minute), int(second))
43
-
44
-
45
- def get_time():
46
- current_device_time = device_time + (datetime.datetime.now(datetime.timezone.utc) - reference_time)
47
- msg = current_device_time.strftime("%a %b %d %H:%M:%S %Y")
48
- logger.info(f":SYST:TIME? {msg = }")
49
- return msg
50
-
51
-
52
- def beep(a, b):
53
- logger.info(f"BEEP {a=}, {b=}")
54
-
55
-
56
- def block(secs: str):
57
- logger.info(f"Blocking execution for {secs} seconds.")
58
- time.sleep(float(secs))
59
-
60
-
61
- def reset():
62
- logger.info("RESET")
63
-
64
-
65
- COMMAND_ACTIONS_RESPONSES = {
66
- "*IDN?": (None, "KEITHLEY INSTRUMENTS, MODEL DAQ6510, SIMULATOR"),
67
- }
68
-
69
- # Check the regex at https://regex101.com
70
-
71
- COMMAND_PATTERNS_ACTIONS_RESPONSES = {
72
- r":?\*RST": (reset, None),
73
- r":?SYST(?:em)*:TIME (\d+), (\d+), (\d+), (\d+), (\d+), (\d+)": (set_time, None),
74
- r":?SYST(?:em)*:TIME\? 1": (nothing, get_time),
75
- r":?SYST(?:em)*:BEEP(?:er)* (\d+), (\d+(?:\.\d+)?)": (beep, None),
76
- # Command to test how the software reacts if the device is busy and blocked
77
- r"BLOCK:TIME (\d+(?:\.\d+)?)": (block, None),
78
- }
79
-
80
-
81
- def write(conn, response: str):
82
- response = f"{response}\n".encode()
83
- logger.debug(f"write: {response = }")
84
- conn.sendall(response)
85
-
86
-
87
- def read(conn) -> str:
88
- """
89
- Reads one command string from the socket, i.e. until a linefeed ('\n') is received.
90
-
91
- Returns:
92
- The command string with the linefeed stripped off.
93
- """
94
-
95
- n_total = 0
96
- buf_size = 1024 * 4
97
- command_string = bytes()
98
-
99
- try:
100
- for _ in range(100):
101
- data = conn.recv(buf_size)
102
- n = len(data)
103
- n_total += n
104
- command_string += data
105
- # if data.endswith(b'\n'):
106
- if n < buf_size:
107
- break
108
- except socket.timeout:
109
- # This timeout is caught at the caller, where the timeout is set.
110
- raise
111
-
112
- logger.info(f"read: {command_string=}")
113
-
114
- return command_string.decode().rstrip()
115
-
116
-
117
- def process_command(command_string: str) -> str:
118
- global COMMAND_ACTIONS_RESPONSES
119
- global COMMAND_PATTERNS_ACTIONS_RESPONSES
120
- global error_msg
121
-
122
- # LOGGER.debug(f"{command_string=}")
123
-
124
- try:
125
- action, response = COMMAND_ACTIONS_RESPONSES[command_string]
126
- action and action()
127
- if error_msg:
128
- return error_msg
129
- else:
130
- return response if isinstance(response, str) else response()
131
- except KeyError:
132
- # try to match with a value
133
- for key, value in COMMAND_PATTERNS_ACTIONS_RESPONSES.items():
134
- if match := re.match(key, command_string, flags=re.IGNORECASE):
135
- # LOGGER.debug(f"{match=}, {match.groups()}")
136
- action, response = value
137
- # LOGGER.debug(f"{action=}, {response=}")
138
- action and action(*match.groups())
139
- return error_msg or (response if isinstance(response, str) or response is None else response())
140
- return f"ERROR: unknown command string: {command_string}"
141
-
142
-
143
- def run_simulator(device_id: str):
144
- global error_msg
145
-
146
- logger.info("Starting the PUNA Simulator")
147
-
148
- killer = SignalCatcher()
149
-
150
- with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
151
- s.bind((HOST, PUNA_SETTINGS[device_id]["PORT"]))
152
- s.listen()
153
- s.settimeout(2.0)
154
- while True:
155
- while True:
156
- with contextlib.suppress(socket.timeout):
157
- conn, addr = s.accept()
158
- break
159
- if killer.term_signal_received:
160
- return
161
- with conn:
162
- logger.info(f"Accepted connection from {addr}")
163
- write(conn, "This is PUNA Hexapod Simulator")
164
- conn.settimeout(2.0)
165
- try:
166
- while True:
167
- error_msg = ""
168
- with contextlib.suppress(socket.timeout):
169
- data = read(conn)
170
- logger.info(f"{data = }")
171
- if data.strip() == "STOP":
172
- logger.info("Client requested to terminate...")
173
- s.close()
174
- return
175
- for cmd in data.split(";"):
176
- response = process_command(cmd.strip())
177
- if response is not None:
178
- write(conn, response)
179
- if not data:
180
- logger.info("Client closed connection, accepting new connection...")
181
- break
182
- if killer.term_signal_received:
183
- logger.info("Terminating...")
184
- s.close()
185
- return
186
- if killer.user_signal_received:
187
- if killer.signal_name == "SIGUSR1":
188
- logger.info("SIGUSR1 is not supported by this simulator")
189
- if killer.signal_name == "SIGUSR2":
190
- logger.info("SIGUSR2 is not supported by this simulator")
191
- killer.clear()
192
-
193
- except ConnectionResetError as exc:
194
- logger.info(f"ConnectionResetError: {exc}")
195
- except Exception as exc:
196
- logger.info(f"{exc.__class__.__name__} caught: {exc.args}")
197
-
198
-
199
- def send_request(device_id: str, cmd: str, type_: str = "query"):
200
- from egse.socketdevice import SocketDevice
201
-
202
- response = None
203
-
204
- hostname = PUNA_SETTINGS[device_id]["HOSTNAME"]
205
- port = PUNA_SETTINGS[device_id]["PORT"]
206
-
207
- logger.info(f"Connecting to {hostname}:{port}...")
208
- dev = SocketDevice(hostname, port)
209
- dev.connect()
210
-
211
- if type_.lower().strip() == "query":
212
- response = dev.query(cmd)
213
- elif type_.lower().strip() == "write":
214
- dev.write(cmd)
215
- else:
216
- logger.info(f"Unknown type {type_} for send_request.")
217
-
218
- dev.disconnect()
219
-
220
- return response
221
-
222
-
223
- @app.command()
224
- def start(device_id: str):
225
- run_simulator(device_id)
226
-
227
-
228
- @app.command()
229
- def status(device_id: str):
230
- response = send_request(device_id, "*IDN?")
231
- logger.info(f"{response}")
232
-
233
-
234
- @app.command()
235
- def stop(device_id: str):
236
- response = send_request(device_id, "STOP", "write")
237
- logger.info(f"{response}")
238
-
239
-
240
- @app.command()
241
- def command(device_id: str, type_: str, cmd: str):
242
- response = send_request(device_id, cmd, type_)
243
- logger.info(f"{response}")
244
-
245
-
246
- if __name__ == "__main__":
247
- logging.basicConfig(
248
- level=logging.DEBUG,
249
- format="%(asctime)s %(threadName)-12s %(levelname)-8s %(name)-12s %(module)-20s %(message)s",
250
- )
251
-
252
- app()