symetrie-hexapod 0.17.2__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.
- {symetrie_hexapod-0.17.2 → symetrie_hexapod-0.17.3}/PKG-INFO +1 -1
- {symetrie_hexapod-0.17.2 → symetrie_hexapod-0.17.3}/pyproject.toml +1 -1
- {symetrie_hexapod-0.17.2 → symetrie_hexapod-0.17.3}/src/egse/hexapod/symetrie/puna_ui.py +2 -3
- symetrie_hexapod-0.17.2/src/egse/hexapod/symetrie/puna_sim.py +0 -252
- {symetrie_hexapod-0.17.2 → symetrie_hexapod-0.17.3}/.gitignore +0 -0
- {symetrie_hexapod-0.17.2 → symetrie_hexapod-0.17.3}/README.md +0 -0
- {symetrie_hexapod-0.17.2 → symetrie_hexapod-0.17.3}/src/egse/hexapod/__init__.py +0 -0
- {symetrie_hexapod-0.17.2 → symetrie_hexapod-0.17.3}/src/egse/hexapod/symetrie/__init__.py +0 -0
- {symetrie_hexapod-0.17.2 → symetrie_hexapod-0.17.3}/src/egse/hexapod/symetrie/alpha.py +0 -0
- {symetrie_hexapod-0.17.2 → symetrie_hexapod-0.17.3}/src/egse/hexapod/symetrie/dynalpha.py +0 -0
- {symetrie_hexapod-0.17.2 → symetrie_hexapod-0.17.3}/src/egse/hexapod/symetrie/hexapod.py +0 -0
- {symetrie_hexapod-0.17.2 → symetrie_hexapod-0.17.3}/src/egse/hexapod/symetrie/hexapod_ui.py +0 -0
- {symetrie_hexapod-0.17.2 → symetrie_hexapod-0.17.3}/src/egse/hexapod/symetrie/joran.py +0 -0
- {symetrie_hexapod-0.17.2 → symetrie_hexapod-0.17.3}/src/egse/hexapod/symetrie/joran.yaml +0 -0
- {symetrie_hexapod-0.17.2 → symetrie_hexapod-0.17.3}/src/egse/hexapod/symetrie/joran_cs.py +0 -0
- {symetrie_hexapod-0.17.2 → symetrie_hexapod-0.17.3}/src/egse/hexapod/symetrie/joran_protocol.py +0 -0
- {symetrie_hexapod-0.17.2 → symetrie_hexapod-0.17.3}/src/egse/hexapod/symetrie/joran_ui.py +0 -0
- {symetrie_hexapod-0.17.2 → symetrie_hexapod-0.17.3}/src/egse/hexapod/symetrie/pmac.py +0 -0
- {symetrie_hexapod-0.17.2 → symetrie_hexapod-0.17.3}/src/egse/hexapod/symetrie/pmac_regex.py +0 -0
- {symetrie_hexapod-0.17.2 → symetrie_hexapod-0.17.3}/src/egse/hexapod/symetrie/puna.py +0 -0
- {symetrie_hexapod-0.17.2 → symetrie_hexapod-0.17.3}/src/egse/hexapod/symetrie/puna.yaml +0 -0
- {symetrie_hexapod-0.17.2 → symetrie_hexapod-0.17.3}/src/egse/hexapod/symetrie/puna_cs.py +0 -0
- {symetrie_hexapod-0.17.2 → symetrie_hexapod-0.17.3}/src/egse/hexapod/symetrie/puna_protocol.py +0 -0
- {symetrie_hexapod-0.17.2 → symetrie_hexapod-0.17.3}/src/egse/hexapod/symetrie/punaplus.py +0 -0
- {symetrie_hexapod-0.17.2 → symetrie_hexapod-0.17.3}/src/egse/hexapod/symetrie/zonda.py +0 -0
- {symetrie_hexapod-0.17.2 → symetrie_hexapod-0.17.3}/src/egse/hexapod/symetrie/zonda.yaml +0 -0
- {symetrie_hexapod-0.17.2 → symetrie_hexapod-0.17.3}/src/egse/hexapod/symetrie/zonda_cs.py +0 -0
- {symetrie_hexapod-0.17.2 → symetrie_hexapod-0.17.3}/src/egse/hexapod/symetrie/zonda_devif.py +0 -0
- {symetrie_hexapod-0.17.2 → symetrie_hexapod-0.17.3}/src/egse/hexapod/symetrie/zonda_protocol.py +0 -0
- {symetrie_hexapod-0.17.2 → symetrie_hexapod-0.17.3}/src/egse/hexapod/symetrie/zonda_ui.py +0 -0
- {symetrie_hexapod-0.17.2 → symetrie_hexapod-0.17.3}/src/symetrie_hexapod/__init__.py +0 -0
- {symetrie_hexapod-0.17.2 → symetrie_hexapod-0.17.3}/src/symetrie_hexapod/cgse_explore.py +0 -0
- {symetrie_hexapod-0.17.2 → symetrie_hexapod-0.17.3}/src/symetrie_hexapod/cgse_services.py +0 -0
- {symetrie_hexapod-0.17.2 → symetrie_hexapod-0.17.3}/src/symetrie_hexapod/settings.yaml +0 -0
|
@@ -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(
|
|
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()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{symetrie_hexapod-0.17.2 → symetrie_hexapod-0.17.3}/src/egse/hexapod/symetrie/joran_protocol.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{symetrie_hexapod-0.17.2 → symetrie_hexapod-0.17.3}/src/egse/hexapod/symetrie/puna_protocol.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{symetrie_hexapod-0.17.2 → symetrie_hexapod-0.17.3}/src/egse/hexapod/symetrie/zonda_devif.py
RENAMED
|
File without changes
|
{symetrie_hexapod-0.17.2 → symetrie_hexapod-0.17.3}/src/egse/hexapod/symetrie/zonda_protocol.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|