motorcortex-python 1.0.3__py3-none-any.whl → 1.2.0__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.
- motorcortex/__init__.py +1 -1
- motorcortex/_request_utils.py +57 -0
- motorcortex/_sp_stream.py +331 -0
- motorcortex/motorcortex_hash.json +17 -1
- motorcortex/motorcortex_pb2.py +69 -61
- motorcortex/motorcortex_pb2.pyi +161 -1
- motorcortex/request.py +39 -0
- motorcortex/subscribe.py +347 -171
- motorcortex/subscription.py +82 -6
- motorcortex/version.py +1 -1
- {motorcortex_python-1.0.3.dist-info → motorcortex_python-1.2.0.dist-info}/METADATA +19 -1
- {motorcortex_python-1.0.3.dist-info → motorcortex_python-1.2.0.dist-info}/RECORD +15 -14
- {motorcortex_python-1.0.3.dist-info → motorcortex_python-1.2.0.dist-info}/WHEEL +1 -1
- {motorcortex_python-1.0.3.dist-info → motorcortex_python-1.2.0.dist-info}/LICENSE +0 -0
- {motorcortex_python-1.0.3.dist-info → motorcortex_python-1.2.0.dist-info}/top_level.txt +0 -0
motorcortex/__init__.py
CHANGED
|
@@ -286,7 +286,7 @@ def connect(
|
|
|
286
286
|
state_update (Callable, optional): Custom callback for connection state changes.
|
|
287
287
|
If provided, disables the built-in reconnect logic.
|
|
288
288
|
req_number_of_threads (int, optional): Thread pool size for request connection. Defaults to 2.
|
|
289
|
-
sub_number_of_threads (int, optional): Thread pool size for subscribe connection. Defaults to 2.
|
|
289
|
+
sub_number_of_threads (int, optional): Thread pool size for subscribe connection. Defaults to 2, clamped up to the minimum of 4 that ``Subscribe`` requires (connect worker, recv loop, reconnect loop, subscription updaters).
|
|
290
290
|
|
|
291
291
|
Returns:
|
|
292
292
|
tuple: (req, sub)
|
motorcortex/_request_utils.py
CHANGED
|
@@ -19,6 +19,7 @@ import hashlib
|
|
|
19
19
|
import json
|
|
20
20
|
import os
|
|
21
21
|
import tempfile
|
|
22
|
+
import zlib
|
|
22
23
|
from threading import Event
|
|
23
24
|
from typing import Any, Callable, Optional, Tuple
|
|
24
25
|
|
|
@@ -135,6 +136,26 @@ def fetch_parameter_tree(
|
|
|
135
136
|
Returns:
|
|
136
137
|
A ``ParameterTreeMsg`` — either the cached one or the freshly
|
|
137
138
|
fetched one (also persisted to the cache).
|
|
139
|
+
|
|
140
|
+
On a cache miss, a compressed tree is tried first
|
|
141
|
+
(``motorcortex-core >= 2.36.0``): a single zlib/deflate blob,
|
|
142
|
+
typically 7-13x smaller than the plain reply. The server deflates
|
|
143
|
+
the *full wire reply* — a 4-byte little-endian type-hash prefix
|
|
144
|
+
followed by the ``ParameterTreeMsg`` body, same as any other RPC
|
|
145
|
+
reply — so the inflated blob goes through the canonical
|
|
146
|
+
``MessageTypes.decode()``, which strips the prefix and resolves the
|
|
147
|
+
type by hash. Any failure — timeout on an old server that silently
|
|
148
|
+
drops the unrecognised request hash, a non-OK status from a
|
|
149
|
+
2.36.1-2.38 core, an unknown or unexpected type hash, or an
|
|
150
|
+
inflate/parse error — falls through to the plain
|
|
151
|
+
``GetParameterTreeMsg`` request. Both paths decode to the same
|
|
152
|
+
``ParameterTreeMsg`` type, so callers (and the cache write below)
|
|
153
|
+
can't tell the difference. Tried for every URL scheme (ipc, tcp,
|
|
154
|
+
ws, tls+tcp, wss) — the request is just bytes over
|
|
155
|
+
:func:`send_and_recv`. ``send_and_recv`` in this repo has no
|
|
156
|
+
per-call timeout knob, so on an old server the compressed attempt
|
|
157
|
+
costs at most one ``recv_timeout`` (the socket's own) before
|
|
158
|
+
falling back.
|
|
138
159
|
"""
|
|
139
160
|
path = parameter_tree_cache_path(url, tree_hash)
|
|
140
161
|
cached = load_parameter_tree_file(path, protobuf_types)
|
|
@@ -143,6 +164,42 @@ def fetch_parameter_tree(
|
|
|
143
164
|
return cached
|
|
144
165
|
logger.debug("[REQUEST] Failed to find parameter tree in the cache")
|
|
145
166
|
|
|
167
|
+
try:
|
|
168
|
+
compressed_request = protobuf_types.createType(
|
|
169
|
+
"motorcortex.GetParameterTreeCompressedMsg")
|
|
170
|
+
compressed_reply = send_and_recv(
|
|
171
|
+
socket, protobuf_types.encode(compressed_request), protobuf_types)
|
|
172
|
+
if compressed_reply is not None \
|
|
173
|
+
and getattr(compressed_reply, "status", 1) == 0 \
|
|
174
|
+
and getattr(compressed_reply, "compressed", b""):
|
|
175
|
+
# The server deflates the *full wire reply* here, not a bare
|
|
176
|
+
# ParameterTreeMsg: inflating yields the same hash-prefixed
|
|
177
|
+
# framing every other RPC reply uses (matches the message's
|
|
178
|
+
# own docstring: "the exact bytes a GetParameterTreeMsg reply
|
|
179
|
+
# carries"). Run it through the canonical decode() — which
|
|
180
|
+
# strips the type-hash prefix and resolves the type by hash —
|
|
181
|
+
# instead of ParseFromString on the raw blob; parsing the blob
|
|
182
|
+
# directly is exactly the bug this branch used to have: the
|
|
183
|
+
# prefix corrupted every parse and silently forced the plain
|
|
184
|
+
# fallback. An unknown hash (KeyError in decode) or a decode
|
|
185
|
+
# to some other type falls through to the plain request rather
|
|
186
|
+
# than caching garbage as a ParameterTreeMsg.
|
|
187
|
+
tree_msg = protobuf_types.decode(
|
|
188
|
+
zlib.decompress(compressed_reply.compressed))
|
|
189
|
+
decoded_name = getattr(
|
|
190
|
+
getattr(tree_msg, "DESCRIPTOR", None), "full_name", None)
|
|
191
|
+
if decoded_name != "motorcortex.ParameterTreeMsg":
|
|
192
|
+
raise ValueError(
|
|
193
|
+
"compressed tree decoded to unexpected type "
|
|
194
|
+
f"{decoded_name or type(tree_msg).__name__}")
|
|
195
|
+
logger.debug("[REQUEST] parameter tree fetched compressed")
|
|
196
|
+
return save_parameter_tree_file(path, tree_msg)
|
|
197
|
+
except Exception as e:
|
|
198
|
+
logger.debug(
|
|
199
|
+
"[REQUEST] compressed tree unavailable (%s: %s) — falling back to plain",
|
|
200
|
+
type(e).__name__, e,
|
|
201
|
+
)
|
|
202
|
+
|
|
146
203
|
request_msg = protobuf_types.createType("motorcortex.GetParameterTreeMsg")
|
|
147
204
|
handle = send_and_recv(socket, protobuf_types.encode(request_msg), protobuf_types)
|
|
148
205
|
return save_parameter_tree_file(path, handle)
|
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
#!/usr/bin/python3
|
|
2
|
+
#
|
|
3
|
+
# Developer: Alexey Zakharov (alexey.zakharov@vectioneer.com)
|
|
4
|
+
# All rights reserved. Copyright (c) 2016-2026 VECTIONEER.
|
|
5
|
+
#
|
|
6
|
+
"""Stream-based SP (nanomsg) pub/sub client transport.
|
|
7
|
+
|
|
8
|
+
Replaces the pynng ``Sub0`` socket for the subscribe data channel so the
|
|
9
|
+
client can send the routing hello as the first upstream message — a raw
|
|
10
|
+
``nng_stream`` has no protocol layer, so we speak the SP wire format
|
|
11
|
+
ourselves. Uses only pynng's bundled cffi bindings (``pynng._nng``): the
|
|
12
|
+
full public ``nng_stream_* / nng_aio_*`` API ships in every pynng wheel.
|
|
13
|
+
|
|
14
|
+
Wire format per scheme (mirrors motorcortex-cpp src/sp_stream.cpp, which
|
|
15
|
+
is the proven reference — see its comments for the full rationale):
|
|
16
|
+
|
|
17
|
+
- ws/wss: subprotocol ``pub.sp.nanomsg.org`` on the HTTP upgrade;
|
|
18
|
+
message mode — one send/recv is one SP message, no length
|
|
19
|
+
prefix, no byte handshake.
|
|
20
|
+
- tcp/tls: 8-byte handshake ``\\x00SP\\x00`` + u16-BE proto + u16-BE 0
|
|
21
|
+
(we announce 33/sub, require peer 32/pub), then each message
|
|
22
|
+
is a u64-BE length prefix + body.
|
|
23
|
+
- ipc: same handshake, but a 9-byte per-message header: type byte
|
|
24
|
+
``0x01`` + u64-BE length. The type byte is load-bearing.
|
|
25
|
+
|
|
26
|
+
nng 1.11.0 caveat (learned in cpp): never ``nng_aio_cancel`` an aio on a
|
|
27
|
+
raw TLS stream — it crashes ``nng_stream_close`` intermittently. This
|
|
28
|
+
implementation never cancels: every aio is owned by exactly one blocking
|
|
29
|
+
call which waits for it to finish (success, error, or timeout) before
|
|
30
|
+
freeing it. Closing the stream from another thread makes a pending recv
|
|
31
|
+
finish with an error, which is the supported wakeup path.
|
|
32
|
+
|
|
33
|
+
Stream lifetime vs. concurrent close(): a bare local capture of
|
|
34
|
+
``self._stream`` before an nng call is not enough — close() both nulls
|
|
35
|
+
the attribute *and* frees the underlying stream, so a racing capture can
|
|
36
|
+
still end up handing a freed pointer to nng between close()'s two steps.
|
|
37
|
+
Every blocking nng call therefore goes through ``_issue()``, which
|
|
38
|
+
captures the stream, increments ``_io_inflight``, AND actually calls
|
|
39
|
+
``nng_stream_send``/``nng_stream_recv`` — all under ``_io_cond`` in one
|
|
40
|
+
atomic step (not just the capture: an earlier version issued the nng
|
|
41
|
+
call *after* releasing the lock, which left a window where
|
|
42
|
+
``nng_stream_close`` could run first and the op would then be issued
|
|
43
|
+
against an already-closed stream — nng accepts that silently and never
|
|
44
|
+
completes it, hanging ``nng_aio_wait`` forever when the aio has no
|
|
45
|
+
timeout of its own, i.e. exactly ``recv_msg()``'s default). close() sets
|
|
46
|
+
``_closing``/nulls ``self._stream`` under the same lock, calls
|
|
47
|
+
``nng_stream_close`` (which wakes any pending aio — pending meaning
|
|
48
|
+
already issued, which ``_issue()`` now guarantees), and only frees the
|
|
49
|
+
stream once ``_io_inflight`` drops back to zero. That ordering — close,
|
|
50
|
+
then wait for in-flight callers to finish with the local pointer they
|
|
51
|
+
already captured, then free — is what makes the free race-free without
|
|
52
|
+
ever touching ``nng_aio_cancel``.
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
import struct
|
|
56
|
+
import threading
|
|
57
|
+
from typing import Optional
|
|
58
|
+
|
|
59
|
+
from pynng._nng import ffi, lib # type: ignore[import-untyped]
|
|
60
|
+
from pynng.exceptions import check_err # type: ignore[import-untyped]
|
|
61
|
+
|
|
62
|
+
from motorcortex.setup_logger import logger
|
|
63
|
+
|
|
64
|
+
_SP_PROTO_SUB = 33
|
|
65
|
+
_SP_PROTO_PUB = 32
|
|
66
|
+
_HANDSHAKE_LEN = 8
|
|
67
|
+
|
|
68
|
+
#: One recv buffer per stream in ws message mode. nng's ws transport caps
|
|
69
|
+
#: read-ahead at one frame and the server pipe buffer is 1 MiB, so a
|
|
70
|
+
#: larger message cannot arrive whole (it would be truncated server-side
|
|
71
|
+
#: first). Mirrors WS_MAX_MSG in cpp sp_stream.h.
|
|
72
|
+
WS_MAX_MSG = 1 << 20
|
|
73
|
+
|
|
74
|
+
#: Refuse absurd length prefixes on byte-stream schemes (64 MiB).
|
|
75
|
+
_MAX_BODY = 1 << 26
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
class SpStreamError(Exception):
|
|
79
|
+
"""Transport-level failure on the SP stream."""
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
class SpProtocolError(SpStreamError):
|
|
83
|
+
"""Peer completed the byte handshake but is not an SP pub (32)."""
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def _tls_pointer(tls_config):
|
|
87
|
+
"""Raw ``nng_tls_config *`` out of a pynng TLSConfig.
|
|
88
|
+
|
|
89
|
+
``TLSConfig._tls_config`` is private but stable across pynng 0.9.x;
|
|
90
|
+
isolate the access here so a pynng bump touches one line.
|
|
91
|
+
"""
|
|
92
|
+
return tls_config._tls_config
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def _alloc_aio(timeout_ms: int):
|
|
96
|
+
ap = ffi.new("nng_aio **")
|
|
97
|
+
check_err(lib.nng_aio_alloc(ap, ffi.NULL, ffi.NULL))
|
|
98
|
+
aio = ap[0]
|
|
99
|
+
lib.nng_aio_set_timeout(aio, timeout_ms if timeout_ms > 0 else -1)
|
|
100
|
+
return aio
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
class SpStream:
|
|
104
|
+
def __init__(self) -> None:
|
|
105
|
+
self._dialer = None
|
|
106
|
+
self._stream = None
|
|
107
|
+
self._ws_mode = False
|
|
108
|
+
self._ipc_mode = False
|
|
109
|
+
self._recv_buf = None # allocated lazily in Task 2
|
|
110
|
+
# Guards the stream-lifetime TOCTOU between a live nng call and a
|
|
111
|
+
# concurrent close(); see the module docstring.
|
|
112
|
+
self._io_cond = threading.Condition()
|
|
113
|
+
self._io_inflight = 0
|
|
114
|
+
self._closing = False
|
|
115
|
+
|
|
116
|
+
@property
|
|
117
|
+
def connected(self) -> bool:
|
|
118
|
+
return self._stream is not None
|
|
119
|
+
|
|
120
|
+
def connect(self, url: str, tls_config=None, timeout_ms: int = 5000) -> None:
|
|
121
|
+
"""Dial + (non-ws) SP handshake. Raises on any failure; the
|
|
122
|
+
stream is fully closed again before an exception propagates."""
|
|
123
|
+
self.close()
|
|
124
|
+
# Re-arm under _io_cond, only after close() fully completed, so
|
|
125
|
+
# the flag flip is atomic against a concurrent close()'s own
|
|
126
|
+
# locked ``_closing = True`` transition (a close() racing the
|
|
127
|
+
# reopen after this point is caught by Subscribe's ``_closed``
|
|
128
|
+
# re-checks, which close any stream dialed past it).
|
|
129
|
+
with self._io_cond:
|
|
130
|
+
self._closing = False
|
|
131
|
+
self._ws_mode = url.startswith("ws://") or url.startswith("wss://")
|
|
132
|
+
self._ipc_mode = url.startswith("ipc://")
|
|
133
|
+
|
|
134
|
+
dp = ffi.new("nng_stream_dialer **")
|
|
135
|
+
check_err(lib.nng_stream_dialer_alloc(dp, url.encode()))
|
|
136
|
+
self._dialer = dp[0]
|
|
137
|
+
try:
|
|
138
|
+
if self._ws_mode:
|
|
139
|
+
# mcxpub0 keeps stock pub0's SP wire name, so every
|
|
140
|
+
# existing client's subprotocol offer is accepted.
|
|
141
|
+
check_err(lib.nng_stream_dialer_set_string(
|
|
142
|
+
self._dialer, b"ws:protocol", b"pub.sp.nanomsg.org"))
|
|
143
|
+
if tls_config is not None:
|
|
144
|
+
check_err(lib.nng_stream_dialer_set_ptr(
|
|
145
|
+
self._dialer, b"tls-config", _tls_pointer(tls_config)))
|
|
146
|
+
|
|
147
|
+
aio = _alloc_aio(timeout_ms)
|
|
148
|
+
lib.nng_stream_dialer_dial(self._dialer, aio)
|
|
149
|
+
lib.nng_aio_wait(aio)
|
|
150
|
+
rv = lib.nng_aio_result(aio)
|
|
151
|
+
if rv == 0:
|
|
152
|
+
self._stream = ffi.cast(
|
|
153
|
+
"nng_stream *", lib.nng_aio_get_output(aio, 0))
|
|
154
|
+
lib.nng_aio_free(aio)
|
|
155
|
+
check_err(rv)
|
|
156
|
+
|
|
157
|
+
if not self._ws_mode:
|
|
158
|
+
self._handshake(timeout_ms)
|
|
159
|
+
except Exception:
|
|
160
|
+
self.close()
|
|
161
|
+
raise
|
|
162
|
+
|
|
163
|
+
def _handshake(self, timeout_ms: int) -> None:
|
|
164
|
+
ours = b"\x00SP\x00" + struct.pack(">H", _SP_PROTO_SUB) + b"\x00\x00"
|
|
165
|
+
self._io(True, ours, timeout_ms)
|
|
166
|
+
peer = self._io(False, _HANDSHAKE_LEN, timeout_ms)
|
|
167
|
+
expected = b"\x00SP\x00" + struct.pack(">H", _SP_PROTO_PUB) + b"\x00\x00"
|
|
168
|
+
if peer[:6] != expected[:6]:
|
|
169
|
+
raise SpProtocolError(
|
|
170
|
+
f"peer is not an SP pub socket (got {peer!r})")
|
|
171
|
+
|
|
172
|
+
def send_msg(self, data: bytes, timeout_ms: int = 2000) -> None:
|
|
173
|
+
if self._stream is None:
|
|
174
|
+
raise SpStreamError("send on a closed SpStream")
|
|
175
|
+
if self._ws_mode:
|
|
176
|
+
self._io(True, data, timeout_ms) # message mode: 1 send = 1 msg
|
|
177
|
+
return
|
|
178
|
+
prefix = struct.pack(">Q", len(data))
|
|
179
|
+
if self._ipc_mode:
|
|
180
|
+
prefix = b"\x01" + prefix # load-bearing type byte
|
|
181
|
+
self._io(True, prefix, timeout_ms)
|
|
182
|
+
self._io(True, data, timeout_ms)
|
|
183
|
+
|
|
184
|
+
def _issue(self, op, buf, offset: int, length: int, timeout_ms: int):
|
|
185
|
+
"""Allocate an aio, set its iov, and hand it to ``op`` (a raw
|
|
186
|
+
``nng_stream_send``/``nng_stream_recv`` — the *call*, not just
|
|
187
|
+
the registration) — all atomically under ``_io_cond``.
|
|
188
|
+
|
|
189
|
+
This has to be one critical section, not "capture the stream,
|
|
190
|
+
release the lock, then call ``op``" (the original shape): a
|
|
191
|
+
concurrent ``close()`` also serializes on ``_io_cond`` for its
|
|
192
|
+
own ``_closing = True`` transition, so whichever of the two
|
|
193
|
+
critical sections runs first fully determines a safe outcome —
|
|
194
|
+
either the op is issued while the stream is still known-open
|
|
195
|
+
(and ``close()``'s later ``nng_stream_close()`` correctly wakes
|
|
196
|
+
it, per nng's contract for *already-registered* ops), or
|
|
197
|
+
``close()`` has already flipped ``_closing`` and this call bails
|
|
198
|
+
out before ever touching nng. The two-step version left a gap
|
|
199
|
+
between "session granted" / "op actually issued" that
|
|
200
|
+
``close()`` could land in: ``nng_stream_close()`` running before
|
|
201
|
+
``nng_stream_recv()``/``nng_stream_send()`` for that same aio
|
|
202
|
+
leaves it waiting forever — with a finite ``timeout_ms`` the
|
|
203
|
+
aio's own timer eventually rescues it, but ``recv_msg()``'s
|
|
204
|
+
default infinite timeout (the receive loop's steady state) has
|
|
205
|
+
no such backstop, so this used to hang the process instead of
|
|
206
|
+
surfacing the intended "stream closed" `None`.
|
|
207
|
+
|
|
208
|
+
Raises ``SpStreamError`` (stream already closing/closed) or lets
|
|
209
|
+
an ``nng_aio_set_iov`` failure propagate — in both cases nothing
|
|
210
|
+
was issued and ``_io_inflight`` was never incremented, so the
|
|
211
|
+
caller has nothing to undo. On success returns the aio with
|
|
212
|
+
``_io_inflight`` already bumped; the caller owns freeing it and
|
|
213
|
+
decrementing the counter once the op settles.
|
|
214
|
+
"""
|
|
215
|
+
with self._io_cond:
|
|
216
|
+
if self._closing or self._stream is None:
|
|
217
|
+
raise SpStreamError("stream closed mid-transfer")
|
|
218
|
+
stream = self._stream
|
|
219
|
+
aio = _alloc_aio(timeout_ms)
|
|
220
|
+
try:
|
|
221
|
+
iov = ffi.new("nng_iov *")
|
|
222
|
+
iov.iov_buf = buf + offset
|
|
223
|
+
iov.iov_len = length
|
|
224
|
+
check_err(lib.nng_aio_set_iov(aio, 1, iov))
|
|
225
|
+
except Exception:
|
|
226
|
+
lib.nng_aio_free(aio)
|
|
227
|
+
raise
|
|
228
|
+
self._io_inflight += 1
|
|
229
|
+
op(stream, aio)
|
|
230
|
+
return aio
|
|
231
|
+
|
|
232
|
+
def _settle(self, aio):
|
|
233
|
+
"""Wait for an ``_issue()``-returned aio outside the lock (the
|
|
234
|
+
blocking part must never hold ``_io_cond`` — that would stall
|
|
235
|
+
``close()``'s own attempt to grab it), then release the
|
|
236
|
+
in-flight slot. Returns ``(rv, got)``."""
|
|
237
|
+
try:
|
|
238
|
+
lib.nng_aio_wait(aio)
|
|
239
|
+
rv = lib.nng_aio_result(aio)
|
|
240
|
+
got = lib.nng_aio_count(aio) if rv == 0 else 0
|
|
241
|
+
finally:
|
|
242
|
+
lib.nng_aio_free(aio)
|
|
243
|
+
with self._io_cond:
|
|
244
|
+
self._io_inflight -= 1
|
|
245
|
+
self._io_cond.notify_all()
|
|
246
|
+
return rv, got
|
|
247
|
+
|
|
248
|
+
def _io(self, is_send: bool, data_or_len, timeout_ms: int):
|
|
249
|
+
"""Blocking send of ``bytes`` / recv of exactly N bytes.
|
|
250
|
+
One aio per call; always waited on, never cancelled. Every nng
|
|
251
|
+
call is issued via ``_issue()`` so it can't race a concurrent
|
|
252
|
+
close() into hanging (see its docstring)."""
|
|
253
|
+
if is_send:
|
|
254
|
+
buf = ffi.new("uint8_t[]", bytes(data_or_len))
|
|
255
|
+
need = len(data_or_len)
|
|
256
|
+
else:
|
|
257
|
+
need = int(data_or_len)
|
|
258
|
+
buf = ffi.new("uint8_t[]", need)
|
|
259
|
+
op = lib.nng_stream_send if is_send else lib.nng_stream_recv
|
|
260
|
+
done = 0
|
|
261
|
+
while done < need:
|
|
262
|
+
aio = self._issue(op, buf, done, need - done, timeout_ms)
|
|
263
|
+
rv, got = self._settle(aio)
|
|
264
|
+
if rv != 0:
|
|
265
|
+
check_err(rv)
|
|
266
|
+
if got == 0:
|
|
267
|
+
raise SpStreamError("stream closed mid-transfer")
|
|
268
|
+
done += got
|
|
269
|
+
return None if is_send else bytes(ffi.buffer(buf, need))
|
|
270
|
+
|
|
271
|
+
def recv_msg(self, timeout_ms: int = -1) -> Optional[bytes]:
|
|
272
|
+
"""Block for one whole SP message.
|
|
273
|
+
|
|
274
|
+
Returns ``None`` when the stream is closed/dead (remote close,
|
|
275
|
+
local close() from another thread, desync) — the receive loop's
|
|
276
|
+
exit signal. The ws invariant (nng caps ws read-ahead at one
|
|
277
|
+
frame) means one recv into a WS_MAX_MSG buffer is exactly one
|
|
278
|
+
message; byte-stream schemes reassemble via the length prefix.
|
|
279
|
+
"""
|
|
280
|
+
if self._stream is None:
|
|
281
|
+
return None
|
|
282
|
+
try:
|
|
283
|
+
if self._ws_mode:
|
|
284
|
+
return self._recv_ws(timeout_ms)
|
|
285
|
+
hdr_len = 9 if self._ipc_mode else 8
|
|
286
|
+
hdr = self._io(False, hdr_len, timeout_ms)
|
|
287
|
+
if self._ipc_mode:
|
|
288
|
+
if hdr[0] != 0x01:
|
|
289
|
+
logger.error("[SPSTREAM] ipc type-byte desync (0x%02x)", hdr[0])
|
|
290
|
+
return None
|
|
291
|
+
hdr = hdr[1:]
|
|
292
|
+
(length,) = struct.unpack(">Q", hdr)
|
|
293
|
+
if length == 0 or length > _MAX_BODY:
|
|
294
|
+
logger.error("[SPSTREAM] absurd frame length %d — desync", length)
|
|
295
|
+
return None
|
|
296
|
+
return self._io(False, length, timeout_ms)
|
|
297
|
+
except Exception as e:
|
|
298
|
+
logger.debug("[SPSTREAM] recv_msg terminating: %s", e)
|
|
299
|
+
return None
|
|
300
|
+
|
|
301
|
+
def _recv_ws(self, timeout_ms: int) -> Optional[bytes]:
|
|
302
|
+
if self._recv_buf is None:
|
|
303
|
+
self._recv_buf = ffi.new("uint8_t[]", WS_MAX_MSG)
|
|
304
|
+
try:
|
|
305
|
+
aio = self._issue(lib.nng_stream_recv, self._recv_buf, 0, WS_MAX_MSG, timeout_ms)
|
|
306
|
+
except Exception:
|
|
307
|
+
return None
|
|
308
|
+
rv, got = self._settle(aio)
|
|
309
|
+
if rv != 0 or got == 0:
|
|
310
|
+
return None
|
|
311
|
+
return bytes(ffi.buffer(self._recv_buf, got))
|
|
312
|
+
|
|
313
|
+
def close(self) -> None:
|
|
314
|
+
with self._io_cond:
|
|
315
|
+
self._closing = True
|
|
316
|
+
stream, self._stream = self._stream, None
|
|
317
|
+
dialer, self._dialer = self._dialer, None
|
|
318
|
+
if stream is not None:
|
|
319
|
+
lib.nng_stream_close(stream) # wakes any pending recv/send
|
|
320
|
+
# Wait for every in-flight _issue()/_settle() caller to
|
|
321
|
+
# finish with the (now-closed, error-returning) stream
|
|
322
|
+
# pointer it already captured before we free it — this is
|
|
323
|
+
# what makes the free race-free; see module docstring and
|
|
324
|
+
# _issue()'s docstring for why issuing the op is folded into
|
|
325
|
+
# the same critical section as this ``_closing`` flip.
|
|
326
|
+
with self._io_cond:
|
|
327
|
+
while self._io_inflight > 0:
|
|
328
|
+
self._io_cond.wait()
|
|
329
|
+
lib.nng_stream_free(stream)
|
|
330
|
+
if dialer is not None:
|
|
331
|
+
lib.nng_stream_dialer_free(dialer)
|
|
@@ -43,6 +43,14 @@
|
|
|
43
43
|
"type": "motorcortex.SessionTokenMsg",
|
|
44
44
|
"hash": "0x7c3e91ab"
|
|
45
45
|
},
|
|
46
|
+
{
|
|
47
|
+
"type": "motorcortex.GetSubCookieMsg",
|
|
48
|
+
"hash": "0x5505c0b0"
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"type": "motorcortex.SubCookieMsg",
|
|
52
|
+
"hash": "0x90ff084b"
|
|
53
|
+
},
|
|
46
54
|
{
|
|
47
55
|
"type": "motorcortex.RestoreSessionMsg",
|
|
48
56
|
"hash": "0x8aef888a"
|
|
@@ -67,6 +75,14 @@
|
|
|
67
75
|
"type": "motorcortex.ParameterTreeHashMsg",
|
|
68
76
|
"hash": "0xc8cef26b"
|
|
69
77
|
},
|
|
78
|
+
{
|
|
79
|
+
"type": "motorcortex.GetParameterTreeCompressedMsg",
|
|
80
|
+
"hash": "0x2347001b"
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"type": "motorcortex.CompressedParameterTreeMsg",
|
|
84
|
+
"hash": "0x769fb6e8"
|
|
85
|
+
},
|
|
70
86
|
{
|
|
71
87
|
"type": "motorcortex.CreateGroupMsg",
|
|
72
88
|
"hash": "0x9eab1b83"
|
|
@@ -149,7 +165,7 @@
|
|
|
149
165
|
},
|
|
150
166
|
{
|
|
151
167
|
"type": "motorcortex.StatusCode",
|
|
152
|
-
"hash": "
|
|
168
|
+
"hash": "0x6a1f3a02"
|
|
153
169
|
},
|
|
154
170
|
{
|
|
155
171
|
"type": "motorcortex.ErrorLevel",
|
motorcortex/motorcortex_pb2.py
CHANGED
|
@@ -13,31 +13,31 @@ _sym_db = _symbol_database.Default()
|
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
|
|
16
|
-
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x11motorcortex.proto\x12\x0bmotorcortex\"i\n\x0fParameterOffset\x12\x36\n\x04type\x18\x01 \x02(\x0e\x32\x17.motorcortex.OffsetType:\x0fOFFSET_ELEMENTS\x12\x0e\n\x06offset\x18\x02 \x02(\r\x12\x0e\n\x06length\x18\x03 \x02(\r\"f\n\x05\x45rror\x12\x11\n\ttimestamp\x18\x01 \x02(\x06\x12\x14\n\x0c\x65rror_number\x18\x02 \x02(\x07\x12\x13\n\x0b\x65rror_level\x18\x03 \x02(\x07\x12\x11\n\tsubsystem\x18\x04 \x02(\x07\x12\x0c\n\x04info\x18\x05 \x02(\x07\"a\n\tErrorList\x12\"\n\x06\x65rrors\x18\x01 \x03(\x0b\x32\x12.motorcortex.Error\x12\x18\n\x10number_of_errors\x18\x02 \x02(\x07\x12\x16\n\x0eupdate_counter\x18\x03 \x02(\x07\"\x8a\x02\n\rParameterInfo\x12\n\n\x02id\x18\x01 \x02(\r\x12\x11\n\tdata_type\x18\x02 \x02(\r\x12\x11\n\tdata_size\x18\x03 \x02(\r\x12\x1a\n\x12number_of_elements\x18\x04 \x02(\r\x12\r\n\x05\x66lags\x18\x05 \x02(\r\x12\x13\n\x0bpermissions\x18\x06 \x02(\r\x12.\n\nparam_type\x18\x07 \x02(\x0e\x32\x1a.motorcortex.ParameterType\x12(\n\x08group_id\x18\x08 \x02(\x0e\x32\x16.motorcortex.UserGroup\x12\x1f\n\x04unit\x18\t \x02(\x0e\x32\x11.motorcortex.Unit\x12\x0c\n\x04path\x18\n \x02(\t\"\x94\x01\n\x12GroupParameterInfo\x12\r\n\x05index\x18\x01 \x02(\r\x12\x0e\n\x06offset\x18\x02 \x02(\r\x12\x0c\n\x04size\x18\x03 \x02(\r\x12(\n\x04info\x18\x04 \x02(\x0b\x32\x1a.motorcortex.ParameterInfo\x12\'\n\x06status\x18\x05 \x02(\x0e\x32\x17.motorcortex.StatusCode\"1\n\x06Header\x12\x14\n\x0c\x66rameCounter\x18\x01 \x02(\x07\x12\x11\n\ttimestamp\x18\x02 \x02(\x06\"Z\n\x08GroupMsg\x12#\n\x06header\x18\x01 \x01(\x0b\x32\x13.motorcortex.Header\x12)\n\x06params\x18\x02 \x03(\x0b\x32\x19.motorcortex.ParameterMsg\"Y\n\tStatusMsg\x12#\n\x06header\x18\x01 \x01(\x0b\x32\x13.motorcortex.Header\x12\'\n\x06status\x18\x02 \x02(\x0e\x32\x17.motorcortex.StatusCode\"P\n\x08LoginMsg\x12#\n\x06header\x18\x01 \x01(\x0b\x32\x13.motorcortex.Header\x12\r\n\x05login\x18\x02 \x02(\t\x12\x10\n\x08password\x18\x03 \x02(\t\"9\n\x12GetSessionTokenMsg\x12#\n\x06header\x18\x01 \x01(\x0b\x32\x13.motorcortex.Header\"n\n\x0fSessionTokenMsg\x12#\n\x06header\x18\x01 \x01(\x0b\x32\x13.motorcortex.Header\x12\r\n\x05token\x18\x02 \x02(\t\x12\'\n\x06status\x18\x03 \x02(\x0e\x32\x17.motorcortex.StatusCode\"G\n\x11RestoreSessionMsg\x12#\n\x06header\x18\x01 \x01(\x0b\x32\x13.motorcortex.Header\x12\r\n\x05token\x18\x02 \x02(\t\"0\n\tLogoutMsg\x12#\n\x06header\x18\x01 \x01(\x0b\x32\x13.motorcortex.Header\":\n\x13GetParameterTreeMsg\x12#\n\x06header\x18\x01 \x01(\x0b\x32\x13.motorcortex.Header\"\x9a\x01\n\x10ParameterTreeMsg\x12#\n\x06header\x18\x01 \x01(\x0b\x32\x13.motorcortex.Header\x12*\n\x06params\x18\x02 \x03(\x0b\x32\x1a.motorcortex.ParameterInfo\x12\x0c\n\x04hash\x18\x03 \x02(\r\x12\'\n\x06status\x18\x04 \x02(\x0e\x32\x17.motorcortex.StatusCode\">\n\x17GetParameterTreeHashMsg\x12#\n\x06header\x18\x01 \x01(\x0b\x32\x13.motorcortex.Header\"r\n\x14ParameterTreeHashMsg\x12#\n\x06header\x18\x01 \x01(\x0b\x32\x13.motorcortex.Header\x12\x0c\n\x04hash\x18\x02 \x02(\r\x12\'\n\x06status\x18\x03 \x02(\x0e\x32\x17.motorcortex.StatusCode\"h\n\x0e\x43reateGroupMsg\x12#\n\x06header\x18\x01 \x01(\x0b\x32\x13.motorcortex.Header\x12\x13\n\x0b\x66rq_divider\x18\x02 \x02(\r\x12\r\n\x05\x61lias\x18\x03 \x02(\t\x12\r\n\x05paths\x18\x04 \x03(\t\"\xaa\x01\n\x0eGroupStatusMsg\x12#\n\x06header\x18\x01 \x01(\x0b\x32\x13.motorcortex.Header\x12\n\n\x02id\x18\x02 \x02(\r\x12\r\n\x05\x61lias\x18\x03 \x02(\t\x12/\n\x06params\x18\x04 \x03(\x0b\x32\x1f.motorcortex.GroupParameterInfo\x12\'\n\x06status\x18\x05 \x02(\x0e\x32\x17.motorcortex.StatusCode\"D\n\x0eRemoveGroupMsg\x12#\n\x06header\x18\x01 \x01(\x0b\x32\x13.motorcortex.Header\x12\r\n\x05\x61lias\x18\x02 \x02(\t\"D\n\x0fGetParameterMsg\x12#\n\x06header\x18\x01 \x01(\x0b\x32\x13.motorcortex.Header\x12\x0c\n\x04path\x18\x02 \x02(\t\"\x95\x01\n\x0cParameterMsg\x12\r\n\x05value\x18\x01 \x02(\x0c\x12#\n\x06header\x18\x02 \x01(\x0b\x32\x13.motorcortex.Header\x12(\n\x04info\x18\x03 \x01(\x0b\x32\x1a.motorcortex.ParameterInfo\x12\'\n\x06status\x18\x04 \x02(\x0e\x32\x17.motorcortex.StatusCode\"h\n\x13GetParameterListMsg\x12#\n\x06header\x18\x01 \x01(\x0b\x32\x13.motorcortex.Header\x12,\n\x06params\x18\x02 \x03(\x0b\x32\x1c.motorcortex.GetParameterMsg\"\x8b\x01\n\x10ParameterListMsg\x12#\n\x06header\x18\x01 \x01(\x0b\x32\x13.motorcortex.Header\x12)\n\x06params\x18\x02 \x03(\x0b\x32\x19.motorcortex.ParameterMsg\x12\'\n\x06status\x18\x03 \x02(\x0e\x32\x17.motorcortex.StatusCode\"\x81\x01\n\x0fSetParameterMsg\x12#\n\x06header\x18\x01 \x01(\x0b\x32\x13.motorcortex.Header\x12,\n\x06offset\x18\x02 \x01(\x0b\x32\x1c.motorcortex.ParameterOffset\x12\x0c\n\x04path\x18\x03 \x02(\t\x12\r\n\x05value\x18\x04 \x02(\x0c\"h\n\x13SetParameterListMsg\x12#\n\x06header\x18\x01 \x01(\x0b\x32\x13.motorcortex.Header\x12,\n\x06params\x18\x02 \x03(\x0b\x32\x1c.motorcortex.SetParameterMsg\"\x99\x01\n\x15OverwriteParameterMsg\x12#\n\x06header\x18\x01 \x01(\x0b\x32\x13.motorcortex.Header\x12,\n\x06offset\x18\x02 \x01(\x0b\x32\x1c.motorcortex.ParameterOffset\x12\x10\n\x08\x61\x63tivate\x18\x03 \x02(\x08\x12\x0c\n\x04path\x18\x04 \x02(\t\x12\r\n\x05value\x18\x05 \x02(\x0c\"H\n\x13ReleaseParameterMsg\x12#\n\x06header\x18\x01 \x01(\x0b\x32\x13.motorcortex.Header\x12\x0c\n\x04path\x18\x02 \x02(\t\"O\n\x07SaveMsg\x12#\n\x06header\x18\x01 \x01(\x0b\x32\x13.motorcortex.Header\x12\x0c\n\x04path\x18\x02 \x02(\t\x12\x11\n\tfile_name\x18\x03 \x02(\t\"O\n\x07LoadMsg\x12#\n\x06header\x18\x01 \x01(\x0b\x32\x13.motorcortex.Header\x12\x0c\n\x04path\x18\x02 \x02(\t\x12\x11\n\tfile_name\x18\x03 \x02(\t\"C\n\rConsoleCmdMsg\x12#\n\x06header\x18\x01 \x01(\x0b\x32\x13.motorcortex.Header\x12\r\n\x05value\x18\x02 \x02(\t\"b\n\x11\x43onsoleCmdListMsg\x12#\n\x06header\x18\x01 \x01(\x0b\x32\x13.motorcortex.Header\x12(\n\x04\x63mds\x18\x02 \x03(\x0b\x32\x1a.motorcortex.ConsoleCmdMsg*\xab\x02\n\x04Unit\x12\x12\n\x0eunit_undefined\x10\x00\x12\n\n\x06Length\x10\x0f\x12\x06\n\x02mm\x10\x01\x12\x05\n\x01m\x10\x02\x12\n\n\x05\x41ngle\x10\xf1\x01\x12\x07\n\x03rad\x10\x31\x12\x07\n\x03\x64\x65g\x10\x41\x12\t\n\x04Time\x10\xf2\x01\x12\x0b\n\x07nanosec\x10\x12\x12\x0c\n\x08microsec\x10\"\x12\x0c\n\x08millisec\x10\x32\x12\x07\n\x03sec\x10\x42\x12\x0b\n\x06Weight\x10\xf3\x01\x12\x08\n\x04gram\x10\x13\x12\x06\n\x02kg\x10#\x12\r\n\x08Velocity\x10\xf4\x01\x12\t\n\x05m_sec\x10\x14\x12\x0b\n\x07rad_sec\x10$\x12\x11\n\x0c\x41\x63\x63\x65leration\x10\xf5\x01\x12\n\n\x06m_sec2\x10\x15\x12\x0c\n\x08rad_sec2\x10%\x12\n\n\x05\x46orce\x10\xf6\x01\x12\x05\n\x01N\x10\x16\x12\x06\n\x02Nm\x10&\x12\x0b\n\x07percent\x10\x17*_\n\tUserGroup\x12\x18\n\x14user_group_undefined\x10\x00\x12\n\n\x06SYSTEM\x10\x01\x12\x11\n\rADMINISTRATOR\x10\x03\x12\x0c\n\x08OPERATOR\x10\x07\x12\x0b\n\x07MONITOR\x10\x0f*\xc4\x01\n\nPermission\x12\x18\n\x14permission_undefined\x10\x00\x12\x0e\n\tUSER_READ\x10\x80\x02\x12\x0f\n\nUSER_WRITE\x10\x80\x01\x12\x10\n\x0cUSER_EXECUTE\x10@\x12\x0e\n\nGROUP_READ\x10 \x12\x0f\n\x0bGROUP_WRITE\x10\x10\x12\x11\n\rGROUP_EXECUTE\x10\x08\x12\x0f\n\x0bOTHERS_READ\x10\x04\x12\x10\n\x0cOTHERS_WRITE\x10\x02\x12\x12\n\x0eOTHERS_EXECUTE\x10\x01*\xd4\x01\n\x08\x44\x61taType\x12\x17\n\x13\x64\x61ta_type_undefined\x10\x00\x12\x08\n\x04INT8\x10\x01\x12\t\n\x05UINT8\x10\x02\x12\t\n\x05INT16\x10\x03\x12\n\n\x06UINT16\x10\x04\x12\t\n\x05INT32\x10\x05\x12\n\n\x06UINT32\x10\x06\x12\t\n\x05INT64\x10\x07\x12\n\n\x06UINT64\x10\x08\x12\x08\n\x04\x42OOL\x10\t\x12\n\n\x05\x46LOAT\x10\x81\x02\x12\x0b\n\x06\x44OUBLE\x10\x82\x02\x12\t\n\x04\x43HAR\x10\x81\x04\x12\x0b\n\x06STRING\x10\x82\x04\x12\n\n\x05\x42YTES\x10\x99\t\x12\x0e\n\tUSER_TYPE\x10\x80\n*\x84\x01\n\rParameterType\x12\x18\n\x14param_type_undefined\x10\x00\x12\t\n\x05INPUT\x10\x01\x12\n\n\x06OUTPUT\x10\x10\x12\x0e\n\tPARAMETER\x10\x80\x02\x12\x17\n\x12PARAMETER_VOLATILE\x10\x81\x02\x12\x19\n\x14PARAMETER_PERSISTENT\x10\x82\x02*\
|
|
16
|
+
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x11motorcortex.proto\x12\x0bmotorcortex\"i\n\x0fParameterOffset\x12\x36\n\x04type\x18\x01 \x02(\x0e\x32\x17.motorcortex.OffsetType:\x0fOFFSET_ELEMENTS\x12\x0e\n\x06offset\x18\x02 \x02(\r\x12\x0e\n\x06length\x18\x03 \x02(\r\"f\n\x05\x45rror\x12\x11\n\ttimestamp\x18\x01 \x02(\x06\x12\x14\n\x0c\x65rror_number\x18\x02 \x02(\x07\x12\x13\n\x0b\x65rror_level\x18\x03 \x02(\x07\x12\x11\n\tsubsystem\x18\x04 \x02(\x07\x12\x0c\n\x04info\x18\x05 \x02(\x07\"a\n\tErrorList\x12\"\n\x06\x65rrors\x18\x01 \x03(\x0b\x32\x12.motorcortex.Error\x12\x18\n\x10number_of_errors\x18\x02 \x02(\x07\x12\x16\n\x0eupdate_counter\x18\x03 \x02(\x07\"\x8a\x02\n\rParameterInfo\x12\n\n\x02id\x18\x01 \x02(\r\x12\x11\n\tdata_type\x18\x02 \x02(\r\x12\x11\n\tdata_size\x18\x03 \x02(\r\x12\x1a\n\x12number_of_elements\x18\x04 \x02(\r\x12\r\n\x05\x66lags\x18\x05 \x02(\r\x12\x13\n\x0bpermissions\x18\x06 \x02(\r\x12.\n\nparam_type\x18\x07 \x02(\x0e\x32\x1a.motorcortex.ParameterType\x12(\n\x08group_id\x18\x08 \x02(\x0e\x32\x16.motorcortex.UserGroup\x12\x1f\n\x04unit\x18\t \x02(\x0e\x32\x11.motorcortex.Unit\x12\x0c\n\x04path\x18\n \x02(\t\"\x94\x01\n\x12GroupParameterInfo\x12\r\n\x05index\x18\x01 \x02(\r\x12\x0e\n\x06offset\x18\x02 \x02(\r\x12\x0c\n\x04size\x18\x03 \x02(\r\x12(\n\x04info\x18\x04 \x02(\x0b\x32\x1a.motorcortex.ParameterInfo\x12\'\n\x06status\x18\x05 \x02(\x0e\x32\x17.motorcortex.StatusCode\"1\n\x06Header\x12\x14\n\x0c\x66rameCounter\x18\x01 \x02(\x07\x12\x11\n\ttimestamp\x18\x02 \x02(\x06\"Z\n\x08GroupMsg\x12#\n\x06header\x18\x01 \x01(\x0b\x32\x13.motorcortex.Header\x12)\n\x06params\x18\x02 \x03(\x0b\x32\x19.motorcortex.ParameterMsg\"Y\n\tStatusMsg\x12#\n\x06header\x18\x01 \x01(\x0b\x32\x13.motorcortex.Header\x12\'\n\x06status\x18\x02 \x02(\x0e\x32\x17.motorcortex.StatusCode\"P\n\x08LoginMsg\x12#\n\x06header\x18\x01 \x01(\x0b\x32\x13.motorcortex.Header\x12\r\n\x05login\x18\x02 \x02(\t\x12\x10\n\x08password\x18\x03 \x02(\t\"9\n\x12GetSessionTokenMsg\x12#\n\x06header\x18\x01 \x01(\x0b\x32\x13.motorcortex.Header\"n\n\x0fSessionTokenMsg\x12#\n\x06header\x18\x01 \x01(\x0b\x32\x13.motorcortex.Header\x12\r\n\x05token\x18\x02 \x02(\t\x12\'\n\x06status\x18\x03 \x02(\x0e\x32\x17.motorcortex.StatusCode\"6\n\x0fGetSubCookieMsg\x12#\n\x06header\x18\x01 \x01(\x0b\x32\x13.motorcortex.Header\"l\n\x0cSubCookieMsg\x12#\n\x06header\x18\x01 \x01(\x0b\x32\x13.motorcortex.Header\x12\x0e\n\x06\x63ookie\x18\x02 \x02(\t\x12\'\n\x06status\x18\x03 \x02(\x0e\x32\x17.motorcortex.StatusCode\"G\n\x11RestoreSessionMsg\x12#\n\x06header\x18\x01 \x01(\x0b\x32\x13.motorcortex.Header\x12\r\n\x05token\x18\x02 \x02(\t\"0\n\tLogoutMsg\x12#\n\x06header\x18\x01 \x01(\x0b\x32\x13.motorcortex.Header\":\n\x13GetParameterTreeMsg\x12#\n\x06header\x18\x01 \x01(\x0b\x32\x13.motorcortex.Header\"\x9a\x01\n\x10ParameterTreeMsg\x12#\n\x06header\x18\x01 \x01(\x0b\x32\x13.motorcortex.Header\x12*\n\x06params\x18\x02 \x03(\x0b\x32\x1a.motorcortex.ParameterInfo\x12\x0c\n\x04hash\x18\x03 \x02(\r\x12\'\n\x06status\x18\x04 \x02(\x0e\x32\x17.motorcortex.StatusCode\">\n\x17GetParameterTreeHashMsg\x12#\n\x06header\x18\x01 \x01(\x0b\x32\x13.motorcortex.Header\"r\n\x14ParameterTreeHashMsg\x12#\n\x06header\x18\x01 \x01(\x0b\x32\x13.motorcortex.Header\x12\x0c\n\x04hash\x18\x02 \x02(\r\x12\'\n\x06status\x18\x03 \x02(\x0e\x32\x17.motorcortex.StatusCode\"D\n\x1dGetParameterTreeCompressedMsg\x12#\n\x06header\x18\x01 \x01(\x0b\x32\x13.motorcortex.Header\"\xa7\x01\n\x1a\x43ompressedParameterTreeMsg\x12#\n\x06header\x18\x01 \x01(\x0b\x32\x13.motorcortex.Header\x12\x12\n\ncompressed\x18\x02 \x02(\x0c\x12\x19\n\x11uncompressed_size\x18\x03 \x02(\r\x12\x0c\n\x04hash\x18\x04 \x02(\r\x12\'\n\x06status\x18\x05 \x02(\x0e\x32\x17.motorcortex.StatusCode\"h\n\x0e\x43reateGroupMsg\x12#\n\x06header\x18\x01 \x01(\x0b\x32\x13.motorcortex.Header\x12\x13\n\x0b\x66rq_divider\x18\x02 \x02(\r\x12\r\n\x05\x61lias\x18\x03 \x02(\t\x12\r\n\x05paths\x18\x04 \x03(\t\"\xaa\x01\n\x0eGroupStatusMsg\x12#\n\x06header\x18\x01 \x01(\x0b\x32\x13.motorcortex.Header\x12\n\n\x02id\x18\x02 \x02(\r\x12\r\n\x05\x61lias\x18\x03 \x02(\t\x12/\n\x06params\x18\x04 \x03(\x0b\x32\x1f.motorcortex.GroupParameterInfo\x12\'\n\x06status\x18\x05 \x02(\x0e\x32\x17.motorcortex.StatusCode\"D\n\x0eRemoveGroupMsg\x12#\n\x06header\x18\x01 \x01(\x0b\x32\x13.motorcortex.Header\x12\r\n\x05\x61lias\x18\x02 \x02(\t\"D\n\x0fGetParameterMsg\x12#\n\x06header\x18\x01 \x01(\x0b\x32\x13.motorcortex.Header\x12\x0c\n\x04path\x18\x02 \x02(\t\"\x95\x01\n\x0cParameterMsg\x12\r\n\x05value\x18\x01 \x02(\x0c\x12#\n\x06header\x18\x02 \x01(\x0b\x32\x13.motorcortex.Header\x12(\n\x04info\x18\x03 \x01(\x0b\x32\x1a.motorcortex.ParameterInfo\x12\'\n\x06status\x18\x04 \x02(\x0e\x32\x17.motorcortex.StatusCode\"h\n\x13GetParameterListMsg\x12#\n\x06header\x18\x01 \x01(\x0b\x32\x13.motorcortex.Header\x12,\n\x06params\x18\x02 \x03(\x0b\x32\x1c.motorcortex.GetParameterMsg\"\x8b\x01\n\x10ParameterListMsg\x12#\n\x06header\x18\x01 \x01(\x0b\x32\x13.motorcortex.Header\x12)\n\x06params\x18\x02 \x03(\x0b\x32\x19.motorcortex.ParameterMsg\x12\'\n\x06status\x18\x03 \x02(\x0e\x32\x17.motorcortex.StatusCode\"\x81\x01\n\x0fSetParameterMsg\x12#\n\x06header\x18\x01 \x01(\x0b\x32\x13.motorcortex.Header\x12,\n\x06offset\x18\x02 \x01(\x0b\x32\x1c.motorcortex.ParameterOffset\x12\x0c\n\x04path\x18\x03 \x02(\t\x12\r\n\x05value\x18\x04 \x02(\x0c\"h\n\x13SetParameterListMsg\x12#\n\x06header\x18\x01 \x01(\x0b\x32\x13.motorcortex.Header\x12,\n\x06params\x18\x02 \x03(\x0b\x32\x1c.motorcortex.SetParameterMsg\"\x99\x01\n\x15OverwriteParameterMsg\x12#\n\x06header\x18\x01 \x01(\x0b\x32\x13.motorcortex.Header\x12,\n\x06offset\x18\x02 \x01(\x0b\x32\x1c.motorcortex.ParameterOffset\x12\x10\n\x08\x61\x63tivate\x18\x03 \x02(\x08\x12\x0c\n\x04path\x18\x04 \x02(\t\x12\r\n\x05value\x18\x05 \x02(\x0c\"H\n\x13ReleaseParameterMsg\x12#\n\x06header\x18\x01 \x01(\x0b\x32\x13.motorcortex.Header\x12\x0c\n\x04path\x18\x02 \x02(\t\"O\n\x07SaveMsg\x12#\n\x06header\x18\x01 \x01(\x0b\x32\x13.motorcortex.Header\x12\x0c\n\x04path\x18\x02 \x02(\t\x12\x11\n\tfile_name\x18\x03 \x02(\t\"O\n\x07LoadMsg\x12#\n\x06header\x18\x01 \x01(\x0b\x32\x13.motorcortex.Header\x12\x0c\n\x04path\x18\x02 \x02(\t\x12\x11\n\tfile_name\x18\x03 \x02(\t\"C\n\rConsoleCmdMsg\x12#\n\x06header\x18\x01 \x01(\x0b\x32\x13.motorcortex.Header\x12\r\n\x05value\x18\x02 \x02(\t\"b\n\x11\x43onsoleCmdListMsg\x12#\n\x06header\x18\x01 \x01(\x0b\x32\x13.motorcortex.Header\x12(\n\x04\x63mds\x18\x02 \x03(\x0b\x32\x1a.motorcortex.ConsoleCmdMsg*\xab\x02\n\x04Unit\x12\x12\n\x0eunit_undefined\x10\x00\x12\n\n\x06Length\x10\x0f\x12\x06\n\x02mm\x10\x01\x12\x05\n\x01m\x10\x02\x12\n\n\x05\x41ngle\x10\xf1\x01\x12\x07\n\x03rad\x10\x31\x12\x07\n\x03\x64\x65g\x10\x41\x12\t\n\x04Time\x10\xf2\x01\x12\x0b\n\x07nanosec\x10\x12\x12\x0c\n\x08microsec\x10\"\x12\x0c\n\x08millisec\x10\x32\x12\x07\n\x03sec\x10\x42\x12\x0b\n\x06Weight\x10\xf3\x01\x12\x08\n\x04gram\x10\x13\x12\x06\n\x02kg\x10#\x12\r\n\x08Velocity\x10\xf4\x01\x12\t\n\x05m_sec\x10\x14\x12\x0b\n\x07rad_sec\x10$\x12\x11\n\x0c\x41\x63\x63\x65leration\x10\xf5\x01\x12\n\n\x06m_sec2\x10\x15\x12\x0c\n\x08rad_sec2\x10%\x12\n\n\x05\x46orce\x10\xf6\x01\x12\x05\n\x01N\x10\x16\x12\x06\n\x02Nm\x10&\x12\x0b\n\x07percent\x10\x17*_\n\tUserGroup\x12\x18\n\x14user_group_undefined\x10\x00\x12\n\n\x06SYSTEM\x10\x01\x12\x11\n\rADMINISTRATOR\x10\x03\x12\x0c\n\x08OPERATOR\x10\x07\x12\x0b\n\x07MONITOR\x10\x0f*\xc4\x01\n\nPermission\x12\x18\n\x14permission_undefined\x10\x00\x12\x0e\n\tUSER_READ\x10\x80\x02\x12\x0f\n\nUSER_WRITE\x10\x80\x01\x12\x10\n\x0cUSER_EXECUTE\x10@\x12\x0e\n\nGROUP_READ\x10 \x12\x0f\n\x0bGROUP_WRITE\x10\x10\x12\x11\n\rGROUP_EXECUTE\x10\x08\x12\x0f\n\x0bOTHERS_READ\x10\x04\x12\x10\n\x0cOTHERS_WRITE\x10\x02\x12\x12\n\x0eOTHERS_EXECUTE\x10\x01*\xd4\x01\n\x08\x44\x61taType\x12\x17\n\x13\x64\x61ta_type_undefined\x10\x00\x12\x08\n\x04INT8\x10\x01\x12\t\n\x05UINT8\x10\x02\x12\t\n\x05INT16\x10\x03\x12\n\n\x06UINT16\x10\x04\x12\t\n\x05INT32\x10\x05\x12\n\n\x06UINT32\x10\x06\x12\t\n\x05INT64\x10\x07\x12\n\n\x06UINT64\x10\x08\x12\x08\n\x04\x42OOL\x10\t\x12\n\n\x05\x46LOAT\x10\x81\x02\x12\x0b\n\x06\x44OUBLE\x10\x82\x02\x12\t\n\x04\x43HAR\x10\x81\x04\x12\x0b\n\x06STRING\x10\x82\x04\x12\n\n\x05\x42YTES\x10\x99\t\x12\x0e\n\tUSER_TYPE\x10\x80\n*\x84\x01\n\rParameterType\x12\x18\n\x14param_type_undefined\x10\x00\x12\t\n\x05INPUT\x10\x01\x12\n\n\x06OUTPUT\x10\x10\x12\x0e\n\tPARAMETER\x10\x80\x02\x12\x17\n\x12PARAMETER_VOLATILE\x10\x81\x02\x12\x19\n\x14PARAMETER_PERSISTENT\x10\x82\x02*\xd2\x02\n\nStatusCode\x12\x06\n\x02OK\x10\x00\x12\x12\n\x0eREAD_ONLY_MODE\x10\x01\x12\x0c\n\x06\x46\x41ILED\x10\x80\xfe\x03\x12\x15\n\x10\x46\x41ILED_TO_DECODE\x10\x80 \x12\x15\n\x10SUB_LIST_IS_FULL\x10\x80\"\x12\x19\n\x14WRONG_PARAMETER_PATH\x10\x80$\x12 \n\x1b\x46\x41ILED_TO_SET_REQUESTED_FRQ\x10\x80&\x12\x18\n\x13\x46\x41ILED_TO_OPEN_FILE\x10\x80(\x12\x17\n\x12GROUP_LIST_IS_FULL\x10\x80*\x12\x1f\n\x1aTIMEOUT_WAITING_FOR_UPDATE\x10\x80,\x12\x15\n\x10SAVE_IN_PROGRESS\x10\x80.\x12\x13\n\x0eWRONG_PASSWORD\x10\x80\x42\x12\x17\n\x12USER_NOT_LOGGED_IN\x10\x80\x44\x12\x16\n\x11PERMISSION_DENIED\x10\x80\x46*v\n\nErrorLevel\x12\x19\n\x15\x65rror_level_undefined\x10\x00\x12\x08\n\x04INFO\x10\x01\x12\x0b\n\x07WARNING\x10\x02\x12\x14\n\x10\x46ORCED_DISENGAGE\x10\x03\x12\x0c\n\x08SHUTDOWN\x10\x04\x12\x12\n\x0e\x45MERGENCY_STOP\x10\x05*_\n\nOffsetType\x12\x19\n\x15offset_type_undefined\x10\x00\x12\x13\n\x0fOFFSET_ELEMENTS\x10\x01\x12\x10\n\x0cOFFSET_BYTES\x10\x02\x12\x0f\n\x0bOFFSET_BITS\x10\x03*<\n\rParameterFlag\x12\x12\n\x0eLINK_IS_ACTIVE\x10\x01\x12\x17\n\x13OVERWRITE_IS_ACTIVE\x10\x02')
|
|
17
17
|
|
|
18
18
|
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
|
|
19
19
|
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'motorcortex_pb2', globals())
|
|
20
20
|
if _descriptor._USE_C_DESCRIPTORS == False:
|
|
21
21
|
|
|
22
22
|
DESCRIPTOR._options = None
|
|
23
|
-
_UNIT._serialized_start=
|
|
24
|
-
_UNIT._serialized_end=
|
|
25
|
-
_USERGROUP._serialized_start=
|
|
26
|
-
_USERGROUP._serialized_end=
|
|
27
|
-
_PERMISSION._serialized_start=
|
|
28
|
-
_PERMISSION._serialized_end=
|
|
29
|
-
_DATATYPE._serialized_start=
|
|
30
|
-
_DATATYPE._serialized_end=
|
|
31
|
-
_PARAMETERTYPE._serialized_start=
|
|
32
|
-
_PARAMETERTYPE._serialized_end=
|
|
33
|
-
_STATUSCODE._serialized_start=
|
|
34
|
-
_STATUSCODE._serialized_end=
|
|
35
|
-
_ERRORLEVEL._serialized_start=
|
|
36
|
-
_ERRORLEVEL._serialized_end=
|
|
37
|
-
_OFFSETTYPE._serialized_start=
|
|
38
|
-
_OFFSETTYPE._serialized_end=
|
|
39
|
-
_PARAMETERFLAG._serialized_start=
|
|
40
|
-
_PARAMETERFLAG._serialized_end=
|
|
23
|
+
_UNIT._serialized_start=3796
|
|
24
|
+
_UNIT._serialized_end=4095
|
|
25
|
+
_USERGROUP._serialized_start=4097
|
|
26
|
+
_USERGROUP._serialized_end=4192
|
|
27
|
+
_PERMISSION._serialized_start=4195
|
|
28
|
+
_PERMISSION._serialized_end=4391
|
|
29
|
+
_DATATYPE._serialized_start=4394
|
|
30
|
+
_DATATYPE._serialized_end=4606
|
|
31
|
+
_PARAMETERTYPE._serialized_start=4609
|
|
32
|
+
_PARAMETERTYPE._serialized_end=4741
|
|
33
|
+
_STATUSCODE._serialized_start=4744
|
|
34
|
+
_STATUSCODE._serialized_end=5082
|
|
35
|
+
_ERRORLEVEL._serialized_start=5084
|
|
36
|
+
_ERRORLEVEL._serialized_end=5202
|
|
37
|
+
_OFFSETTYPE._serialized_start=5204
|
|
38
|
+
_OFFSETTYPE._serialized_end=5299
|
|
39
|
+
_PARAMETERFLAG._serialized_start=5301
|
|
40
|
+
_PARAMETERFLAG._serialized_end=5361
|
|
41
41
|
_PARAMETEROFFSET._serialized_start=34
|
|
42
42
|
_PARAMETEROFFSET._serialized_end=139
|
|
43
43
|
_ERROR._serialized_start=141
|
|
@@ -60,46 +60,54 @@ if _descriptor._USE_C_DESCRIPTORS == False:
|
|
|
60
60
|
_GETSESSIONTOKENMSG._serialized_end=1137
|
|
61
61
|
_SESSIONTOKENMSG._serialized_start=1139
|
|
62
62
|
_SESSIONTOKENMSG._serialized_end=1249
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
63
|
+
_GETSUBCOOKIEMSG._serialized_start=1251
|
|
64
|
+
_GETSUBCOOKIEMSG._serialized_end=1305
|
|
65
|
+
_SUBCOOKIEMSG._serialized_start=1307
|
|
66
|
+
_SUBCOOKIEMSG._serialized_end=1415
|
|
67
|
+
_RESTORESESSIONMSG._serialized_start=1417
|
|
68
|
+
_RESTORESESSIONMSG._serialized_end=1488
|
|
69
|
+
_LOGOUTMSG._serialized_start=1490
|
|
70
|
+
_LOGOUTMSG._serialized_end=1538
|
|
71
|
+
_GETPARAMETERTREEMSG._serialized_start=1540
|
|
72
|
+
_GETPARAMETERTREEMSG._serialized_end=1598
|
|
73
|
+
_PARAMETERTREEMSG._serialized_start=1601
|
|
74
|
+
_PARAMETERTREEMSG._serialized_end=1755
|
|
75
|
+
_GETPARAMETERTREEHASHMSG._serialized_start=1757
|
|
76
|
+
_GETPARAMETERTREEHASHMSG._serialized_end=1819
|
|
77
|
+
_PARAMETERTREEHASHMSG._serialized_start=1821
|
|
78
|
+
_PARAMETERTREEHASHMSG._serialized_end=1935
|
|
79
|
+
_GETPARAMETERTREECOMPRESSEDMSG._serialized_start=1937
|
|
80
|
+
_GETPARAMETERTREECOMPRESSEDMSG._serialized_end=2005
|
|
81
|
+
_COMPRESSEDPARAMETERTREEMSG._serialized_start=2008
|
|
82
|
+
_COMPRESSEDPARAMETERTREEMSG._serialized_end=2175
|
|
83
|
+
_CREATEGROUPMSG._serialized_start=2177
|
|
84
|
+
_CREATEGROUPMSG._serialized_end=2281
|
|
85
|
+
_GROUPSTATUSMSG._serialized_start=2284
|
|
86
|
+
_GROUPSTATUSMSG._serialized_end=2454
|
|
87
|
+
_REMOVEGROUPMSG._serialized_start=2456
|
|
88
|
+
_REMOVEGROUPMSG._serialized_end=2524
|
|
89
|
+
_GETPARAMETERMSG._serialized_start=2526
|
|
90
|
+
_GETPARAMETERMSG._serialized_end=2594
|
|
91
|
+
_PARAMETERMSG._serialized_start=2597
|
|
92
|
+
_PARAMETERMSG._serialized_end=2746
|
|
93
|
+
_GETPARAMETERLISTMSG._serialized_start=2748
|
|
94
|
+
_GETPARAMETERLISTMSG._serialized_end=2852
|
|
95
|
+
_PARAMETERLISTMSG._serialized_start=2855
|
|
96
|
+
_PARAMETERLISTMSG._serialized_end=2994
|
|
97
|
+
_SETPARAMETERMSG._serialized_start=2997
|
|
98
|
+
_SETPARAMETERMSG._serialized_end=3126
|
|
99
|
+
_SETPARAMETERLISTMSG._serialized_start=3128
|
|
100
|
+
_SETPARAMETERLISTMSG._serialized_end=3232
|
|
101
|
+
_OVERWRITEPARAMETERMSG._serialized_start=3235
|
|
102
|
+
_OVERWRITEPARAMETERMSG._serialized_end=3388
|
|
103
|
+
_RELEASEPARAMETERMSG._serialized_start=3390
|
|
104
|
+
_RELEASEPARAMETERMSG._serialized_end=3462
|
|
105
|
+
_SAVEMSG._serialized_start=3464
|
|
106
|
+
_SAVEMSG._serialized_end=3543
|
|
107
|
+
_LOADMSG._serialized_start=3545
|
|
108
|
+
_LOADMSG._serialized_end=3624
|
|
109
|
+
_CONSOLECMDMSG._serialized_start=3626
|
|
110
|
+
_CONSOLECMDMSG._serialized_end=3693
|
|
111
|
+
_CONSOLECMDLISTMSG._serialized_start=3695
|
|
112
|
+
_CONSOLECMDLISTMSG._serialized_end=3793
|
|
105
113
|
# @@protoc_insertion_point(module_scope)
|