auto-trainer-api 0.9.6__py3-none-any.whl → 0.9.7__py3-none-any.whl
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.
- {auto_trainer_api-0.9.6.dist-info → auto_trainer_api-0.9.7.dist-info}/METADATA +14 -2
- auto_trainer_api-0.9.7.dist-info/RECORD +16 -0
- autotrainer/api/__init__.py +2 -5
- autotrainer/api/api_event_kind.py +13 -0
- autotrainer/api/command/__init__.py +3 -0
- autotrainer/api/command/api_command.py +30 -0
- autotrainer/api/command/configuration_response.py +11 -0
- autotrainer/api/command/status_response.py +22 -0
- autotrainer/api/rpc_service.py +15 -24
- autotrainer/api/zeromq/zeromq_api_service.py +2 -1
- auto_trainer_api-0.9.6.dist-info/RECORD +0 -12
- {auto_trainer_api-0.9.6.dist-info → auto_trainer_api-0.9.7.dist-info}/WHEEL +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: auto-trainer-api
|
|
3
|
-
Version: 0.9.
|
|
3
|
+
Version: 0.9.7
|
|
4
4
|
Summary: API for interfacing with the core acquisition process via platform and language agnostic message queues.
|
|
5
5
|
License: AGPL-3.0-only
|
|
6
6
|
Classifier: Operating System :: OS Independent
|
|
@@ -83,7 +83,7 @@ The returned `ApiCommandRequestResponse` object contains one require field
|
|
|
83
83
|
* `result` - a value of `ApiCommandReqeustResult`
|
|
84
84
|
|
|
85
85
|
There are also three optional fields
|
|
86
|
-
* `data` - an optional
|
|
86
|
+
* `data` - an optional object with results from the command beyond success/failure (often will be None)
|
|
87
87
|
* `error_code` an integer error code value if the command is not successful or can't be initiated
|
|
88
88
|
* `error_message` an integer error code value if the command is not successful or can't be initiated
|
|
89
89
|
|
|
@@ -106,6 +106,18 @@ topic of `ApiTopic.COMMAND_RESULT`. The `message` argument of the `send_dict` m
|
|
|
106
106
|
received in the `ApiCommandRequest` (the client is responsible for storing these values until needed). Note that
|
|
107
107
|
those two properties are ignored for synchronous command handling, but required for asynchronous responses.
|
|
108
108
|
|
|
109
|
+
## Tools
|
|
110
|
+
|
|
111
|
+
### Client Application
|
|
112
|
+
`scripts/client_application.py` starts an interactive process that enables the `RpcService` as a "real" autotrainer
|
|
113
|
+
application would. It generates heartbeat events, can publish other events from the command line, and responds to
|
|
114
|
+
commands. This is primarily useful for testing remote applictions/services without running the main autotrainer
|
|
115
|
+
acquisition application.
|
|
116
|
+
|
|
117
|
+
### Remote Console
|
|
118
|
+
`scripts/remote_console.py` starts an interactive process that connects to an `RpcService` instance in the same manner
|
|
119
|
+
full remote management services would. Currently, it only supports sending a small subset of the predefined
|
|
120
|
+
`ApiCommand` values, but may be expanded to show events and send additional commands.
|
|
109
121
|
|
|
110
122
|
## Publishing
|
|
111
123
|
`python -m build`
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
autotrainer/api/__init__.py,sha256=SaDhy95qTzVH67pZ3qM0Uv86KoKP6Zh-V3VUHJqBBXo,686
|
|
2
|
+
autotrainer/api/api_event_kind.py,sha256=-suGV1kTS5gXrkOS2Yq_ahkyTgFhwhbPn8PcR7vT9CE,3647
|
|
3
|
+
autotrainer/api/api_options.py,sha256=LJrWqVe6JhYKw9UDL3uJcX4HTkwLW0STaNCGpPWRkoc,761
|
|
4
|
+
autotrainer/api/rpc_service.py,sha256=b1zseMu328sdPWJHazlfl_fC94iXy7zwmDwmv3rqNw0,18351
|
|
5
|
+
autotrainer/api/util.py,sha256=RfN6xMgCUahOz6RWMvSUkuw3mz0JEB2cpYoZBVdDY5M,1244
|
|
6
|
+
autotrainer/api/command/__init__.py,sha256=CPwRJSFU89XchwJhZ4Yw8ANYBDalb7uoMW63RxQ8NRQ,141
|
|
7
|
+
autotrainer/api/command/api_command.py,sha256=p5ymobZXBGiZt1RFwGZLaZnXgfZOPWTZg60Zra6fv_w,804
|
|
8
|
+
autotrainer/api/command/configuration_response.py,sha256=-V8vbZlgHFCwTNf3KTq5wqPWaysY2-SxdjKkUdrVVFQ,233
|
|
9
|
+
autotrainer/api/command/status_response.py,sha256=-Sq52Ebv8oIkzLhkIJdpgb3zKBqJXQ09aZZXTISfBQE,433
|
|
10
|
+
autotrainer/api/telemtry/__init__.py,sha256=gd013s0gvD2Wc-hj2tGkvQQGNR3u0f8ZGYxbYvITWfo,57
|
|
11
|
+
autotrainer/api/telemtry/open_telemetry_service.py,sha256=V-bDe_UX1I4iPtBgKV4R4tAAuGbsE3kyxGtr5ZD2mJc,2018
|
|
12
|
+
autotrainer/api/zeromq/__init__.py,sha256=L0txGZRsARnVMfuKpEg9E22WkiuoU1FRmzqMAQCqtf4,50
|
|
13
|
+
autotrainer/api/zeromq/zeromq_api_service.py,sha256=StThMM5JMu_Zua9_q9MzMM0xkQijyuABunADqq8yAKY,5029
|
|
14
|
+
auto_trainer_api-0.9.7.dist-info/METADATA,sha256=h6CvFJgjhRNpuK9debdIWVSvJWoqL2ntWq9kaytQ6cY,7065
|
|
15
|
+
auto_trainer_api-0.9.7.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
16
|
+
auto_trainer_api-0.9.7.dist-info/RECORD,,
|
autotrainer/api/__init__.py
CHANGED
|
@@ -4,18 +4,15 @@ API Service functionality for Autotrainer.
|
|
|
4
4
|
|
|
5
5
|
from typing import Optional
|
|
6
6
|
|
|
7
|
+
from .api_event_kind import ApiEventKind
|
|
8
|
+
from .command import ApiCommand, ConfigurationResponse, StatusResponse
|
|
7
9
|
from .api_options import ApiOptions, create_default_api_options
|
|
8
10
|
from .rpc_service import ApiTopic, ApiCommandRequest, ApiCommandRequestResponse, ApiCommandReqeustResult, RpcService
|
|
9
11
|
|
|
10
|
-
from .util import patch_uuid_encoder
|
|
11
|
-
|
|
12
12
|
|
|
13
13
|
def create_api_service(options: ApiOptions) -> Optional[RpcService]:
|
|
14
14
|
from .zeromq import ZeroMQApiService
|
|
15
15
|
|
|
16
|
-
# Several autotrainer messages may contain a UUID, which is not handled by the default JSON encoder.
|
|
17
|
-
# patch_uuid_encoder()
|
|
18
|
-
|
|
19
16
|
# TODO Enable when ready
|
|
20
17
|
# configure_telemetry(options.telemetry)
|
|
21
18
|
|
|
@@ -16,11 +16,20 @@ class ApiEventKind(IntEnum):
|
|
|
16
16
|
|
|
17
17
|
# Core/System
|
|
18
18
|
emergencyStop = 101
|
|
19
|
+
"""Payload {"reason": <string>}"""
|
|
19
20
|
emergencyResume = 102
|
|
21
|
+
"""Payload {"reason": <string>}"""
|
|
20
22
|
|
|
21
23
|
applicationLaunched = 201
|
|
22
24
|
applicationTerminating = 202
|
|
23
25
|
|
|
26
|
+
acquisitionStarted = 301
|
|
27
|
+
acquisitionEnded = 305
|
|
28
|
+
calibrationDcsStarted = 310
|
|
29
|
+
calibrationDcsEnded = 315
|
|
30
|
+
calibration3dStarted = 320
|
|
31
|
+
calibration3dEnded = 325
|
|
32
|
+
|
|
24
33
|
propertyChanged = 501
|
|
25
34
|
|
|
26
35
|
# Behavior
|
|
@@ -111,10 +120,14 @@ class ApiEventKind(IntEnum):
|
|
|
111
120
|
|
|
112
121
|
# Training
|
|
113
122
|
trainingModeChanged = 5001
|
|
123
|
+
"""Payload {"training_mode": ApiTrainingMode}"""
|
|
114
124
|
|
|
115
125
|
trainingPlanLoad = 5101
|
|
126
|
+
"""Payload {training_plan_id: <uuid of plan>}"""
|
|
116
127
|
|
|
117
128
|
trainingPhaseEnter = 5201
|
|
129
|
+
"""Payload {"training_phase_id": <uuid of plan>}"""
|
|
118
130
|
trainingPhaseExit = 5202
|
|
131
|
+
"""Payload {"training_phase_id": <uuid of plan>}"""
|
|
119
132
|
|
|
120
133
|
trainingProgressUpdate = 5501
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
from enum import IntEnum
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class ApiCommand(IntEnum):
|
|
5
|
+
"""
|
|
6
|
+
A command value is required for all command requests.
|
|
7
|
+
"""
|
|
8
|
+
NONE = 0
|
|
9
|
+
"""No command. Can be used to verify connection or that the receiver is configured to receive commands."""
|
|
10
|
+
|
|
11
|
+
START_ACQUISITION = 100
|
|
12
|
+
STOP_ACQUISITION = 110
|
|
13
|
+
|
|
14
|
+
EMERGENCY_STOP = 200
|
|
15
|
+
EMERGENCY_RESUME = 210
|
|
16
|
+
|
|
17
|
+
GET_CONFIGURATION = 300
|
|
18
|
+
"""Response Payload: ConfigurationResponse"""
|
|
19
|
+
|
|
20
|
+
GET_STATUS = 400
|
|
21
|
+
"""Response Payload: StatusResponse"""
|
|
22
|
+
|
|
23
|
+
USER_DEFINED = 99999
|
|
24
|
+
"""A custom command defined between a particular commander and receiver. Additional information can be
|
|
25
|
+
defined in the `data` field."""
|
|
26
|
+
|
|
27
|
+
@classmethod
|
|
28
|
+
def is_member(cls, value):
|
|
29
|
+
return value in cls._value2member_map_
|
|
30
|
+
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from enum import IntEnum
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class ApiAppStatus(IntEnum):
|
|
6
|
+
IDLE = 0
|
|
7
|
+
ACQUIRING = 100
|
|
8
|
+
CALIBRATION_DCS = 200
|
|
9
|
+
CALIBRATION_3D = 300
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class ApiTrainingMode(IntEnum):
|
|
13
|
+
UNDEFINED = 0
|
|
14
|
+
MANUAL = 100
|
|
15
|
+
MANUAL_WITH_PROTOCOL = 200
|
|
16
|
+
AUTOMATIC = 300
|
|
17
|
+
|
|
18
|
+
@dataclass
|
|
19
|
+
class StatusResponse:
|
|
20
|
+
app_status: ApiAppStatus
|
|
21
|
+
training_mode: ApiTrainingMode
|
|
22
|
+
animal_id: str
|
autotrainer/api/rpc_service.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import json
|
|
2
2
|
import logging
|
|
3
3
|
import time
|
|
4
|
-
from dataclasses import dataclass, asdict
|
|
4
|
+
from dataclasses import dataclass, asdict, is_dataclass
|
|
5
5
|
from enum import IntEnum
|
|
6
6
|
from queue import Queue, Empty
|
|
7
7
|
from threading import Timer, Thread
|
|
@@ -10,11 +10,16 @@ from typing_extensions import Self
|
|
|
10
10
|
|
|
11
11
|
import humps
|
|
12
12
|
|
|
13
|
+
from autotrainer.api.command.api_command import ApiCommand
|
|
13
14
|
from .api_event_kind import ApiEventKind
|
|
14
15
|
from .api_options import RpcOptions
|
|
15
16
|
|
|
16
17
|
logger = logging.getLogger(__name__)
|
|
17
18
|
|
|
19
|
+
import importlib.metadata
|
|
20
|
+
|
|
21
|
+
_heartbeat_version = importlib.metadata.version("auto-trainer-api")
|
|
22
|
+
|
|
18
23
|
|
|
19
24
|
class ApiTopic(IntEnum):
|
|
20
25
|
"""
|
|
@@ -40,25 +45,6 @@ class ApiTopic(IntEnum):
|
|
|
40
45
|
""" Responses to asynchronous command handling. """
|
|
41
46
|
|
|
42
47
|
|
|
43
|
-
class ApiCommand(IntEnum):
|
|
44
|
-
"""
|
|
45
|
-
A command value is required for all command requests.
|
|
46
|
-
"""
|
|
47
|
-
NONE = 0
|
|
48
|
-
START_ACQUISITION = 100
|
|
49
|
-
STOP_ACQUISITION = 110
|
|
50
|
-
EMERGENCY_STOP = 130
|
|
51
|
-
EMERGENCY_RESUME = 135
|
|
52
|
-
"""No command. Can be used to verify connection or that the receiver is configured to receive commands."""
|
|
53
|
-
USER_DEFINED = 99999
|
|
54
|
-
"""A custom command defined between a particular commander and receiver. Additional information can be
|
|
55
|
-
defined in the `data` field."""
|
|
56
|
-
|
|
57
|
-
@classmethod
|
|
58
|
-
def is_member(cls, value):
|
|
59
|
-
return value in cls._value2member_map_
|
|
60
|
-
|
|
61
|
-
|
|
62
48
|
@dataclass(frozen=True)
|
|
63
49
|
class ApiCommandRequest:
|
|
64
50
|
"""
|
|
@@ -136,7 +122,7 @@ NotificationEventKinds = [ApiEventKind.emergencyStop, ApiEventKind.emergencyResu
|
|
|
136
122
|
class ApiCommandRequestResponse:
|
|
137
123
|
result: ApiCommandReqeustResult
|
|
138
124
|
|
|
139
|
-
data: Optional[
|
|
125
|
+
data: Optional[Any] = None
|
|
140
126
|
|
|
141
127
|
error_code: int = 0
|
|
142
128
|
error_message: Optional[str] = None
|
|
@@ -264,7 +250,7 @@ class RpcService:
|
|
|
264
250
|
self._heartbeat_timer = None
|
|
265
251
|
self._heartbeat: HeartbeatMessage = HeartbeatMessage(
|
|
266
252
|
identifier=options.identifier,
|
|
267
|
-
version=
|
|
253
|
+
version=_heartbeat_version,
|
|
268
254
|
timestamp=0.0
|
|
269
255
|
)
|
|
270
256
|
|
|
@@ -394,10 +380,15 @@ class RpcService:
|
|
|
394
380
|
|
|
395
381
|
error_kind = ApiCommandRequestErrorKind.COMMAND_ERROR if client_response.error_code != 0 else ApiCommandRequestErrorKind.NONE
|
|
396
382
|
|
|
383
|
+
data = client_response.data
|
|
384
|
+
|
|
385
|
+
if data is not None and is_dataclass(data):
|
|
386
|
+
data = asdict(data)
|
|
387
|
+
|
|
397
388
|
self._send_command_response(
|
|
398
389
|
ApiCommandRequestServiceResponse(request.nonce, request.command, client_response.result,
|
|
399
|
-
|
|
400
|
-
client_response.
|
|
390
|
+
data, error_kind, client_response.error_code,
|
|
391
|
+
client_response.error_message))
|
|
401
392
|
except Exception as e:
|
|
402
393
|
self._send_command_response(
|
|
403
394
|
ApiCommandRequestServiceResponse.for_exception(request.command, request.nonce, e))
|
|
@@ -5,7 +5,8 @@ from typing import Optional
|
|
|
5
5
|
import zmq
|
|
6
6
|
import humps
|
|
7
7
|
|
|
8
|
-
from ..rpc_service import RpcService, RpcOptions, ApiTopic, ApiCommandRequestServiceResponse, ApiCommandRequest
|
|
8
|
+
from ..rpc_service import RpcService, RpcOptions, ApiTopic, ApiCommandRequestServiceResponse, ApiCommandRequest
|
|
9
|
+
from autotrainer.api.command.api_command import ApiCommand
|
|
9
10
|
from ..util import get_ip4_addr_str, UUIDEncoder
|
|
10
11
|
|
|
11
12
|
logger = logging.getLogger(__name__)
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
autotrainer/api/__init__.py,sha256=8GUKQ8L-gGgU8XlMztL88zwcjalregEVh__Mo6GGRg4,748
|
|
2
|
-
autotrainer/api/api_event_kind.py,sha256=cKwMDhlTUGY6SM_A1r2vWfHIDPRHYHtSDkWdTt9oDbs,3159
|
|
3
|
-
autotrainer/api/api_options.py,sha256=LJrWqVe6JhYKw9UDL3uJcX4HTkwLW0STaNCGpPWRkoc,761
|
|
4
|
-
autotrainer/api/rpc_service.py,sha256=1r7RFrSgsjfZSMunq1UgA8AEP6oLXF48waM8TC-OMI4,18628
|
|
5
|
-
autotrainer/api/util.py,sha256=RfN6xMgCUahOz6RWMvSUkuw3mz0JEB2cpYoZBVdDY5M,1244
|
|
6
|
-
autotrainer/api/telemtry/__init__.py,sha256=gd013s0gvD2Wc-hj2tGkvQQGNR3u0f8ZGYxbYvITWfo,57
|
|
7
|
-
autotrainer/api/telemtry/open_telemetry_service.py,sha256=V-bDe_UX1I4iPtBgKV4R4tAAuGbsE3kyxGtr5ZD2mJc,2018
|
|
8
|
-
autotrainer/api/zeromq/__init__.py,sha256=L0txGZRsARnVMfuKpEg9E22WkiuoU1FRmzqMAQCqtf4,50
|
|
9
|
-
autotrainer/api/zeromq/zeromq_api_service.py,sha256=WiG7B7rFJNESdDZhzxkmvHY03ei5T9PXeNgRFhJUTjg,4981
|
|
10
|
-
auto_trainer_api-0.9.6.dist-info/METADATA,sha256=3P0jS8siCnK0uIw9MyIjvPfVSq7sPnZV3DozRmPgs8g,6332
|
|
11
|
-
auto_trainer_api-0.9.6.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
12
|
-
auto_trainer_api-0.9.6.dist-info/RECORD,,
|
|
File without changes
|