standardbots 2.0.0.dev1737138088__tar.gz → 2.0.0.dev1740502639__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.
Potentially problematic release.
This version of standardbots might be problematic. Click here for more details.
- {standardbots-2.0.0.dev1737138088 → standardbots-2.0.0.dev1740502639}/PKG-INFO +1 -1
- standardbots-2.0.0.dev1740502639/README.md +153 -0
- {standardbots-2.0.0.dev1737138088 → standardbots-2.0.0.dev1740502639}/setup.py +1 -1
- {standardbots-2.0.0.dev1737138088 → standardbots-2.0.0.dev1740502639}/standardbots/auto_generated/apis.py +186 -15
- {standardbots-2.0.0.dev1737138088 → standardbots-2.0.0.dev1740502639}/standardbots/auto_generated/models.py +665 -255
- {standardbots-2.0.0.dev1737138088 → standardbots-2.0.0.dev1740502639}/standardbots.egg-info/PKG-INFO +1 -1
- {standardbots-2.0.0.dev1737138088 → standardbots-2.0.0.dev1740502639}/standardbots.egg-info/SOURCES.txt +6 -1
- {standardbots-2.0.0.dev1737138088 → standardbots-2.0.0.dev1740502639}/standardbots.egg-info/top_level.txt +1 -0
- standardbots-2.0.0.dev1740502639/tests/fixtures/__init__.py +0 -0
- standardbots-2.0.0.dev1740502639/tests/fixtures/client_fixt.py +25 -0
- standardbots-2.0.0.dev1740502639/tests/fixtures/routines_fixt.py +48 -0
- standardbots-2.0.0.dev1740502639/tests/test_apis.py +2994 -0
- {standardbots-2.0.0.dev1737138088 → standardbots-2.0.0.dev1740502639}/setup.cfg +0 -0
- {standardbots-2.0.0.dev1737138088 → standardbots-2.0.0.dev1740502639}/standardbots/__init__.py +0 -0
- {standardbots-2.0.0.dev1737138088 → standardbots-2.0.0.dev1740502639}/standardbots/auto_generated/__init__.py +0 -0
- {standardbots-2.0.0.dev1737138088 → standardbots-2.0.0.dev1740502639}/standardbots.egg-info/dependency_links.txt +0 -0
- {standardbots-2.0.0.dev1737138088 → standardbots-2.0.0.dev1740502639}/standardbots.egg-info/requires.txt +0 -0
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
You can test the API by using the playground, add your own file or use the existing python scripts.
|
|
2
|
+
When a client has an issue, and they send their code. It's helpful to test their code to see possible issues
|
|
3
|
+
|
|
4
|
+
# ENABLE API ON YOUR LOCAL MACHINE
|
|
5
|
+
|
|
6
|
+
Follow the steps here https://www.notion.so/standardbots/Using-the-REST-API-b2c778d47969444dac61483f0117acad
|
|
7
|
+
|
|
8
|
+
# CONFIG
|
|
9
|
+
|
|
10
|
+
At the top of the file, use your token
|
|
11
|
+
|
|
12
|
+
# RUN
|
|
13
|
+
|
|
14
|
+
To run a script move into the `sdks/python` folder and run `python playground/filename.py`
|
|
15
|
+
|
|
16
|
+
# To create a test build
|
|
17
|
+
|
|
18
|
+
1. Update version in `setup.py`
|
|
19
|
+
2. Run `python3 setup.py sdist bdist_wheel`
|
|
20
|
+
|
|
21
|
+
# Tests
|
|
22
|
+
|
|
23
|
+
## Setup
|
|
24
|
+
|
|
25
|
+
To set up tests:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
cd sdks/python
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Note: Make sure to select proper python interpreter.
|
|
32
|
+
Sometimes there is an error related to missing "dotenv" module, to solve this install it separately
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
python3 -m pip install python-dotenv
|
|
36
|
+
python3 -m pip install -r requirements-dev.txt
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Create sample data
|
|
40
|
+
|
|
41
|
+
#### Sample routine
|
|
42
|
+
|
|
43
|
+
You need to add the sample routine in [sdks/python/tests/fixtures/test_public_api_routine.json](./tests/fixtures/test_public_api_routine.json) to your target test environment (i.e. upload the routine to ).
|
|
44
|
+
|
|
45
|
+
The name of routine should be "Test Public API"
|
|
46
|
+
|
|
47
|
+
#### Sample globals
|
|
48
|
+
|
|
49
|
+
- _Variable._ Add global variable called "test_public_api_global" with any value.
|
|
50
|
+
- _Space._ Create a global space called "Test global space" of any kind.
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
## Running
|
|
54
|
+
|
|
55
|
+
Here is a basic test command:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
SB_API_URL=http://34.162.0.32:3000
|
|
59
|
+
SB_API_TOKEN=...
|
|
60
|
+
|
|
61
|
+
python3 -m pytest ./tests --cov=standardbots --token=$SB_API_TOKEN --api-url=$SB_API_URL
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
You may also set up a `.env` file at `sdks/python/.env` with the following contents:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
export SB_API_URL=http://34.162.0.32:3000
|
|
68
|
+
export SB_API_TOKEN=...
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Then you can just do:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
python3 -m pytest ./tests --cov=standardbots
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Robot state and testing (Markers)
|
|
78
|
+
|
|
79
|
+
We need the bot to be in a certain state to run certain tests. For example, we need a routine to be running in order to stop the routine. Camera should be connected by default.
|
|
80
|
+
|
|
81
|
+
At start of testing, robot should:
|
|
82
|
+
|
|
83
|
+
- _NOT_ be e-stopped.
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
The basic idea here is:
|
|
87
|
+
|
|
88
|
+
- These special tests will not be run by default.
|
|
89
|
+
- You may pass a flag (e.g. `--routine-running`) when the bot is in the correct state to run the tests.
|
|
90
|
+
- Markers usage:
|
|
91
|
+
- When `--routine-running` flag is passed:
|
|
92
|
+
1. Tests with the flag are run.
|
|
93
|
+
2. Tests without the flag are not run.
|
|
94
|
+
- When `--gripper=<type>` flag is passed(`type` is value from `GripperKindEnum` enum):
|
|
95
|
+
1. Tests expect that this specific gripper is connected
|
|
96
|
+
2. Tests without the flag are not run.
|
|
97
|
+
- When `--camera-disconnected` flag is passed:
|
|
98
|
+
1. Tests with the flag are run.
|
|
99
|
+
2. Tests without the flag are not run.
|
|
100
|
+
|
|
101
|
+
We use [pytest markers](https://docs.pytest.org/en/7.1.x/example/markers.html) to do this.
|
|
102
|
+
|
|
103
|
+
#### Routine running
|
|
104
|
+
|
|
105
|
+
The special sample routine ("Test Public API") should be running prior to running these tests. Then do:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
python3 -m pytest ./tests --cov=standardbots --routine-running
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
#### E-stop
|
|
112
|
+
|
|
113
|
+
No marker needed for e-stop. However, we do rely on active recovery of e-stop and getting the failure state in order to do these tests.
|
|
114
|
+
|
|
115
|
+
When e-stop test runs, cannot have bot in a failure state (pre-test will fail).
|
|
116
|
+
|
|
117
|
+
## Troubleshooting
|
|
118
|
+
|
|
119
|
+
### Tests are hanging
|
|
120
|
+
|
|
121
|
+
The first test appears to start but then nothing happens for several seconds:
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
$ python3 -m pytest ./tests --cov=standardbots
|
|
125
|
+
========================================================================================================== test session starts ===========================================================================================================
|
|
126
|
+
platform linux -- Python 3.10.12, pytest-6.2.5, py-1.10.0, pluggy-0.13.0
|
|
127
|
+
rootdir: /workspaces/sb/sdks/python, configfile: pytest.ini
|
|
128
|
+
plugins: ament-pep257-0.12.11, ament-xmllint-0.12.11, launch-testing-1.0.6, launch-testing-ros-0.19.7, ament-flake8-0.12.11, ament-lint-0.12.11, ament-copyright-0.12.11, colcon-core-0.18.1, cov-6.0.0
|
|
129
|
+
collected 110 items
|
|
130
|
+
|
|
131
|
+
tests/test_apis.py
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Fixes:
|
|
135
|
+
|
|
136
|
+
- _Make sure you can log into remote control._ Ensure that botman is connected.
|
|
137
|
+
- _Ensure that the robot URL is up-to-date._ Botman url will often change when you reboot.
|
|
138
|
+
|
|
139
|
+
### Custom sensors
|
|
140
|
+
|
|
141
|
+
To test custom sensors:
|
|
142
|
+
- go to the menu on the left bottom corner;
|
|
143
|
+
- Click on 'Equipment';
|
|
144
|
+
- Add Gripper > Custom Gripper;
|
|
145
|
+
- Go to the Sensors tab and click 'Add Sensor';
|
|
146
|
+
- Keep the default values as they are (name: 'Sensor 1', kind: 'Control Box IO', sensor value: 'low');
|
|
147
|
+
- Hit 'Save' and make sure the Custom Gripper is enabled.
|
|
148
|
+
|
|
149
|
+
Then run:
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
python3 -m pytest ./tests --cov=standardbots --custom-sensors
|
|
153
|
+
```
|
|
@@ -76,6 +76,95 @@ class RequestManager:
|
|
|
76
76
|
|
|
77
77
|
class Default:
|
|
78
78
|
_request_manager: RequestManager
|
|
79
|
+
class Calibration:
|
|
80
|
+
def __init__(self, request_manager: RequestManager):
|
|
81
|
+
self._request_manager = request_manager
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def get_active_calibration(
|
|
85
|
+
self,
|
|
86
|
+
) -> Response[
|
|
87
|
+
Union[
|
|
88
|
+
models.ActiveCalibrationContainer,
|
|
89
|
+
models.ErrorResponse,
|
|
90
|
+
None
|
|
91
|
+
],
|
|
92
|
+
models.ActiveCalibrationContainer
|
|
93
|
+
]:
|
|
94
|
+
"""
|
|
95
|
+
Get the active calibration for the robot.
|
|
96
|
+
|
|
97
|
+
"""
|
|
98
|
+
path = "/api/v1/calibration/active"
|
|
99
|
+
try:
|
|
100
|
+
response = self._request_manager.request(
|
|
101
|
+
"GET",
|
|
102
|
+
path,
|
|
103
|
+
headers=self._request_manager.json_headers(),
|
|
104
|
+
)
|
|
105
|
+
parsed = None
|
|
106
|
+
if response.status == 200:
|
|
107
|
+
parsed = models.parse_active_calibration_container(json.loads(response.data))
|
|
108
|
+
|
|
109
|
+
is_user_error = response.status >= 400 and response.status <= 500
|
|
110
|
+
is_unavailable = response.status == 503
|
|
111
|
+
if parsed is None and (is_user_error or is_unavailable):
|
|
112
|
+
parsed = models.parse_error_response(json.loads(response.data))
|
|
113
|
+
|
|
114
|
+
return Response(
|
|
115
|
+
parsed,
|
|
116
|
+
response.status,
|
|
117
|
+
response
|
|
118
|
+
)
|
|
119
|
+
except urllib3.exceptions.MaxRetryError:
|
|
120
|
+
return Response(
|
|
121
|
+
models.ErrorResponse(
|
|
122
|
+
error=models.ErrorEnum.InternalServerError,
|
|
123
|
+
message="Connection Refused"
|
|
124
|
+
),
|
|
125
|
+
503,
|
|
126
|
+
None
|
|
127
|
+
)
|
|
128
|
+
def set_active_calibration(
|
|
129
|
+
self,
|
|
130
|
+
body: models.ActiveCalibrationContainer,
|
|
131
|
+
) -> Response[
|
|
132
|
+
None,
|
|
133
|
+
None
|
|
134
|
+
]:
|
|
135
|
+
"""
|
|
136
|
+
Set the active calibration for the robot.
|
|
137
|
+
|
|
138
|
+
"""
|
|
139
|
+
path = "/api/v1/calibration/active"
|
|
140
|
+
try:
|
|
141
|
+
response = self._request_manager.request(
|
|
142
|
+
"POST",
|
|
143
|
+
path,
|
|
144
|
+
headers=self._request_manager.json_headers(),
|
|
145
|
+
body=json.dumps(models.serialize_active_calibration_container(body)),
|
|
146
|
+
)
|
|
147
|
+
parsed = None
|
|
148
|
+
|
|
149
|
+
is_user_error = response.status >= 400 and response.status <= 500
|
|
150
|
+
is_unavailable = response.status == 503
|
|
151
|
+
if parsed is None and (is_user_error or is_unavailable):
|
|
152
|
+
parsed = models.parse_error_response(json.loads(response.data))
|
|
153
|
+
|
|
154
|
+
return Response(
|
|
155
|
+
parsed,
|
|
156
|
+
response.status,
|
|
157
|
+
response
|
|
158
|
+
)
|
|
159
|
+
except urllib3.exceptions.MaxRetryError:
|
|
160
|
+
return Response(
|
|
161
|
+
models.ErrorResponse(
|
|
162
|
+
error=models.ErrorEnum.InternalServerError,
|
|
163
|
+
message="Connection Refused"
|
|
164
|
+
),
|
|
165
|
+
503,
|
|
166
|
+
None
|
|
167
|
+
)
|
|
79
168
|
class Equipment:
|
|
80
169
|
def __init__(self, request_manager: RequestManager):
|
|
81
170
|
self._request_manager = request_manager
|
|
@@ -83,7 +172,7 @@ class Default:
|
|
|
83
172
|
def onrobot_2fg7_move(
|
|
84
173
|
self,
|
|
85
174
|
value: Union[int, float],
|
|
86
|
-
direction: Union[str, models.LinearGripDirectionEnum] = models.LinearGripDirectionEnum.
|
|
175
|
+
direction: Union[str, models.LinearGripDirectionEnum] = models.LinearGripDirectionEnum.Internal,
|
|
87
176
|
unit_kind: Union[str, models.LinearUnitKind] = models.LinearUnitKind.Millimeters
|
|
88
177
|
):
|
|
89
178
|
"""Move the robot to the onrobot_2fg7 position.
|
|
@@ -105,7 +194,7 @@ class Default:
|
|
|
105
194
|
def onrobot_2fg7_grip(
|
|
106
195
|
self,
|
|
107
196
|
value: Union[int, float],
|
|
108
|
-
direction: Union[str, models.LinearGripDirectionEnum] = models.LinearGripDirectionEnum.
|
|
197
|
+
direction: Union[str, models.LinearGripDirectionEnum] = models.LinearGripDirectionEnum.Internal,
|
|
109
198
|
unit_kind: Union[str, models.LinearUnitKind] = models.LinearUnitKind.Millimeters,
|
|
110
199
|
force: Union[int, float] = 0.0,
|
|
111
200
|
force_unit: Union[str, models.ForceUnitKind] = models.ForceUnitKind.Newtons
|
|
@@ -188,7 +277,7 @@ class Default:
|
|
|
188
277
|
return self.control_gripper(
|
|
189
278
|
body=models.GripperCommandRequest(
|
|
190
279
|
kind=models.GripperKindEnum.DhCgi,
|
|
191
|
-
|
|
280
|
+
dh_cgi=models.DHCGIGripperCommandRequest(
|
|
192
281
|
target_diameter, target_force, target_speed
|
|
193
282
|
),
|
|
194
283
|
),
|
|
@@ -382,12 +471,14 @@ class Default:
|
|
|
382
471
|
None
|
|
383
472
|
)
|
|
384
473
|
|
|
474
|
+
calibration: Calibration
|
|
385
475
|
equipment: Equipment
|
|
386
476
|
sensors: Sensors
|
|
387
477
|
space: Space
|
|
388
478
|
|
|
389
479
|
def __init__(self, request_manager: RequestManager):
|
|
390
480
|
self._request_manager = request_manager
|
|
481
|
+
self.calibration = Default.Calibration(request_manager)
|
|
391
482
|
self.equipment = Default.Equipment(request_manager)
|
|
392
483
|
self.sensors = Default.Sensors(request_manager)
|
|
393
484
|
self.space = Default.Space(request_manager)
|
|
@@ -425,6 +516,7 @@ class Movement:
|
|
|
425
516
|
Union[
|
|
426
517
|
models.BrakesState,
|
|
427
518
|
models.ErrorResponse,
|
|
519
|
+
models.ErrorResponse,
|
|
428
520
|
None
|
|
429
521
|
],
|
|
430
522
|
models.BrakesState
|
|
@@ -444,6 +536,8 @@ class Movement:
|
|
|
444
536
|
parsed = None
|
|
445
537
|
if response.status == 200:
|
|
446
538
|
parsed = models.parse_brakes_state(json.loads(response.data))
|
|
539
|
+
if response.status == 500:
|
|
540
|
+
parsed = models.parse_error_response(json.loads(response.data))
|
|
447
541
|
|
|
448
542
|
is_user_error = response.status >= 400 and response.status <= 500
|
|
449
543
|
is_unavailable = response.status == 503
|
|
@@ -713,7 +807,7 @@ class Camera:
|
|
|
713
807
|
None
|
|
714
808
|
]:
|
|
715
809
|
"""
|
|
716
|
-
Retrieve the latest RGB frame from the camera.
|
|
810
|
+
Retrieve the latest RGB frame from the camera as base64 string. In JPEG format.
|
|
717
811
|
"""
|
|
718
812
|
path = "/api/v1/camera/frame/rgb"
|
|
719
813
|
try:
|
|
@@ -747,8 +841,12 @@ class Camera:
|
|
|
747
841
|
def get_camera_intrinsics_color(
|
|
748
842
|
self,
|
|
749
843
|
) -> Response[
|
|
750
|
-
|
|
751
|
-
|
|
844
|
+
Union[
|
|
845
|
+
models.CameraIntrinsics,
|
|
846
|
+
models.ErrorResponse,
|
|
847
|
+
None
|
|
848
|
+
],
|
|
849
|
+
models.CameraIntrinsics
|
|
752
850
|
]:
|
|
753
851
|
"""
|
|
754
852
|
Retrieve the intrinsic parameters for the color camera.
|
|
@@ -761,6 +859,8 @@ class Camera:
|
|
|
761
859
|
headers=self._request_manager.json_headers(),
|
|
762
860
|
)
|
|
763
861
|
parsed = None
|
|
862
|
+
if response.status == 200:
|
|
863
|
+
parsed = models.parse_camera_intrinsics(json.loads(response.data))
|
|
764
864
|
|
|
765
865
|
is_user_error = response.status >= 400 and response.status <= 500
|
|
766
866
|
is_unavailable = response.status == 503
|
|
@@ -788,7 +888,7 @@ class Camera:
|
|
|
788
888
|
None
|
|
789
889
|
]:
|
|
790
890
|
"""
|
|
791
|
-
Retrieve the latest RGB frame from the camera.
|
|
891
|
+
Retrieve the latest RGB frame from the camera as base64 string. In JPEG format.
|
|
792
892
|
"""
|
|
793
893
|
path = "/api/v1/camera/stream/rgb"
|
|
794
894
|
try:
|
|
@@ -863,14 +963,64 @@ class Camera:
|
|
|
863
963
|
503,
|
|
864
964
|
None
|
|
865
965
|
)
|
|
966
|
+
class Status:
|
|
967
|
+
def __init__(self, request_manager: RequestManager):
|
|
968
|
+
self._request_manager = request_manager
|
|
969
|
+
|
|
970
|
+
|
|
971
|
+
def get_camera_status(
|
|
972
|
+
self,
|
|
973
|
+
) -> Response[
|
|
974
|
+
Union[
|
|
975
|
+
models.CameraStatus,
|
|
976
|
+
models.ErrorResponse,
|
|
977
|
+
None
|
|
978
|
+
],
|
|
979
|
+
models.CameraStatus
|
|
980
|
+
]:
|
|
981
|
+
"""
|
|
982
|
+
Retrieve the current status of the camera.
|
|
983
|
+
"""
|
|
984
|
+
path = "/api/v1/camera/status"
|
|
985
|
+
try:
|
|
986
|
+
response = self._request_manager.request(
|
|
987
|
+
"GET",
|
|
988
|
+
path,
|
|
989
|
+
headers=self._request_manager.json_headers(),
|
|
990
|
+
)
|
|
991
|
+
parsed = None
|
|
992
|
+
if response.status == 200:
|
|
993
|
+
parsed = models.parse_camera_status(json.loads(response.data))
|
|
994
|
+
|
|
995
|
+
is_user_error = response.status >= 400 and response.status <= 500
|
|
996
|
+
is_unavailable = response.status == 503
|
|
997
|
+
if parsed is None and (is_user_error or is_unavailable):
|
|
998
|
+
parsed = models.parse_error_response(json.loads(response.data))
|
|
999
|
+
|
|
1000
|
+
return Response(
|
|
1001
|
+
parsed,
|
|
1002
|
+
response.status,
|
|
1003
|
+
response
|
|
1004
|
+
)
|
|
1005
|
+
except urllib3.exceptions.MaxRetryError:
|
|
1006
|
+
return Response(
|
|
1007
|
+
models.ErrorResponse(
|
|
1008
|
+
error=models.ErrorEnum.InternalServerError,
|
|
1009
|
+
message="Connection Refused"
|
|
1010
|
+
),
|
|
1011
|
+
503,
|
|
1012
|
+
None
|
|
1013
|
+
)
|
|
866
1014
|
|
|
867
1015
|
data: Data
|
|
868
1016
|
settings: Settings
|
|
1017
|
+
status: Status
|
|
869
1018
|
|
|
870
1019
|
def __init__(self, request_manager: RequestManager):
|
|
871
1020
|
self._request_manager = request_manager
|
|
872
1021
|
self.data = Camera.Data(request_manager)
|
|
873
1022
|
self.settings = Camera.Settings(request_manager)
|
|
1023
|
+
self.status = Camera.Status(request_manager)
|
|
874
1024
|
|
|
875
1025
|
class Faults:
|
|
876
1026
|
_request_manager: RequestManager
|
|
@@ -1927,8 +2077,13 @@ class RoutineEditor:
|
|
|
1927
2077
|
body: models.PlayRoutineRequest,
|
|
1928
2078
|
routine_id: str,
|
|
1929
2079
|
) -> Response[
|
|
1930
|
-
|
|
1931
|
-
|
|
2080
|
+
Union[
|
|
2081
|
+
models.PlayRoutineResponse,
|
|
2082
|
+
models.ErrorResponse,
|
|
2083
|
+
models.ErrorResponse,
|
|
2084
|
+
None
|
|
2085
|
+
],
|
|
2086
|
+
models.PlayRoutineResponse
|
|
1932
2087
|
]:
|
|
1933
2088
|
"""
|
|
1934
2089
|
Play a routine
|
|
@@ -1943,6 +2098,10 @@ class RoutineEditor:
|
|
|
1943
2098
|
body=json.dumps(models.serialize_play_routine_request(body)),
|
|
1944
2099
|
)
|
|
1945
2100
|
parsed = None
|
|
2101
|
+
if response.status == 200:
|
|
2102
|
+
parsed = models.parse_play_routine_response(json.loads(response.data))
|
|
2103
|
+
if response.status == 400:
|
|
2104
|
+
parsed = models.parse_error_response(json.loads(response.data))
|
|
1946
2105
|
|
|
1947
2106
|
is_user_error = response.status >= 400 and response.status <= 500
|
|
1948
2107
|
is_unavailable = response.status == 503
|
|
@@ -1967,11 +2126,15 @@ class RoutineEditor:
|
|
|
1967
2126
|
self,
|
|
1968
2127
|
routine_id: str,
|
|
1969
2128
|
) -> Response[
|
|
1970
|
-
|
|
2129
|
+
Union[
|
|
2130
|
+
models.ErrorResponse,
|
|
2131
|
+
models.ErrorResponse,
|
|
2132
|
+
None
|
|
2133
|
+
],
|
|
1971
2134
|
None
|
|
1972
2135
|
]:
|
|
1973
2136
|
"""
|
|
1974
|
-
Pause a routine
|
|
2137
|
+
Pause a routine. Routine must be running.
|
|
1975
2138
|
"""
|
|
1976
2139
|
path = "/api/v1/routine-editor/routines/{routine_id}/pause"
|
|
1977
2140
|
path = path.replace("{routine_id}", str(routine_id))
|
|
@@ -1982,6 +2145,8 @@ class RoutineEditor:
|
|
|
1982
2145
|
headers=self._request_manager.json_headers(),
|
|
1983
2146
|
)
|
|
1984
2147
|
parsed = None
|
|
2148
|
+
if response.status == 400:
|
|
2149
|
+
parsed = models.parse_error_response(json.loads(response.data))
|
|
1985
2150
|
|
|
1986
2151
|
is_user_error = response.status >= 400 and response.status <= 500
|
|
1987
2152
|
is_unavailable = response.status == 503
|
|
@@ -2005,11 +2170,15 @@ class RoutineEditor:
|
|
|
2005
2170
|
def stop(
|
|
2006
2171
|
self,
|
|
2007
2172
|
) -> Response[
|
|
2008
|
-
|
|
2173
|
+
Union[
|
|
2174
|
+
models.ErrorResponse,
|
|
2175
|
+
models.ErrorResponse,
|
|
2176
|
+
None
|
|
2177
|
+
],
|
|
2009
2178
|
None
|
|
2010
2179
|
]:
|
|
2011
2180
|
"""
|
|
2012
|
-
Stop running routine and all ongoing motions
|
|
2181
|
+
Stop running routine and all ongoing motions. Routine must be running.
|
|
2013
2182
|
"""
|
|
2014
2183
|
path = "/api/v1/routine-editor/stop"
|
|
2015
2184
|
try:
|
|
@@ -2019,6 +2188,8 @@ class RoutineEditor:
|
|
|
2019
2188
|
headers=self._request_manager.json_headers(),
|
|
2020
2189
|
)
|
|
2021
2190
|
parsed = None
|
|
2191
|
+
if response.status == 400:
|
|
2192
|
+
parsed = models.parse_error_response(json.loads(response.data))
|
|
2022
2193
|
|
|
2023
2194
|
is_user_error = response.status >= 400 and response.status <= 500
|
|
2024
2195
|
is_unavailable = response.status == 503
|
|
@@ -2293,7 +2464,7 @@ class RoutineEditor:
|
|
|
2293
2464
|
models.RuntimeVariable
|
|
2294
2465
|
]:
|
|
2295
2466
|
"""
|
|
2296
|
-
Returns current state of a variable
|
|
2467
|
+
Returns current state of a variable. Routine must be running.
|
|
2297
2468
|
"""
|
|
2298
2469
|
path = "/api/v1/routine-editor/variables/{variable_name}"
|
|
2299
2470
|
path = path.replace("{variable_name}", str(variable_name))
|
|
@@ -2339,7 +2510,7 @@ class RoutineEditor:
|
|
|
2339
2510
|
models.RuntimeVariable
|
|
2340
2511
|
]:
|
|
2341
2512
|
"""
|
|
2342
|
-
Update the value of a variable
|
|
2513
|
+
Update the value of a variable. Routine must be running.
|
|
2343
2514
|
"""
|
|
2344
2515
|
path = "/api/v1/routine-editor/variables/{variable_name}"
|
|
2345
2516
|
path = path.replace("{variable_name}", str(variable_name))
|