UC2-REST 0.2.0.17__tar.gz → 0.2.0.18__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 (36) hide show
  1. {UC2-REST-0.2.0.17 → UC2-REST-0.2.0.18}/PKG-INFO +1 -1
  2. {UC2-REST-0.2.0.17 → UC2-REST-0.2.0.18}/UC2_REST.egg-info/PKG-INFO +1 -1
  3. {UC2-REST-0.2.0.17 → UC2-REST-0.2.0.18}/uc2rest/UC2Client.py +2 -1
  4. {UC2-REST-0.2.0.17 → UC2-REST-0.2.0.18}/uc2rest/__version__.py +1 -1
  5. {UC2-REST-0.2.0.17 → UC2-REST-0.2.0.18}/uc2rest/home.py +1 -1
  6. {UC2-REST-0.2.0.17 → UC2-REST-0.2.0.18}/uc2rest/laser.py +1 -31
  7. {UC2-REST-0.2.0.17 → UC2-REST-0.2.0.18}/uc2rest/motor.py +51 -7
  8. {UC2-REST-0.2.0.17 → UC2-REST-0.2.0.18}/uc2rest/mserial.py +23 -18
  9. {UC2-REST-0.2.0.17 → UC2-REST-0.2.0.18}/uc2rest/temperature.py +8 -10
  10. {UC2-REST-0.2.0.17 → UC2-REST-0.2.0.18}/LICENSE +0 -0
  11. {UC2-REST-0.2.0.17 → UC2-REST-0.2.0.18}/README.md +0 -0
  12. {UC2-REST-0.2.0.17 → UC2-REST-0.2.0.18}/UC2_REST.egg-info/SOURCES.txt +0 -0
  13. {UC2-REST-0.2.0.17 → UC2-REST-0.2.0.18}/UC2_REST.egg-info/dependency_links.txt +0 -0
  14. {UC2-REST-0.2.0.17 → UC2-REST-0.2.0.18}/UC2_REST.egg-info/not-zip-safe +0 -0
  15. {UC2-REST-0.2.0.17 → UC2-REST-0.2.0.18}/UC2_REST.egg-info/requires.txt +0 -0
  16. {UC2-REST-0.2.0.17 → UC2-REST-0.2.0.18}/UC2_REST.egg-info/top_level.txt +0 -0
  17. {UC2-REST-0.2.0.17 → UC2-REST-0.2.0.18}/setup.cfg +0 -0
  18. {UC2-REST-0.2.0.17 → UC2-REST-0.2.0.18}/setup.py +0 -0
  19. {UC2-REST-0.2.0.17 → UC2-REST-0.2.0.18}/uc2rest/__init__.py +0 -0
  20. {UC2-REST-0.2.0.17 → UC2-REST-0.2.0.18}/uc2rest/analog.py +0 -0
  21. {UC2-REST-0.2.0.17 → UC2-REST-0.2.0.18}/uc2rest/camera.py +0 -0
  22. {UC2-REST-0.2.0.17 → UC2-REST-0.2.0.18}/uc2rest/cmdrecorder.py +0 -0
  23. {UC2-REST-0.2.0.17 → UC2-REST-0.2.0.18}/uc2rest/config.py +0 -0
  24. {UC2-REST-0.2.0.17 → UC2-REST-0.2.0.18}/uc2rest/config_.py +0 -0
  25. {UC2-REST-0.2.0.17 → UC2-REST-0.2.0.18}/uc2rest/digitalout.py +0 -0
  26. {UC2-REST-0.2.0.17 → UC2-REST-0.2.0.18}/uc2rest/galvo.py +0 -0
  27. {UC2-REST-0.2.0.17 → UC2-REST-0.2.0.18}/uc2rest/ledmatrix.py +0 -0
  28. {UC2-REST-0.2.0.17 → UC2-REST-0.2.0.18}/uc2rest/logger.py +0 -0
  29. {UC2-REST-0.2.0.17 → UC2-REST-0.2.0.18}/uc2rest/modules.py +0 -0
  30. {UC2-REST-0.2.0.17 → UC2-REST-0.2.0.18}/uc2rest/pid.py +0 -0
  31. {UC2-REST-0.2.0.17 → UC2-REST-0.2.0.18}/uc2rest/rotator.py +0 -0
  32. {UC2-REST-0.2.0.17 → UC2-REST-0.2.0.18}/uc2rest/slm.py +0 -0
  33. {UC2-REST-0.2.0.17 → UC2-REST-0.2.0.18}/uc2rest/state.py +0 -0
  34. {UC2-REST-0.2.0.17 → UC2-REST-0.2.0.18}/uc2rest/updater.py +0 -0
  35. {UC2-REST-0.2.0.17 → UC2-REST-0.2.0.18}/uc2rest/utils.py +0 -0
  36. {UC2-REST-0.2.0.17 → UC2-REST-0.2.0.18}/uc2rest/wifi.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: UC2-REST
3
- Version: 0.2.0.17
3
+ Version: 0.2.0.18
4
4
  Summary: This pacage will help you to drive the ESP32-driven microscopy control modules from UC2
5
5
  Home-page: https://github.com/openUC2/UC2-REST
6
6
  Author: Benedict Diederich
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: UC2-REST
3
- Version: 0.2.0.17
3
+ Version: 0.2.0.18
4
4
  Summary: This pacage will help you to drive the ESP32-driven microscopy control modules from UC2
5
5
  Home-page: https://github.com/openUC2/UC2-REST
6
6
  Author: Benedict Diederich
@@ -160,6 +160,7 @@ class UC2Client(object):
160
160
  # FIXME: this is not working
161
161
  url = f"http://{self.host}:{self.port}{path}"
162
162
  try:
163
+ if timeout==0: timeout=.2
163
164
  r = requests.post(url, json=payload, headers=self.headers, timeout=timeout)
164
165
  returnMessage = r.json()
165
166
  returnMessage["success"] = r.status_code==200
@@ -172,7 +173,7 @@ class UC2Client(object):
172
173
  elif self.is_serial or self.isPyScript:
173
174
  if timeout <=0:
174
175
  getReturn = False
175
- return self.serial.post_json(path, payload, getReturn=getReturn, nResponses=nResponses)
176
+ return self.serial.post_json(path, payload, getReturn=getReturn, timeout=timeout, nResponses=nResponses)
176
177
  else:
177
178
  self.logger.error("No ESP32 device is connected - check IP or Serial port!")
178
179
  return None
@@ -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.17"
9
+ __version__ = "v0.2.0.18"
10
10
  __author__ = 'Benedict Diederich'
11
11
  __author_email__ = 'benedictdied@gmail.com'
12
12
  __license__ = 'GPL v3'
@@ -78,7 +78,7 @@ class Home(object):
78
78
  {
79
79
  "stepperid": axis,
80
80
  "timeout":timeout*1000,
81
- "speed":speed,
81
+ "speed":direction*abs(speed),
82
82
  "direction":direction,
83
83
  "endposrelease":endposrelease,
84
84
  "endstoppolarity":endstoppolarity
@@ -46,7 +46,7 @@ class Laser(object):
46
46
 
47
47
  }
48
48
  #self._parent.logger.debug("Setting Laser "+str(channel)+", value: "+str(value))
49
- r = self._parent.post_json(path, payload, getReturn=is_blocking)
49
+ r = self._parent.post_json(path, payload, getReturn=is_blocking, timeout=.5)
50
50
  return r
51
51
 
52
52
  def set_laserpin(self, laserid=1, laserpin=0):
@@ -61,33 +61,3 @@ class Laser(object):
61
61
  r = self._parent.post_json(path, payload)
62
62
  return r
63
63
 
64
- def get_laserpins(self):
65
- path = '/laser_get'
66
-
67
- r = self._parent.get_json(path)
68
-
69
- if type(r) is dict:
70
- # cast laser pins
71
- if "LASER1pin" in r: r["LASER1pin"] = int(r["LASER1pin"])
72
- else: r["LASER1pin"] = 0
73
- if r.__contains__("LASER2pin"): r["LASER2pin"] = int(r["LASER2pin"])
74
- else: r["LASER2pin"] = 0
75
- if r.__contains__("LASER3pin"): r["LASER3pin"] = int(r["LASER3pin"])
76
- else: r["LASER3pin"] = 0
77
- else:
78
- r={}
79
- r["LASER1pin"] = 0
80
- r["LASER2pin"] = 0
81
- r["LASER3pin"] = 0
82
-
83
- return r
84
-
85
- def get_laserpin(self, laserid=1):
86
- path = '/laser_get'
87
-
88
- payload = {
89
- "task": path,
90
- }
91
-
92
- r = self._parent.post_json(path, payload,timeout=2)
93
- return r["LASER"+str(laserid)+"pin"]
@@ -48,14 +48,17 @@ class Motor(object):
48
48
  self.stepSizeZ = 1
49
49
  self.stepSizeA = 1
50
50
 
51
+ self.DEFAULT_ACCELERATION = 10000
52
+
51
53
  self.motorAxisOrder = [0,1,2,3] # motor axis is 1,2,3,0 => X,Y,Z,T # FIXME: Hardcoded
52
54
 
53
55
  # register a callback function for the motor status on the serial loop
54
- self._parent.serial.register_callback(self._callback_motor_status, pattern="steppers")
56
+ if hasattr(self._parent, "serial"):
57
+ self._parent.serial.register_callback(self._callback_motor_status, pattern="steppers")
55
58
 
56
59
  # move motor to wake them up #FIXME: Should not be necessary!
57
- self.move_stepper(steps=(1,1,1,1), speed=(1000,1000,1000,1000), is_absolute=(False,False,False,False))
58
- self.move_stepper(steps=(-1,-1,-1,-1), speed=(1000,1000,1000,1000), is_absolute=(False,False,False,False))
60
+ #self.move_stepper(steps=(1,1,1,1), speed=(1000,1000,1000,1000), is_absolute=(False,False,False,False))
61
+ #self.move_stepper(steps=(-1,-1,-1,-1), speed=(1000,1000,1000,1000), is_absolute=(False,False,False,False))
59
62
 
60
63
  def _callback_motor_status(self, data):
61
64
  ''' cast the json in the form:
@@ -77,7 +80,46 @@ class Motor(object):
77
80
  except Exception as e:
78
81
  print("Error in _callback_motor_status: ", e)
79
82
 
83
+ def setTrigger(self, axis="X", pin=1, offset=0, period=1):
84
+ # {"task": "/motor_act", "setTrig": {"steppers": [{"stepperid": 1, "trigPin": 1, "trigOff":0, "trigPer":1}]}}
85
+ if type(axis) is not int:
86
+ axis = self.xyztTo1230(axis)
87
+ path = "/motor_act"
88
+ payload = {
89
+ "task": path,
90
+ "setTrig":{
91
+ "steppers": [
92
+ {
93
+ "stepperid": axis,
94
+ "trigPin": pin,
95
+ "trigOff": offset,
96
+ "trigPer": period
97
+ }]
98
+ }}
99
+ r = self._parent.post_json(path, payload)
100
+ return r
101
+
102
+ # {"task": "/motor_act", "stagescan": {"nStepsLine": 100, "dStepsLine": 1, "nTriggerLine": 1, "nStepsPixel": 100, "dStepsPixel": 1, "nTriggerPixel": 1, "delayTimeStep": 10, "stopped": 0, "nFrames": 5}}"}}
103
+ def startStageScanning(self, nStepsLine=100, dStepsLine=1, nTriggerLine=1, nStepsPixel=100, dStepsPixel=1, nTriggerPixel=1, delayTimeStep=10, nFrames=5):
104
+ path = "/motor_act"
105
+ payload = {
106
+ "task": path,
107
+ "stagescan":{
108
+ "nStepsLine": nStepsLine,
109
+ "dStepsLine": dStepsLine,
110
+ "nTriggerLine": nTriggerLine,
111
+ "nStepsPixel": nStepsPixel,
112
+ "dStepsPixel": dStepsPixel,
113
+ "nTriggerPixel": nTriggerPixel,
114
+ "delayTimeStep": delayTimeStep,
115
+ "stopped": 0,
116
+ "nFrames": nFrames
117
+ }}
118
+ r = self._parent.post_json(path, payload)
119
+ return r
80
120
 
121
+ def stopStageScanning(self):
122
+ self.startStageScanning(stopped=1)
81
123
 
82
124
  def setIsCoreXY(self, isCoreXY = False):
83
125
  self.isCoreXY = isCoreXY
@@ -164,7 +206,7 @@ class Motor(object):
164
206
  # have to move only one motor to move in XY direction
165
207
  return self.move_xyza(steps=(0,steps[0], steps[1], 0), speed=(0,speed[0],speed[1],0), is_blocking=is_blocking, is_absolute=is_absolute, is_enabled=is_enabled, timeout=timeout)
166
208
  else:
167
- if len(speed)!= 2:
209
+ if type(speed)==int or len(speed)!= 2:
168
210
  speed = (speed,speed)
169
211
 
170
212
  if len(acceleration)!= 2:
@@ -339,10 +381,12 @@ class Motor(object):
339
381
  "position": int(steps[iMotor]),
340
382
  "speed": int(speed[iMotor]),
341
383
  "isabs": isAbsoluteArray[iMotor],
342
- "isaccel":0,
384
+ "isaccel":1,
343
385
  "isen": is_enabled}
344
386
  if acceleration[iMotor] is not None:
345
387
  motorProp["accel"] = int(acceleration[iMotor])
388
+ else:
389
+ motorProp["accel"] = self.DEFAULT_ACCELERATION
346
390
  motorPropList.append(motorProp)
347
391
 
348
392
  path = "/motor_act"
@@ -478,7 +522,7 @@ class Motor(object):
478
522
  r = self._parent.post_json(path, payload)
479
523
  return r
480
524
 
481
- def get_position(self, axis=None, timeout=1):
525
+ def get_position(self, axis=None, timeout=.2):
482
526
  # pulls all current positions from the stepper controller
483
527
  path = "/motor_get"
484
528
  payload = {
@@ -489,7 +533,7 @@ class Motor(object):
489
533
  _physicalStepSizes = np.array((self.stepSizeA, self.stepSizeX, self.stepSizeY, self.stepSizeZ))
490
534
 
491
535
  # this may be an asynchronous call.. #FIXME!
492
- r = self._parent.post_json(path, payload, getReturn = True, nResponses=1)
536
+ r = self._parent.post_json(path, payload, getReturn = True, nResponses=1, timeout=timeout)
493
537
  if "motor" in r:
494
538
  for index, istepper in enumerate(r["motor"]["steppers"]):
495
539
  _position[istepper["stepperid"]]=istepper["position"]*_physicalStepSizes[self.motorAxisOrder[index]]
@@ -9,7 +9,7 @@ class Serial:
9
9
  def __init__(self, port, baudrate=115200, timeout=5,
10
10
  identity="UC2_Feather", parent=None, DEBUG=False):
11
11
 
12
- self.ser = None
12
+ self.serialdevice = None
13
13
  self.serialport = port
14
14
  self.baudrate = baudrate
15
15
  self.timeout = timeout
@@ -42,7 +42,7 @@ class Serial:
42
42
 
43
43
  # initialize serial connection
44
44
  self.thread = None
45
- self.ser = self.openDevice(port, baudrate)
45
+ self.serialdevice= self.openDevice(port, baudrate)
46
46
 
47
47
  def breakCurrentCommunication(self):
48
48
  self.resetLastCommand = True
@@ -66,7 +66,7 @@ class Serial:
66
66
  def openDevice(self, port=None, baud_rate=115200):
67
67
  try: # try to close an eventually open serial connection
68
68
  if str(type(self.ser)) != "<class 'uc2rest.mserial.MockSerial'>":
69
- self.ser.close()
69
+ self.serialdevice.close()
70
70
  except: pass
71
71
 
72
72
  try:
@@ -104,6 +104,12 @@ class Serial:
104
104
  return ser
105
105
 
106
106
  def findCorrectSerialDevice(self):
107
+ '''
108
+ This function tries to find the correct serial device from the list of available ports
109
+ It also checks if the firmware is correct by sending a command and checking for the correct response
110
+ It may be that - depending on the OS - the response may be corrupted
111
+ If this is the case try to hard-code the COM port into the config JSON file
112
+ '''
107
113
  _available_ports = serial.tools.list_ports.comports(include_links=False)
108
114
  ports_to_check = ["COM", "/dev/tt", "/dev/a", "/dev/cu.SLA", "/dev/cu.wchusb"]
109
115
  descriptions_to_check = ["CH340", "CP2102"]
@@ -148,7 +154,7 @@ class Serial:
148
154
  ser.write(json.dumps(payload).encode('utf-8'))
149
155
  ser.write(b'\n')
150
156
  # iterate a few times in case the debug mode on the ESP32 is turned on and it sends additional lines
151
- for i in range(100):
157
+ for i in range(500):
152
158
  # if we just want to send but not even wait for a response
153
159
  mReadline = ser.readline()
154
160
  if self.DEBUG: self._logger.debug("[checkFirmware]: "+str(mReadline))
@@ -173,9 +179,9 @@ class Serial:
173
179
  # Check if the last command went through successfully
174
180
  #if not self.command_queue.empty() and not reading_json:
175
181
  # currentIdentifier, command = self.command_queue.get()
176
-
182
+
177
183
  # device not ready yet
178
- if self.ser is None:
184
+ if self.serialdevice is None:
179
185
  self.is_connected = False
180
186
  continue
181
187
  else:
@@ -183,11 +189,9 @@ class Serial:
183
189
 
184
190
  # if we just want to send but not even wait for a response
185
191
  try:
186
- mReadline = self.ser.readline()
192
+ mReadline = self.serialdevice.readline()
187
193
  except Exception as e:
188
194
  self._logger.error("Failed to read the line in serial: "+str(e))
189
- self.is_connected = False
190
- break
191
195
  try:
192
196
  line = mReadline.decode('utf-8').strip()
193
197
  if self.DEBUG and line!="": self._logger.debug("[ProcessLines]:"+str(line))
@@ -212,7 +216,7 @@ class Serial:
212
216
 
213
217
  except Exception as e:
214
218
  self._logger.error("Failed to load the json from serial %s" % buffer)
215
- self._logger.error("Error: %s", e)
219
+ self._logger.error("Error: %s" % str(e))
216
220
  json_response = {}
217
221
 
218
222
  with self.lock:
@@ -235,7 +239,7 @@ class Serial:
235
239
  message = json.dumps(message)
236
240
  return self.sendMessage(message, nResponses=0, timeout=timeout)
237
241
 
238
- def post_json(self, path, payload, getReturn=True, nResponses=1, timeout=1):
242
+ def post_json(self, path, payload, getReturn=True, nResponses=1, timeout=100):
239
243
  """Make an HTTP POST request and return the JSON response"""
240
244
  if payload is None:
241
245
  payload = {}
@@ -290,16 +294,14 @@ class Serial:
290
294
  try:
291
295
  json_command = json.dumps(command)+"\n"
292
296
  with self.lock:
293
- t0 = time.time()
294
- self.ser.flush()
297
+ self.serialdevice.flush()
295
298
  self._logger.debug("[SendMessage]: "+str(json_command))
296
- self.ser.write(json_command.encode('utf-8') )
297
- self._logger.debug("[SendMessage] took: "+str(time.time()-t0))
299
+ self.serialdevice.write(json_command.encode('utf-8') )
298
300
  except Exception as e:
299
301
  if self.DEBUG: self._logger.error(e)
300
302
  return "Failed to Send"
301
303
  self.commands[identifier]=command
302
- if nResponses <= 0 or not self.is_connected or not type(self.ser.BAUDRATES) is tuple:
304
+ if nResponses <= 0 or not self.is_connected or not type(self.serialdevice.BAUDRATES) is tuple:
303
305
  return identifier
304
306
  while self.running:
305
307
  time.sleep(0.002)
@@ -320,7 +322,7 @@ class Serial:
320
322
  def stop(self):
321
323
  self.running = False
322
324
  self.thread.join()
323
- self.ser.close()
325
+ self.serialdevice.close()
324
326
 
325
327
  def closeSerial(self):
326
328
  self.stop()
@@ -329,7 +331,7 @@ class Serial:
329
331
  def reconnect(self):
330
332
  self.running = False
331
333
  try:
332
- self.ser.close()
334
+ self.serialdevice.close()
333
335
  except:
334
336
  pass
335
337
  self.serialdevice = self.openDevice(port = self.serialport, baud_rate = self.baudrate)
@@ -388,6 +390,9 @@ class MockSerial:
388
390
  self.manufacturer = "UC2Mock"
389
391
  self.BAUDRATES = -1
390
392
 
393
+ def flush(self):
394
+ pass
395
+
391
396
  def isOpen(self):
392
397
  return self.is_open
393
398
 
@@ -1,8 +1,8 @@
1
1
  class Temperature(object):
2
-
2
+
3
3
  def __init__(self, parent):
4
4
  self._parent = parent
5
-
5
+
6
6
  '''
7
7
  ##############################################################################################################################
8
8
  Temperature Controllers
@@ -12,9 +12,9 @@ class Temperature(object):
12
12
  def stop_heating(self):
13
13
  r = self.set_temperature(active=0)
14
14
  return r
15
-
16
- def set_temperature(self, active=1, Kp=1000, Ki=0.1, Kd=0.1, target=37, timeout=600000, updaterate=1000):
17
- # {"task": "/heat_act", "active":1, "Kp":1000, "Ki":0.1, "Kd":0.1, "target":37, "timeout":600000, "updaterate":1000}
15
+
16
+ def set_temperature(self, active=1, Kp=1000, Ki=0.1, Kd=0.1, target=37, timeout=600000000, updaterate=1000):
17
+ # {"task": "/heat_act", "active":1, "Kp":1000, "Ki":0.1, "Kd":0.1, "target":37, "timeout":60000000, "updaterate":1000}
18
18
  path = "/heat_act"
19
19
  payload = {
20
20
  "task": path,
@@ -28,19 +28,19 @@ class Temperature(object):
28
28
  }
29
29
  r = self._parent.post_json(path, payload, getReturn=False)
30
30
  return r
31
-
31
+
32
32
  def get_temperature(self, timeout=0.5):
33
33
  path = "/heat_get"
34
34
  r = self._parent.get_json(path, timeout=timeout)
35
35
  try:
36
36
  r = r["heat"]
37
37
  except:
38
- r = 9999
38
+ r = -273.15
39
39
  return r
40
40
 
41
41
 
42
42
  if __name__ == "__main__":
43
-
43
+
44
44
  #%%
45
45
  import uc2rest
46
46
  import time
@@ -52,5 +52,3 @@ if __name__ == "__main__":
52
52
  time.sleep(1)
53
53
  ESP32.temperature.stop_heating()
54
54
  ESP32.close()
55
-
56
-
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes