Merge branch 'main' of ssh://892887cvmk08.aicp.io:24928/orisys-tech/orisys-app

This commit is contained in:
ykcheungab
2026-09-23 10:00:13 +08:00
21 changed files with 1200 additions and 59 deletions
+25 -4
View File
@@ -21,6 +21,7 @@ from typing import Any # noqa: F401 (kept for ZmotionValue.value's annotation)
from .loader import ZmotionDllNotFound, load_dll, resolve_dll_dir
__all__ = [
"RESPONSE_BUFFER_BYTES",
"ZAuxError",
"ZmotionClient",
"ZmotionDllNotFound",
@@ -28,6 +29,11 @@ __all__ = [
"ZmotionValue",
]
#: Reply buffer for :meth:`ZmotionClient.execute`. The vendor Python wrapper
#: allocates 2 048 bytes for the same call; the controller's diagnostics
#: (``?*ETHERCAT`` and friends) run to a few hundred.
RESPONSE_BUFFER_BYTES = 2048
class ZAuxError(RuntimeError):
"""A ``ZAux_*`` call returned a non-zero code.
@@ -215,14 +221,29 @@ class ZmotionClient:
return ZmotionResult(int(ret))
def execute(self, command: str) -> ZmotionValue:
"""Run an online command string (e.g. ``RUN "ECAT.bas",4``)."""
"""Run an online command string (e.g. ``RUN "ECAT.bas",4``).
Returns the controller's own reply text as the value. The reply buffer
is not optional: ``ZAux_Execute`` writes into ``psResponse`` for any
command that answers — a ``?`` query does — and passing ``NULL`` with a
zero length is a write through a null pointer inside the DLL, which
terminates the process rather than raising. The vendor wrapper allocates
the same 2 048-byte buffer for this reason.
A non-zero code is *not* the only failure mode: an online command that
the firmware rejects (a ``RUN`` naming a program the controller does not
have) can still return 0 while putting the diagnosis in the reply text.
Callers that need to distinguish that must inspect the returned value.
"""
buffer = (ctypes.c_char * RESPONSE_BUFFER_BYTES)()
ret = self._dll.ZAux_Execute( # type: ignore[union-attr]
self._require_handle(),
command.encode("utf-8"),
None,
ctypes.c_uint32(0),
buffer,
ctypes.c_uint32(RESPONSE_BUFFER_BYTES),
)
return ZmotionValue(int(ret), command)
text = buffer.value.decode("utf-8", errors="replace") if buffer.value else ""
return ZmotionValue(int(ret), text.strip())
def get_user_var(self, name: str) -> ZmotionValue:
"""Read a global variable from the running ``.bas`` program.