UC2-REST 0.2.0.9__tar.gz → 0.2.0.12__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. {UC2 REST-0.2.0.9 → UC2 REST-0.2.0.12}/PKG-INFO +1 -1
  2. {UC2 REST-0.2.0.9 → UC2 REST-0.2.0.12}/UC2_REST.egg-info/PKG-INFO +1 -1
  3. {UC2 REST-0.2.0.9 → UC2 REST-0.2.0.12}/UC2_REST.egg-info/SOURCES.txt +1 -0
  4. {UC2 REST-0.2.0.9 → UC2 REST-0.2.0.12}/uc2rest/UC2Client.py +38 -20
  5. UC2 REST-0.2.0.12/uc2rest/__init__.py +6 -0
  6. {UC2 REST-0.2.0.9 → UC2 REST-0.2.0.12}/uc2rest/__version__.py +1 -1
  7. {UC2 REST-0.2.0.9 → UC2 REST-0.2.0.12}/uc2rest/laser.py +1 -5
  8. {UC2 REST-0.2.0.9 → UC2 REST-0.2.0.12}/uc2rest/ledmatrix.py +3 -5
  9. {UC2 REST-0.2.0.9 → UC2 REST-0.2.0.12}/uc2rest/modules.py +4 -6
  10. {UC2 REST-0.2.0.9 → UC2 REST-0.2.0.12}/uc2rest/motor.py +86 -56
  11. {UC2 REST-0.2.0.9 → UC2 REST-0.2.0.12}/uc2rest/mserial.py +75 -3
  12. {UC2 REST-0.2.0.9 → UC2 REST-0.2.0.12}/uc2rest/state.py +1 -4
  13. UC2 REST-0.2.0.12/uc2rest/utils.py +17 -0
  14. UC2 REST-0.2.0.9/uc2rest/__init__.py +0 -3
  15. {UC2 REST-0.2.0.9 → UC2 REST-0.2.0.12}/LICENSE +0 -0
  16. {UC2 REST-0.2.0.9 → UC2 REST-0.2.0.12}/README.md +0 -0
  17. {UC2 REST-0.2.0.9 → UC2 REST-0.2.0.12}/UC2_REST.egg-info/dependency_links.txt +0 -0
  18. {UC2 REST-0.2.0.9 → UC2 REST-0.2.0.12}/UC2_REST.egg-info/not-zip-safe +0 -0
  19. {UC2 REST-0.2.0.9 → UC2 REST-0.2.0.12}/UC2_REST.egg-info/requires.txt +0 -0
  20. {UC2 REST-0.2.0.9 → UC2 REST-0.2.0.12}/UC2_REST.egg-info/top_level.txt +0 -0
  21. {UC2 REST-0.2.0.9 → UC2 REST-0.2.0.12}/setup.cfg +0 -0
  22. {UC2 REST-0.2.0.9 → UC2 REST-0.2.0.12}/setup.py +0 -0
  23. {UC2 REST-0.2.0.9 → UC2 REST-0.2.0.12}/uc2rest/analog.py +0 -0
  24. {UC2 REST-0.2.0.9 → UC2 REST-0.2.0.12}/uc2rest/camera.py +0 -0
  25. {UC2 REST-0.2.0.9 → UC2 REST-0.2.0.12}/uc2rest/config.py +0 -0
  26. {UC2 REST-0.2.0.9 → UC2 REST-0.2.0.12}/uc2rest/config_.py +0 -0
  27. {UC2 REST-0.2.0.9 → UC2 REST-0.2.0.12}/uc2rest/digitalout.py +0 -0
  28. {UC2 REST-0.2.0.9 → UC2 REST-0.2.0.12}/uc2rest/galvo.py +0 -0
  29. {UC2 REST-0.2.0.9 → UC2 REST-0.2.0.12}/uc2rest/home.py +0 -0
  30. {UC2 REST-0.2.0.9 → UC2 REST-0.2.0.12}/uc2rest/logger.py +0 -0
  31. {UC2 REST-0.2.0.9 → UC2 REST-0.2.0.12}/uc2rest/pid.py +0 -0
  32. {UC2 REST-0.2.0.9 → UC2 REST-0.2.0.12}/uc2rest/slm.py +0 -0
  33. {UC2 REST-0.2.0.9 → UC2 REST-0.2.0.12}/uc2rest/updater.py +0 -0
  34. {UC2 REST-0.2.0.9 → UC2 REST-0.2.0.12}/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.9
3
+ Version: 0.2.0.12
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.9
3
+ Version: 0.2.0.12
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
@@ -27,4 +27,5 @@ uc2rest/pid.py
27
27
  uc2rest/slm.py
28
28
  uc2rest/state.py
29
29
  uc2rest/updater.py
30
+ uc2rest/utils.py
30
31
  uc2rest/wifi.py
@@ -6,15 +6,20 @@ Simple client code for the ESP32 in Python
6
6
  Copyright 2021 Benedict Diederich, released under LGPL 3.0 or later
7
7
  """
8
8
  from .mserial import Serial
9
+ from .mserial import SerialManagerWrapper
10
+
9
11
  try:
10
- from imswitch.imcommon.model import initLogger
12
+ from .imswitch.imcommon.model import initLogger
11
13
  IS_IMSWITCH = True
12
14
  except:
13
15
  print("No imswitch available")
14
16
  from .logger import Logger
15
17
  IS_IMSWITCH = False
16
18
 
17
- import requests
19
+ try:
20
+ import requests
21
+ except:
22
+ print("No requests available - running on pyscript?")
18
23
 
19
24
  class UC2Client(object):
20
25
  # headers = {'ESP32-version': '*'}
@@ -28,7 +33,7 @@ class UC2Client(object):
28
33
  # BAUDRATE = 500000
29
34
  BAUDRATE = 115200
30
35
 
31
- def __init__(self, host=None, port=31950, serialport=None, identity="UC2_Feather", baudrate=BAUDRATE, NLeds=64, DEBUG=False):
36
+ def __init__(self, host=None, port=31950, serialport=None, identity="UC2_Feather", baudrate=BAUDRATE, NLeds=64, SerialManager=None, DEBUG=False):
32
37
  '''
33
38
  This client connects to the UC2-REST microcontroller that can be found here
34
39
  https://github.com/openUC2/UC2-REST
@@ -48,6 +53,7 @@ class UC2Client(object):
48
53
  self.logger = Logger()
49
54
  # set default APIVersion
50
55
  self.APIVersion = 2
56
+ self.isPyScript = False
51
57
 
52
58
  # initialize communication channel (# connect to wifi or usb)
53
59
  if serialport is not None:
@@ -64,10 +70,14 @@ class UC2Client(object):
64
70
 
65
71
  # check if host is up
66
72
  self.logger.debug(f"Connecting to microscope {self.host}:{self.port}")
67
- self.is_connected = self.isConnected()
73
+ #self.is_connected = self.isConnected()
74
+ elif SerialManager is not None:
75
+ # we are trying to access the controller from .a web browser
76
+ self.serial = SerialManagerWrapper(SerialManager, parent=self)
77
+ self.isPyScript = True
68
78
  else:
69
79
  self.logger.error("No ESP32 device is connected - check IP or Serial port!")
70
-
80
+
71
81
  # import libraries depending on API version
72
82
  if self.APIVersion == 1:
73
83
  self.logger.debug("Using API version 1")
@@ -93,7 +103,7 @@ class UC2Client(object):
93
103
  from .wifi import Wifi
94
104
  from .camera import Camera
95
105
  from .analog import Analog
96
- from .updater import updater
106
+ if not self.isPyScript: from .updater import updater
97
107
  from .modules import Modules
98
108
  from .digitalout import DigitalOut
99
109
 
@@ -103,10 +113,12 @@ class UC2Client(object):
103
113
 
104
114
  # initialize state
105
115
  self.state = State(self)
106
- self.state.get_state()
107
-
116
+ if not self.isPyScript:
117
+ state = self.state.get_state()
118
+
108
119
  # initialize config
109
- self.config = config(self)
120
+ if not self.isPyScript:
121
+ self.config = config(self)
110
122
 
111
123
  # initialize LED matrix
112
124
  self.led = LedMatrix(self, NLeds=NLeds)
@@ -139,11 +151,15 @@ class UC2Client(object):
139
151
  self.digitalout = DigitalOut(self)
140
152
 
141
153
  # initialize config
142
- self.config = config(self)
143
- self.pinConfig = self.config.loadConfigDevice()
154
+ if not self.isPyScript:
155
+ self.config = config(self)
156
+ try: self.pinConfig = self.config.loadConfigDevice()
157
+ except: self.pinConfig = None
144
158
 
145
159
  # initialize updater
146
- self.updater = updater(parent=self)
160
+ if not self.isPyScript:
161
+ try: self.updater = updater(parent=self)
162
+ except: self.updater = None
147
163
 
148
164
  # initialize module controller
149
165
  self.modules = Modules(parent=self)
@@ -152,23 +168,25 @@ class UC2Client(object):
152
168
  if self.is_wifi:
153
169
  # FIXME: this is not working
154
170
  url = f"http://{self.host}:{self.port}{path}"
155
- r = requests.post(url, json=payload, headers=self.headers)
156
- return r.json()
157
- elif self.is_serial:
171
+ r = requests.post(url, json=payload, headers=self.headers, timeout=timeout)
172
+ returnMessage = r.json()
173
+ returnMessage["success"] = r.status_code==200
174
+ return returnMessage
175
+ elif self.is_serial or self.isPyScript:
158
176
  return self.serial.post_json(path, payload, getReturn=getReturn, timeout=timeout)
159
177
  else:
160
178
  self.logger.error("No ESP32 device is connected - check IP or Serial port!")
161
179
  return None
162
180
 
163
- def get_json(self, path, timeout=1):
181
+ def get_json(self, path, getReturn=False, timeout=1):
164
182
  if self.is_wifi:
165
183
  # FIXME: this is not working
166
184
  url = f"http://{self.host}:{self.port}{path}"
167
- r = requests.get(url, headers=self.headers)
185
+ r = requests.get(url, headers=self.headers, timeout=timeout)
168
186
  return r.json()
169
- elif self.is_serial:
170
- self.serial.get_json(path)
171
- return self.serial.read_json()
187
+ elif self.is_serial or self.isPyScript:
188
+ return self.serial.get_json(path)
189
+ #return self.serial.read_json()
172
190
  else:
173
191
  self.logger.error("No ESP32 device is connected - check IP or Serial port!")
174
192
  return None
@@ -0,0 +1,6 @@
1
+ from .config import *
2
+ from .UC2Client import *
3
+ try:
4
+ from .updater import *
5
+ except:
6
+ print("Updater not available")
@@ -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"
9
+ __version__ = "v0.2.0.12"
10
10
  __author__ = 'Benedict Diederich'
11
11
  __author_email__ = 'benedictdied@gmail.com'
12
12
  __license__ = 'GPL v3'
@@ -64,11 +64,7 @@ class Laser(object):
64
64
  def get_laserpins(self):
65
65
  path = '/laser_get'
66
66
 
67
- payload = {
68
- "task": path,
69
- }
70
-
71
- r = self._parent.post_json(path, payload)
67
+ r = self._parent.get_json(path)
72
68
 
73
69
  if type(r) is dict:
74
70
  # cast laser pins
@@ -10,7 +10,7 @@ class LedMatrix(object):
10
10
  self.Nx = self.Ny = int(np.sqrt(NLeds))
11
11
 
12
12
  # we assume the pattern is binary (e.g. 0 or 1)
13
- self.ledpattern = np.zeros((self.NLeds, 3))
13
+ self.ledpattern = np.ones((self.NLeds, 3))*-1 # not set yet
14
14
 
15
15
  # this is a istance of the _parent32Client class
16
16
  self._parent = parent
@@ -165,6 +165,7 @@ class LedMatrix(object):
165
165
  def setAll(self, state, intensity=None):
166
166
  # fast addressing
167
167
  # turns on all LEDs at a certain intensity
168
+ state = np.sum(state)>0
168
169
  if intensity is not None:
169
170
  self.intensity = intensity
170
171
  intensity2display = np.array(self.intensity)*np.array(state)
@@ -217,10 +218,7 @@ class LedMatrix(object):
217
218
 
218
219
  def get_ledpin(self):
219
220
  path = "/ledarr_get"
220
- payload = {
221
- "task": path,
222
- }
223
- r = self._parent.post_json(path, payload, getReturn=True, timeout=1)
221
+ r = self._parent.get_json(path, getReturn=True, timeout=1)
224
222
  return r
225
223
 
226
224
 
@@ -25,12 +25,10 @@ class Modules(object):
25
25
  def get_modules(self, timeout=1):
26
26
  # returns a list of available modules that are set or not set in the ESP
27
27
  path = '/modules_get'
28
-
29
- payload = {
30
- "task": path,
31
- }
32
- r = self._parent.post_json(path, payload)["modules"]
33
-
28
+ try:
29
+ r = self._parent.get_json(path)["modules"]
30
+ except:
31
+ r = None
34
32
  return r
35
33
 
36
34
  def set_modules(self, modules, timeout=1):
@@ -3,7 +3,7 @@ import time
3
3
  import json
4
4
 
5
5
 
6
- gTIMEOUT = 10 # seconds to wait for a response from the ESP32
6
+ gTIMEOUT = 100 # seconds to wait for a response from the ESP32
7
7
  class Motor(object):
8
8
 
9
9
  # indicate if there is any motion happening
@@ -21,6 +21,9 @@ class Motor(object):
21
21
 
22
22
  def __init__(self, parent=None):
23
23
  self._parent = parent
24
+
25
+ # do we have a coreXY setup?
26
+ self.isCoreXY = False
24
27
 
25
28
  self.nMotors = 4
26
29
  self.steps_last = np.zeros((self.nMotors))
@@ -44,6 +47,9 @@ class Motor(object):
44
47
 
45
48
  self.motorAxisOrder = [0,1,2,3] # motor axis is 1,2,3,0 => X,Y,Z,T # FIXME: Hardcoded
46
49
 
50
+ def setIsCoreXY(self, isCoreXY = False):
51
+ self.isCoreXY = isCoreXY
52
+
47
53
  def setMotorAxisOrder(self, order=[0,1,2,3]):
48
54
  self.motorAxisOrder = order
49
55
 
@@ -84,17 +90,34 @@ class Motor(object):
84
90
  axis = 0
85
91
  return axis
86
92
 
87
- def move_x(self, steps=0, speed=1000, is_blocking=False, is_absolute=False, is_enabled=True, timeout=gTIMEOUT):
88
- return self.move_axis_by_name(axis="X", steps=steps, speed=speed, is_blocking=is_blocking, is_absolute=is_absolute, is_enabled=is_enabled, timeout=timeout)
93
+ def cartesian2corexy(self, x, y):
94
+ # convert cartesian coordinates to coreXY coordinates
95
+ # https://www.corexy.com/theory.html
96
+ x1 = (x+y)/np.sqrt(2)
97
+ y1 = (x-y)/np.sqrt(2)
98
+ return x1, y1
99
+
100
+ def move_x(self, steps=0, speed=1000, acceleration=None, is_blocking=False, is_absolute=False, is_enabled=True, timeout=gTIMEOUT):
101
+ if self.isCoreXY:
102
+ # have to turn two motors to move in X direction
103
+ xTemp, yTemp = self.cartesian2corexy(steps, 0)
104
+ return self.move_xy(steps=(xTemp, yTemp), speed=(speed,speed), is_blocking=is_blocking, is_absolute=is_absolute, is_enabled=is_enabled, timeout=timeout)
105
+ else:
106
+ return self.move_axis_by_name(axis="X", steps=steps, speed=speed, acceleration=acceleration, is_blocking=is_blocking, is_absolute=is_absolute, is_enabled=is_enabled, timeout=timeout)
89
107
 
90
- def move_y(self, steps=0, speed=1000, is_blocking=False, is_absolute=False, is_enabled=True, timeout=gTIMEOUT):
91
- return self.move_axis_by_name(axis="Y", steps=steps, speed=speed, is_blocking=is_blocking, is_absolute=is_absolute, is_enabled=is_enabled, timeout=timeout)
108
+ def move_y(self, steps=0, speed=1000, acceleration=None, is_blocking=False, is_absolute=False, is_enabled=True, timeout=gTIMEOUT):
109
+ if self.isCoreXY:
110
+ # have to turn two motors to move in Y direction
111
+ xTemp, yTemp = self.cartesian2corexy(0,steps)
112
+ return self.move_xy(steps=(xTemp, yTemp), speed=(speed,speed), is_blocking=is_blocking, is_absolute=is_absolute, is_enabled=is_enabled, timeout=timeout)
113
+ else:
114
+ return self.move_axis_by_name(axis="Y", steps=steps, speed=speed, acceleration=acceleration, is_blocking=is_blocking, is_absolute=is_absolute, is_enabled=is_enabled, timeout=timeout)
92
115
 
93
- def move_z(self, steps=0, speed=1000, is_blocking=False, is_absolute=False, is_enabled=True, timeout=gTIMEOUT):
94
- return self.move_axis_by_name(axis="Z", steps=steps, speed=speed, is_blocking=is_blocking, is_absolute=is_absolute, is_enabled=is_enabled, timeout=timeout)
116
+ def move_z(self, steps=0, speed=1000, acceleration=None, is_blocking=False, is_absolute=False, is_enabled=True, timeout=gTIMEOUT):
117
+ return self.move_axis_by_name(axis="Z", steps=steps, speed=speed, acceleration=acceleration, is_blocking=is_blocking, is_absolute=is_absolute, is_enabled=is_enabled, timeout=timeout)
95
118
 
96
- def move_t(self, steps=0, speed=1000, is_blocking=False, is_absolute=False, is_enabled=True, timeout=gTIMEOUT):
97
- return self.move_axis_by_name(axis="T", steps=steps, speed=speed, is_blocking=is_blocking, is_absolute=is_absolute, is_enabled=is_enabled, timeout=timeout)
119
+ def move_t(self, steps=0, speed=1000, acceleration=None, is_blocking=False, is_absolute=False, is_enabled=True, timeout=gTIMEOUT):
120
+ return self.move_axis_by_name(axis="T", steps=steps, speed=speed, acceleration=acceleration, is_blocking=is_blocking, is_absolute=is_absolute, is_enabled=is_enabled, timeout=timeout)
98
121
 
99
122
  def move_xyz(self, steps=(0,0,0), speed=(1000,1000,1000), is_blocking=False, is_absolute=False, is_enabled=True, timeout=gTIMEOUT):
100
123
  if len(speed)!= 3:
@@ -105,12 +128,16 @@ class Motor(object):
105
128
  return r
106
129
 
107
130
  def move_xy(self, steps=(0,0), speed=(1000,1000), is_blocking=False, is_absolute=False, is_enabled=True, timeout=gTIMEOUT):
108
- if len(speed)!= 2:
109
- speed = (speed,speed)
131
+ if self.isCoreXY:
132
+ # have to move only one motor to move in XY direction
133
+ return self.move_xyzt(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)
134
+ else:
135
+ if len(speed)!= 2:
136
+ speed = (speed,speed)
110
137
 
111
- # motor axis is 1,2,3,0 => X,Y,Z,T # FIXME: Hardcoded
112
- r = self.move_xyzt(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)
113
- return r
138
+ # motor axis is 1,2,3,0 => X,Y,Z,T # FIXME: Hardcoded
139
+ r = self.move_xyzt(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)
140
+ return r
114
141
 
115
142
  def move_xyzt(self, steps=(0,0,0,0), speed=(1000,1000,1000,1000), is_blocking=False, is_absolute=False, is_enabled=True, timeout=gTIMEOUT):
116
143
  if type(speed)==int:
@@ -121,7 +148,7 @@ class Motor(object):
121
148
  r = self.move_stepper(steps=steps, speed=speed, backlash=(self.backlash[0],self.backlash[1],self.backlash[2],self.backlash[3]), is_blocking=is_blocking, is_absolute=is_absolute, is_enabled=is_enabled, timeout=timeout)
122
149
  return r
123
150
 
124
- def move_axis_by_name(self, axis="X", steps=100, speed=1000, is_blocking=False, is_absolute=False, is_enabled=True, timeout=gTIMEOUT):
151
+ def move_axis_by_name(self, axis="X", steps=100, speed=1000, acceleration=None, is_blocking=False, is_absolute=False, is_enabled=True, timeout=gTIMEOUT):
125
152
  axis = self.xyztTo1230(axis)
126
153
  _speed=np.zeros(4)
127
154
  _speed[axis] = speed
@@ -129,7 +156,8 @@ class Motor(object):
129
156
  _steps[axis] = steps
130
157
  _backlash=np.zeros(4)
131
158
  _backlash[axis] = self.backlash[axis]
132
- r = self.move_stepper(_steps, speed=_speed, timeout=timeout, backlash=_backlash, is_blocking=is_blocking, is_absolute=is_absolute, is_enabled=is_enabled)
159
+ _acceleration=acceleration
160
+ r = self.move_stepper(_steps, speed=_speed, acceleration=_acceleration, timeout=timeout, backlash=_backlash, is_blocking=is_blocking, is_absolute=is_absolute, is_enabled=is_enabled)
133
161
  return r
134
162
 
135
163
  def move_forever(self, speed=(0,0,0,0), is_stop=False):
@@ -197,7 +225,7 @@ class Motor(object):
197
225
  return r
198
226
 
199
227
 
200
- def move_stepper(self, steps=(0,0,0,0), speed=(1000,1000,1000,1000), is_absolute=(False,False,False,False), timeout=1, backlash=(0,0,0,0), is_blocking=True, is_enabled=True):
228
+ def move_stepper(self, steps=(0,0,0,0), speed=(1000,1000,1000,1000), is_absolute=(False,False,False,False), timeout=gTIMEOUT, backlash=(0,0,0,0), acceleration=(None, None, None, None), is_blocking=True, is_enabled=True):
201
229
  '''
202
230
  This tells the motor to run at a given speed for a specific number of steps; Multiple motors can run simultaneously
203
231
 
@@ -217,6 +245,10 @@ class Motor(object):
217
245
  if type(speed)!=list and type(speed)!=tuple and type(speed)!=np.ndarray:
218
246
  speed = np.array((speed,speed,speed,speed))
219
247
 
248
+ # convert single elements to array
249
+ if type(acceleration)!=list and type(acceleration)!=tuple and type(acceleration)!=np.ndarray:
250
+ acceleration = np.array((acceleration,acceleration,acceleration,acceleration))
251
+
220
252
  # make sure value is an array
221
253
  if type(steps)==tuple:
222
254
  steps = np.array(steps)
@@ -248,41 +280,19 @@ class Motor(object):
248
280
  steps_3 = 0
249
281
  '''
250
282
 
251
- '''
252
- {"task":"/motor_act",
253
- "motor":{
254
- "steppers":[
255
- {
256
- "stepperid":1,
257
- "position":-1000,
258
- "speed":2000,
259
- "isabs":0,
260
- "isaccel":0
261
- }
262
- ]
263
- }
264
- }
265
-
266
- {"task":"/motor_act",
267
- "motor":
268
- {
269
- "steppers": [
270
- { "stepperid": 1, "position": -100, "speed": 2000, "isabs": 0, "isaccel":0}
271
- ]
272
- }
273
- }
274
- '''
275
283
 
276
284
  # only consider those actions that are necessary
277
285
  motorPropList = []
278
286
  for iMotor in range(4):
279
287
  if isAbsoluteArray[iMotor] or abs(steps[iMotor])>0:
280
288
  motorProp = { "stepperid": self.motorAxisOrder[iMotor],
281
- "position": np.int(steps[iMotor]),
282
- "speed": speed[iMotor],
289
+ "position": int(steps[iMotor]),
290
+ "speed": int(speed[iMotor]),
283
291
  "isabs": isAbsoluteArray[iMotor],
284
292
  "isaccel":0,
285
293
  "isen": is_enabled}
294
+ if acceleration[iMotor] is not None:
295
+ motorProp["accel"] = int(acceleration[iMotor])
286
296
  motorPropList.append(motorProp)
287
297
 
288
298
  path = "/motor_act"
@@ -304,8 +314,11 @@ class Motor(object):
304
314
 
305
315
  # wait until job has been done
306
316
  time0=time.time()
307
- steppersRunning = np.abs(np.array(steps))>0
308
- if is_blocking and self._parent.serial.is_connected:
317
+ if np.sum(isAbsoluteArray):
318
+ steppersRunning = isAbsoluteArray
319
+ else:
320
+ steppersRunning = np.abs(np.array(steps))>0
321
+ if not self._parent.is_wifi and is_blocking and self._parent.serial.is_connected:
309
322
  while True:
310
323
  time.sleep(0.05) # don'T overwhelm the CPU
311
324
  # see if already done
@@ -395,21 +408,40 @@ class Motor(object):
395
408
  r = self.set_motor(stepperid = axis, position = currentPosition)
396
409
  return r
397
410
 
398
- def set_motor_acceleration(self, axis=0, acceleration=10000):
411
+ def set_motor_acceleration(self, axis=0, acceleration=40000):
399
412
  if type(axis)==str:
400
413
  axis = self.xyztTo1230(axis)
401
414
 
402
- r = self.set_motor(stepperid = axis, acceleration=acceleration)
415
+ path = "/motor_act"
416
+ payload = {
417
+ "task": path,
418
+ "motor":
419
+ {
420
+ "steppers": [
421
+ { "stepperid":axis, "isaccel":1, "accel":acceleration}
422
+ ]
423
+ }
424
+ }
425
+ r = self._parent.post_json(path, payload)
403
426
  return r
404
427
 
405
- def set_motor_enable(self, axis =0, is_enable=1):
406
- if type(axis)==str:
407
- axis = self.xyztTo1230(axis)
428
+
429
+ def set_motor_enable(self, is_enable=1):
430
+ self.set_motor_enable(enable=is_enable)
431
+
432
+ def set_motor_enable(self, enable=None, enableauto=None):
433
+ """
434
+ turns on/off enable pin overrides motor settings - god for cooling puproses
435
+ eanbaleauto turns on/off timer of the accelstepper library
436
+ """
408
437
  path = "/motor_act"
409
438
  payload = {
410
- "task": path,
411
- "isen": is_enable
439
+ "task": path
412
440
  }
441
+ if enable is not None:
442
+ payload["isen"] = enable
443
+ if enableauto is not None:
444
+ payload["isenauto"] = enableauto
413
445
  r = self._parent.post_json(path, payload)
414
446
  return r
415
447
 
@@ -464,10 +496,8 @@ class Motor(object):
464
496
 
465
497
  def get_motors(self, timeout=1):
466
498
  path = "/motor_get"
467
- payload = {
468
- "task":path,
469
- }
470
- r = self._parent.post_json(path, payload, timeout=timeout)
499
+
500
+ r = self._parent.get_json(path, timeout=timeout)
471
501
  try: return r["steppers"]
472
502
  except: return False
473
503
 
@@ -1,9 +1,12 @@
1
- import serial
2
- import serial.tools.list_ports
1
+ try:
2
+ import serial
3
+ import serial.tools.list_ports
4
+ except:
5
+ print("No serial available - running on pyscript?")
3
6
  import time
4
7
  import json
5
8
 
6
- T_SERIAL_WARMUP = 2 # the time to wait for the serial to warm up
9
+ T_SERIAL_WARMUP = 3 # the time to wait for the serial to warm up
7
10
 
8
11
  class Serial(object):
9
12
 
@@ -208,6 +211,75 @@ class Serial(object):
208
211
  self.isSafetyBreak = False
209
212
  return _returnmessage
210
213
 
214
+ class SerialManagerWrapper(object):
215
+
216
+ def __init__(self, SerialManager, DEBUG = True, parent=None) -> None:
217
+ self._parent=parent
218
+ self._parent.logger.debug("SerialManagerWrapper init")
219
+ self.SerialManager = SerialManager
220
+ self.isSafetyBreak = False
221
+ self.DEBUG = DEBUG
222
+
223
+ async def post_json(self, path, payload={}, getReturn=True, timeout=1):
224
+ if "task" not in payload:
225
+ payload["task"] = path
226
+
227
+ if "isblock" in payload:
228
+ is_blocking = payload["isblock"]
229
+ else:
230
+ is_blocking = True
231
+
232
+ # write message to the serial
233
+ await self.writeSerial(payload)
234
+ return ''
235
+ print(3)
236
+ if getReturn:
237
+ # we read the return message
238
+ #self._parent.logger.debug(payload)
239
+ returnmessage = self.readSerial(is_blocking=is_blocking, timeout=timeout)
240
+ else:
241
+ returnmessage = False
242
+ return returnmessage
243
+
244
+ async def writeSerial(self, payload):
245
+ """Write JSON document to serial device"""
246
+ if type(payload)==dict:
247
+ payload = json.dumps(payload)
248
+ try:
249
+ if self.DEBUG: self._parent.logger.debug(payload)
250
+ await self.SerialManager.write(payload)
251
+ except Exception as e:
252
+ self._parent.logger.error(e)
253
+
254
+ async def readSerial(self, is_blocking=True, timeout = 1): # TODO: hardcoded timeout - not code
255
+ """Receive and decode return message"""
256
+ returnmessage = ''
257
+ _returnmessage = ''
258
+ rmessage = ''
259
+ _time0 = time.time()
260
+ print("Reading serial")
261
+ if is_blocking:
262
+ while is_blocking and not self.isSafetyBreak:
263
+ try:
264
+ rmessage = await self.SerialManager.read().decode()
265
+ if self.DEBUG: self._parent.logger.debug(rmessage)
266
+ returnmessage += rmessage
267
+ if rmessage.find("--")==0:
268
+ break
269
+ except:
270
+ pass
271
+ if (time.time()-_time0)>timeout:
272
+ break
273
+ # casting to dict
274
+ try:
275
+ # TODO: check if this is a valid JSON
276
+ _returnmessage = returnmessage.split("\n--")[0].split("\n++")[-1].replace("\r","").replace("\n", "").replace("'", '"')
277
+ if self.DEBUG: self._parent.logger.debug(returnmessage)
278
+ _returnmessage = json.loads(_returnmessage)
279
+ except Exception as e:
280
+ if self.DEBUG: self._parent.logger.debug("Casting json string from serial to Python dict failed")
281
+ self.isSafetyBreak = False
282
+ return _returnmessage
211
283
  class SerialDummy(object):
212
284
 
213
285
  def __init__(self, port, baudrate, timeout=1, parent=None):
@@ -11,10 +11,7 @@ class State(object):
11
11
  def get_state(self, timeout=3):
12
12
  path = "/state_get"
13
13
 
14
- payload = {
15
- "task":path
16
- }
17
- r = self._parent.post_json(path, payload, timeout=timeout)
14
+ r = self._parent.get_json(path, timeout=timeout)
18
15
  return r
19
16
 
20
17
  def set_state(self, debug=False, timeout=1):
@@ -0,0 +1,17 @@
1
+ from datetime import datetime as dt
2
+
3
+
4
+ def format_date(dt_, fmt="%m/%d/%Y, %H:%M:%S"):
5
+ return dt_.strftime(fmt)
6
+
7
+
8
+ def now(fmt="%m/%d/%Y, %H:%M:%S"):
9
+ return format_date(dt.now(), fmt)
10
+
11
+
12
+ def remove_class(element, className):
13
+ element.element.classList.remove(className)
14
+
15
+
16
+ def add_class(element, className):
17
+ element.element.classList.add(className)
@@ -1,3 +0,0 @@
1
- from .config import *
2
- from .UC2Client import *
3
- from .updater import *
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