UC2-REST 0.2.0.32__tar.gz → 0.2.0.34__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.
- {uc2_rest-0.2.0.32 → uc2_rest-0.2.0.34}/PKG-INFO +1 -1
- {uc2_rest-0.2.0.32 → uc2_rest-0.2.0.34}/UC2_REST.egg-info/PKG-INFO +1 -1
- {uc2_rest-0.2.0.32 → uc2_rest-0.2.0.34}/UC2_REST.egg-info/SOURCES.txt +1 -0
- {uc2_rest-0.2.0.32 → uc2_rest-0.2.0.34}/uc2rest/UC2Client.py +28 -51
- {uc2_rest-0.2.0.32 → uc2_rest-0.2.0.34}/uc2rest/__version__.py +1 -1
- {uc2_rest-0.2.0.32 → uc2_rest-0.2.0.34}/uc2rest/can.py +20 -6
- uc2_rest-0.2.0.34/uc2rest/canota.py +588 -0
- uc2_rest-0.2.0.34/uc2rest/fan.py +86 -0
- uc2_rest-0.2.0.34/uc2rest/galvo.py +312 -0
- {uc2_rest-0.2.0.32 → uc2_rest-0.2.0.34}/uc2rest/home.py +44 -3
- {uc2_rest-0.2.0.32 → uc2_rest-0.2.0.34}/uc2rest/ledmatrix.py +1 -1
- {uc2_rest-0.2.0.32 → uc2_rest-0.2.0.34}/uc2rest/motor.py +144 -25
- {uc2_rest-0.2.0.32 → uc2_rest-0.2.0.34}/uc2rest/mserial.py +127 -61
- {uc2_rest-0.2.0.32 → uc2_rest-0.2.0.34}/uc2rest/objective.py +16 -9
- {uc2_rest-0.2.0.32 → uc2_rest-0.2.0.34}/uc2rest/rotator.py +1 -1
- uc2_rest-0.2.0.34/uc2rest/state.py +222 -0
- uc2_rest-0.2.0.34/uc2rest/wifi.py +44 -0
- uc2_rest-0.2.0.32/uc2rest/canota.py +0 -256
- uc2_rest-0.2.0.32/uc2rest/galvo.py +0 -116
- uc2_rest-0.2.0.32/uc2rest/state.py +0 -99
- uc2_rest-0.2.0.32/uc2rest/wifi.py +0 -98
- {uc2_rest-0.2.0.32 → uc2_rest-0.2.0.34}/LICENSE +0 -0
- {uc2_rest-0.2.0.32 → uc2_rest-0.2.0.34}/README.md +0 -0
- {uc2_rest-0.2.0.32 → uc2_rest-0.2.0.34}/UC2_REST.egg-info/dependency_links.txt +0 -0
- {uc2_rest-0.2.0.32 → uc2_rest-0.2.0.34}/UC2_REST.egg-info/not-zip-safe +0 -0
- {uc2_rest-0.2.0.32 → uc2_rest-0.2.0.34}/UC2_REST.egg-info/requires.txt +0 -0
- {uc2_rest-0.2.0.32 → uc2_rest-0.2.0.34}/UC2_REST.egg-info/top_level.txt +0 -0
- {uc2_rest-0.2.0.32 → uc2_rest-0.2.0.34}/setup.cfg +0 -0
- {uc2_rest-0.2.0.32 → uc2_rest-0.2.0.34}/setup.py +0 -0
- {uc2_rest-0.2.0.32 → uc2_rest-0.2.0.34}/uc2rest/MockSerial.py +0 -0
- {uc2_rest-0.2.0.32 → uc2_rest-0.2.0.34}/uc2rest/__init__.py +0 -0
- {uc2_rest-0.2.0.32 → uc2_rest-0.2.0.34}/uc2rest/analog.py +0 -0
- {uc2_rest-0.2.0.32 → uc2_rest-0.2.0.34}/uc2rest/camera.py +0 -0
- {uc2_rest-0.2.0.32 → uc2_rest-0.2.0.34}/uc2rest/camera_trigger.py +0 -0
- {uc2_rest-0.2.0.32 → uc2_rest-0.2.0.34}/uc2rest/cmdrecorder.py +0 -0
- {uc2_rest-0.2.0.32 → uc2_rest-0.2.0.34}/uc2rest/digitalin.py +0 -0
- {uc2_rest-0.2.0.32 → uc2_rest-0.2.0.34}/uc2rest/digitalout.py +0 -0
- {uc2_rest-0.2.0.32 → uc2_rest-0.2.0.34}/uc2rest/gripper.py +0 -0
- {uc2_rest-0.2.0.32 → uc2_rest-0.2.0.34}/uc2rest/laser.py +0 -0
- {uc2_rest-0.2.0.32 → uc2_rest-0.2.0.34}/uc2rest/lcddisplay.py +0 -0
- {uc2_rest-0.2.0.32 → uc2_rest-0.2.0.34}/uc2rest/logger.py +0 -0
- {uc2_rest-0.2.0.32 → uc2_rest-0.2.0.34}/uc2rest/message.py +0 -0
- {uc2_rest-0.2.0.32 → uc2_rest-0.2.0.34}/uc2rest/modules.py +0 -0
- {uc2_rest-0.2.0.32 → uc2_rest-0.2.0.34}/uc2rest/motor_config.py +0 -0
- {uc2_rest-0.2.0.32 → uc2_rest-0.2.0.34}/uc2rest/pid.py +0 -0
- {uc2_rest-0.2.0.32 → uc2_rest-0.2.0.34}/uc2rest/slm.py +0 -0
- {uc2_rest-0.2.0.32 → uc2_rest-0.2.0.34}/uc2rest/temperature.py +0 -0
- {uc2_rest-0.2.0.32 → uc2_rest-0.2.0.34}/uc2rest/utils.py +0 -0
|
@@ -26,22 +26,24 @@ from .rotator import Rotator
|
|
|
26
26
|
from .logger import Logger
|
|
27
27
|
from .cmdrecorder import cmdRecorder
|
|
28
28
|
from .temperature import Temperature
|
|
29
|
+
from .fan import Fan
|
|
29
30
|
from .message import Message
|
|
30
31
|
from .can import CAN
|
|
31
32
|
from .canota import CANOTA
|
|
32
33
|
from .camera_trigger import CameraTrigger
|
|
34
|
+
|
|
35
|
+
# requests is no longer used for direct ESP communication (serial-only).
|
|
36
|
+
# Kept as optional import for other modules that may need HTTP (e.g. firmware downloads).
|
|
33
37
|
try:
|
|
34
38
|
import requests
|
|
35
|
-
except:
|
|
36
|
-
|
|
39
|
+
except Exception:
|
|
40
|
+
requests = None
|
|
37
41
|
|
|
38
42
|
class UC2Client(object):
|
|
39
|
-
# headers = {'ESP32-version': '*'}
|
|
40
43
|
headers={"Content-Type":"application/json"}
|
|
41
44
|
getmessage = ""
|
|
42
45
|
is_connected = False
|
|
43
46
|
|
|
44
|
-
is_wifi = False
|
|
45
47
|
is_serial = False
|
|
46
48
|
BAUDRATE = 115200
|
|
47
49
|
|
|
@@ -52,12 +54,13 @@ class UC2Client(object):
|
|
|
52
54
|
This client connects to the UC2-REST microcontroller that can be found here
|
|
53
55
|
https://github.com/openUC2/UC2-REST
|
|
54
56
|
|
|
57
|
+
Communication is via USB/serial only.
|
|
58
|
+
The host/port parameters are deprecated and will be ignored.
|
|
59
|
+
|
|
55
60
|
generally speaking you send/receive JSON documents that will cause an:
|
|
56
61
|
1. action => "/XXX_act"
|
|
57
62
|
2. getting => "/XXX_get"
|
|
58
63
|
3. setting => "/XXX_set"
|
|
59
|
-
|
|
60
|
-
you can send commands through wifi/http or usb/serial
|
|
61
64
|
'''
|
|
62
65
|
if True: #logger is None:
|
|
63
66
|
self.logger = Logger()
|
|
@@ -67,28 +70,27 @@ class UC2Client(object):
|
|
|
67
70
|
# perhaps we are in the browser?
|
|
68
71
|
self.isPyScript = isPyScript
|
|
69
72
|
|
|
70
|
-
#
|
|
73
|
+
# Deprecation notice for WiFi mode
|
|
74
|
+
if host is not None and serialport is None and SerialManager is None:
|
|
75
|
+
self.logger.warning(
|
|
76
|
+
"WiFi/HTTP communication has been removed. "
|
|
77
|
+
"Please use serialport= instead. Ignoring host parameter."
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
# initialize communication channel (serial only)
|
|
71
81
|
if serialport is not None:
|
|
72
82
|
# use USB connection
|
|
73
83
|
self.serial = Serial(serialport, baudrate, parent=self, identity=identity, DEBUG=DEBUG, skipFirmwareCheck=skipFirmwareCheck)
|
|
74
84
|
self.is_serial = True
|
|
75
85
|
self.is_connected = self.serial.is_connected
|
|
76
86
|
self.serial.DEBUG = DEBUG
|
|
77
|
-
elif host is not None:
|
|
78
|
-
# use client in wireless mode
|
|
79
|
-
self.is_wifi = True
|
|
80
|
-
self.host = host
|
|
81
|
-
self.port = port
|
|
82
|
-
|
|
83
|
-
# check if host is up
|
|
84
|
-
self.logger.debug(f"Connecting to microscope {self.host}:{self.port}")
|
|
85
|
-
#self.is_connected = self.isConnected()
|
|
86
87
|
elif SerialManager is not None:
|
|
87
|
-
# we are trying to access the controller from
|
|
88
|
+
# we are trying to access the controller from a web browser
|
|
88
89
|
self.serial = SerialManagerWrapper(SerialManager, parent=self)
|
|
89
90
|
self.isPyScript = True
|
|
91
|
+
self.is_serial = True
|
|
90
92
|
else:
|
|
91
|
-
self.logger.error("No ESP32 device is connected -
|
|
93
|
+
self.logger.error("No ESP32 device is connected - please provide a serialport!")
|
|
92
94
|
|
|
93
95
|
|
|
94
96
|
# import libraries depending on API version
|
|
@@ -130,8 +132,8 @@ class UC2Client(object):
|
|
|
130
132
|
# initialize temperature
|
|
131
133
|
self.temperature = Temperature(self)
|
|
132
134
|
|
|
133
|
-
# initialize
|
|
134
|
-
self.
|
|
135
|
+
# initialize fan controller
|
|
136
|
+
self.fan = Fan(self)
|
|
135
137
|
|
|
136
138
|
# initialize galvo
|
|
137
139
|
self.galvo = Galvo(self)
|
|
@@ -164,42 +166,17 @@ class UC2Client(object):
|
|
|
164
166
|
self.modules = Modules(parent=self)
|
|
165
167
|
|
|
166
168
|
def post_json(self, path, payload, getReturn=True, nResponses=1, timeout=1):
|
|
167
|
-
if
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
try:
|
|
171
|
-
if timeout==0: timeout=.2
|
|
172
|
-
r = requests.post(url, json=payload, headers=self.headers, timeout=timeout)
|
|
173
|
-
returnMessage = r.json()
|
|
174
|
-
returnMessage["success"] = r.status_code==200
|
|
175
|
-
except Exception as e:
|
|
176
|
-
print(e)
|
|
177
|
-
returnMessage = {}
|
|
178
|
-
returnMessage["error"] = str(e)
|
|
179
|
-
returnMessage["success"] = 0
|
|
180
|
-
return returnMessage
|
|
181
|
-
elif self.is_serial or self.isPyScript:
|
|
182
|
-
if timeout <=0:
|
|
183
|
-
getReturn = False
|
|
184
|
-
return self.serial.post_json(path, payload, getReturn=getReturn, nResponses=nResponses, timeout=timeout)
|
|
185
|
-
else:
|
|
186
|
-
self.logger.error("No ESP32 device is connected - check IP or Serial port!")
|
|
187
|
-
return None
|
|
169
|
+
if timeout <=0:
|
|
170
|
+
getReturn = False
|
|
171
|
+
return self.serial.post_json(path, payload, getReturn=getReturn, nResponses=nResponses, timeout=timeout)
|
|
188
172
|
|
|
189
173
|
def get_json(self, path, getReturn=True, timeout=1):
|
|
190
|
-
if self.
|
|
191
|
-
|
|
192
|
-
url = f"http://{self.host}:{self.port}{path}"
|
|
193
|
-
r = requests.get(url, headers=self.headers, timeout=timeout)
|
|
194
|
-
return r.json()
|
|
195
|
-
elif self.is_serial or self.isPyScript:
|
|
196
|
-
# timeout is not used anymore
|
|
197
|
-
if timeout <=0:
|
|
174
|
+
if self.is_serial or self.isPyScript:
|
|
175
|
+
if timeout <= 0:
|
|
198
176
|
getReturn = False
|
|
199
177
|
return self.serial.post_json(path, payload=None, getReturn=getReturn, nResponses=1, timeout=timeout)
|
|
200
|
-
#return self.serial.read_json()<
|
|
201
178
|
else:
|
|
202
|
-
self.logger.error("No ESP32 device is connected -
|
|
179
|
+
self.logger.error("No ESP32 device is connected - serial not initialized!")
|
|
203
180
|
return None
|
|
204
181
|
|
|
205
182
|
def setDebugging(self, debug=False):
|
|
@@ -6,7 +6,7 @@ __version__.py
|
|
|
6
6
|
|
|
7
7
|
__title__ = 'UC2-REST'
|
|
8
8
|
__description__ = 'This pacage will help you to drive the ESP32-driven microscopy control modules from UC2'
|
|
9
|
-
__version__ = "v0.2.0.
|
|
9
|
+
__version__ = "v0.2.0.34"
|
|
10
10
|
__author__ = 'Benedict Diederich'
|
|
11
11
|
__author_email__ = 'benedictdied@gmail.com'
|
|
12
12
|
__license__ = 'GPL v3'
|
|
@@ -57,15 +57,29 @@ class CAN(object):
|
|
|
57
57
|
"""Register a callback function for a specific key."""
|
|
58
58
|
self._callbackPerKey[key] = callbackfct
|
|
59
59
|
|
|
60
|
+
def get_can_ids(self):
|
|
61
|
+
"""Return CAN node IDs from the latest scan (e.g. for OTA flashing)."""
|
|
62
|
+
return [entry.get("canId") for entry in self.scanResults
|
|
63
|
+
if entry.get("canId") is not None]
|
|
64
|
+
|
|
60
65
|
def reboot_remote(self, qid=1, can_address=0, isBlocking=False, timeout=2):
|
|
61
66
|
"""
|
|
62
|
-
|
|
67
|
+
Reboot a CAN device.
|
|
63
68
|
|
|
64
|
-
|
|
69
|
+
- ``can_address == 0`` reboots the master (this ESP32) itself.
|
|
70
|
+
- ``can_address in 1..127`` reboots a remote slave by SDO-writing 1
|
|
71
|
+
to OD index 0x2507 sub 0 on the target node. The slave's
|
|
72
|
+
CO_tmr_task observes the write and calls ESP.restart() ~200 ms
|
|
73
|
+
later.
|
|
74
|
+
|
|
75
|
+
:param qid: Query ID for the CAN command (unused by firmware, kept
|
|
76
|
+
for API compatibility)
|
|
77
|
+
:param can_address: 0 = master, 1..127 = remote slave nodeId
|
|
65
78
|
:param isBlocking: If True, wait for response
|
|
66
79
|
:param timeout: Timeout for the command in seconds
|
|
67
|
-
:
|
|
68
|
-
|
|
80
|
+
:return: Response from the device, e.g.
|
|
81
|
+
``{"status":"ok","nodeId":11}`` or
|
|
82
|
+
``{"status":"error","error":"SDO write failed","nodeId":11}``.
|
|
69
83
|
"""
|
|
70
84
|
path = "/can_act"
|
|
71
85
|
payload = {
|
|
@@ -98,7 +112,7 @@ class CAN(object):
|
|
|
98
112
|
"count": 2
|
|
99
113
|
}
|
|
100
114
|
"""
|
|
101
|
-
path = "/can_act"
|
|
115
|
+
path = "/can_act" # {"task":"/can_act", "scan": true}
|
|
102
116
|
payload = {
|
|
103
117
|
"task": path,
|
|
104
118
|
"scan": True,
|
|
@@ -109,7 +123,7 @@ class CAN(object):
|
|
|
109
123
|
payload,
|
|
110
124
|
getReturn=True,
|
|
111
125
|
timeout=timeout,
|
|
112
|
-
nResponses=
|
|
126
|
+
nResponses=1
|
|
113
127
|
)
|
|
114
128
|
|
|
115
129
|
def get_available_devices(self, timeout=2):
|