xarm-python-sdk 1.15.2__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.
Files changed (63) hide show
  1. xarm/__init__.py +2 -0
  2. xarm/build_backend.py +17 -0
  3. xarm/core/__init__.py +2 -0
  4. xarm/core/comm/__init__.py +5 -0
  5. xarm/core/comm/base.py +303 -0
  6. xarm/core/comm/serial_port.py +44 -0
  7. xarm/core/comm/socket_port.py +150 -0
  8. xarm/core/comm/uxbus_cmd_protocol.py +100 -0
  9. xarm/core/config/__init__.py +0 -0
  10. xarm/core/config/x_code.py +1427 -0
  11. xarm/core/config/x_config.py +553 -0
  12. xarm/core/utils/__init__.py +3 -0
  13. xarm/core/utils/convert.py +124 -0
  14. xarm/core/utils/crc16.py +76 -0
  15. xarm/core/utils/debug_print.py +21 -0
  16. xarm/core/utils/log.py +98 -0
  17. xarm/core/version.py +1 -0
  18. xarm/core/wrapper/__init__.py +11 -0
  19. xarm/core/wrapper/uxbus_cmd.py +1457 -0
  20. xarm/core/wrapper/uxbus_cmd_ser.py +94 -0
  21. xarm/core/wrapper/uxbus_cmd_tcp.py +305 -0
  22. xarm/tools/__init__.py +0 -0
  23. xarm/tools/blockly/__init__.py +1 -0
  24. xarm/tools/blockly/_blockly_base.py +416 -0
  25. xarm/tools/blockly/_blockly_handler.py +1338 -0
  26. xarm/tools/blockly/_blockly_highlight.py +94 -0
  27. xarm/tools/blockly/_blockly_node.py +61 -0
  28. xarm/tools/blockly/_blockly_tool.py +480 -0
  29. xarm/tools/blockly_tool.py +1864 -0
  30. xarm/tools/gcode.py +90 -0
  31. xarm/tools/list_ports.py +39 -0
  32. xarm/tools/modbus_tcp.py +205 -0
  33. xarm/tools/threads.py +30 -0
  34. xarm/tools/utils.py +36 -0
  35. xarm/version.py +1 -0
  36. xarm/wrapper/__init__.py +1 -0
  37. xarm/wrapper/studio_api.py +34 -0
  38. xarm/wrapper/xarm_api.py +4416 -0
  39. xarm/x3/__init__.py +2 -0
  40. xarm/x3/base.py +2638 -0
  41. xarm/x3/base_board.py +198 -0
  42. xarm/x3/code.py +62 -0
  43. xarm/x3/decorator.py +104 -0
  44. xarm/x3/events.py +166 -0
  45. xarm/x3/ft_sensor.py +264 -0
  46. xarm/x3/gpio.py +457 -0
  47. xarm/x3/grammar_async.py +21 -0
  48. xarm/x3/grammar_coroutine.py +24 -0
  49. xarm/x3/gripper.py +830 -0
  50. xarm/x3/modbus_tcp.py +84 -0
  51. xarm/x3/parse.py +110 -0
  52. xarm/x3/record.py +216 -0
  53. xarm/x3/report.py +204 -0
  54. xarm/x3/robotiq.py +220 -0
  55. xarm/x3/servo.py +485 -0
  56. xarm/x3/studio.py +138 -0
  57. xarm/x3/track.py +424 -0
  58. xarm/x3/utils.py +43 -0
  59. xarm/x3/xarm.py +1928 -0
  60. xarm_python_sdk-1.15.2.dist-info/METADATA +103 -0
  61. xarm_python_sdk-1.15.2.dist-info/RECORD +63 -0
  62. xarm_python_sdk-1.15.2.dist-info/WHEEL +4 -0
  63. xarm_python_sdk-1.15.2.dist-info/licenses/LICENSE +27 -0
xarm/tools/gcode.py ADDED
@@ -0,0 +1,90 @@
1
+ # !/usr/bin/env python3
2
+ # Software License Agreement (BSD License)
3
+ #
4
+ # Copyright (c) 2024, UFACTORY, Inc.
5
+ # All rights reserved.
6
+ #
7
+ # Author: Vinman <vinman.wen@ufactory.cc> <vinman.cub@gmail.com>
8
+
9
+ import os
10
+ import re
11
+ import sys
12
+ import socket
13
+ import logging
14
+ import threading
15
+
16
+ def create_logger(name):
17
+ logger = logging.Logger(name)
18
+ logger_fmt = '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d] - - %(message)s'
19
+ logger_date_fmt = '%Y-%m-%d %H:%M:%S'
20
+ stream_handler = logging.StreamHandler(sys.stdout)
21
+ stream_handler.setLevel(logging.DEBUG)
22
+ stream_handler.setFormatter(logging.Formatter(logger_fmt, logger_date_fmt))
23
+ logger.handlers.clear()
24
+ logger.addHandler(stream_handler)
25
+ logger.setLevel(logging.INFO)
26
+ return logger
27
+
28
+
29
+ GCODE_PATTERN = r'([A-Z])([-+]?[0-9.]+)'
30
+ CLEAN_PATTERN = r'\s+|\(.*?\)|;.*'
31
+
32
+
33
+ class GcodeClient(object):
34
+ def __init__(self, robot_ip, logger=None):
35
+ if isinstance(logger, logging.Logger):
36
+ self.logger = logger
37
+ else:
38
+ self.logger = create_logger('gcode')
39
+ self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
40
+ self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
41
+ self.sock.setblocking(True)
42
+ self.sock.connect((robot_ip, 504))
43
+ self.logger.info('Connetc to GcodeServer({}) success'.format(robot_ip))
44
+ self._lock = threading.Lock()
45
+
46
+ def close(self):
47
+ self.sock.close()
48
+
49
+ def execute(self, cmd):
50
+ data = re.sub(CLEAN_PATTERN, '', cmd.strip().upper())
51
+ if not data:
52
+ # self.logger.warning('[E] null after clean {}'.format(cmd))
53
+ return -1, []
54
+ if data[0] == '%':
55
+ # self.logger.warning('[E] starts with % ({})'.format(cmd))
56
+ return -2, []
57
+ if not re.findall(GCODE_PATTERN, data):
58
+ # self.logger.warning('[E] not found {}'.format(cmd))
59
+ return -3, []
60
+ data = data.encode('utf-8', 'replace')
61
+ with self._lock:
62
+ self.sock.send(data + b'\n')
63
+ ret = self.sock.recv(5)
64
+ code, mode_state, err = ret[0:3]
65
+ state, mode = mode_state & 0x0F, mode_state >> 4
66
+ cmdnum = ret[3] << 8 | ret[4]
67
+ if code != 0 or err != 0:
68
+ self.logger.error('[{}], code={}, err={}, mode={}, state={}, cmdnum={}'.format(cmd, code, err, mode, state, cmdnum))
69
+ elif state >= 4:
70
+ self.logger.warning('[{}], code={}, err={}, mode={}, state={}, cmdnum={}'.format(cmd, code, err, mode, state, cmdnum))
71
+ return code, [mode, state, err, cmdnum]
72
+
73
+ def execute_file(self, filepath):
74
+ if not os.path.exists(filepath) or os.path.isdir(filepath):
75
+ return -99
76
+ with open(filepath, 'r') as f:
77
+ for line in f.readlines():
78
+ cmd = line.strip()
79
+ if not cmd:
80
+ continue
81
+ code, info = self.execute(cmd)
82
+ if code < 0:
83
+ continue
84
+ if code != 0 or info[2] != 0:
85
+ if code != 1 and code != 2:
86
+ return code
87
+ if cmd in ['M2', 'M02', 'M30']:
88
+ self.logger.info('[{}] Program End'.format(cmd))
89
+ break
90
+ return 0
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/env python3
2
+ # Software License Agreement (MIT License)
3
+ #
4
+ # Copyright (c) 2018, UFACTORY, Inc.
5
+ # All rights reserved.
6
+ #
7
+ # Author: Vinman <vinman.wen@ufactory.cc>
8
+
9
+ from serial.tools import list_ports
10
+
11
+ def _dump_port(d):
12
+ print('-' * 80)
13
+ print(' device : {}'.format(d.device))
14
+ print(' hwid : {}'.format(d.hwid))
15
+ print(' product : {}'.format(d.hwid))
16
+ print(' description: {}'.format(d.hwid))
17
+ print('-' * 80)
18
+
19
+ def get_ports(is_dump=True):
20
+ ports = []
21
+ for i in list_ports.comports():
22
+ # if i.pid is not None and '{:04x}:{:04x}'.format(i.vid, i.pid) == vidpid:
23
+ if i.pid is not None:
24
+ if is_dump:
25
+ _dump_port(i)
26
+ ports.append({
27
+ 'pid': '{:04x}'.format(i.pid),
28
+ 'vid': '{:04x}'.format(i.vid),
29
+ 'device': i.device,
30
+ 'serial_number': i.serial_number,
31
+ 'hwid': i.hwid,
32
+ 'name': i.name,
33
+ 'description': i.description,
34
+ 'interface': i.interface,
35
+ 'location': i.location,
36
+ 'manufacturer': i.manufacturer,
37
+ 'product': i.product
38
+ })
39
+ return ports
@@ -0,0 +1,205 @@
1
+ # !/usr/bin/env python3
2
+ # Software License Agreement (BSD License)
3
+ #
4
+ # Copyright (c) 2024, UFACTORY, Inc.
5
+ # All rights reserved.
6
+ #
7
+ # Author: Vinman <vinman.wen@ufactory.cc> <vinman.cub@gmail.com>
8
+
9
+ import sys
10
+ import time
11
+ import socket
12
+ import struct
13
+ import logging
14
+ import threading
15
+
16
+ def create_logger(name):
17
+ logger = logging.Logger(name)
18
+ logger_fmt = '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d] - - %(message)s'
19
+ logger_date_fmt = '%Y-%m-%d %H:%M:%S'
20
+ stream_handler = logging.StreamHandler(sys.stdout)
21
+ stream_handler.setLevel(logging.DEBUG)
22
+ stream_handler.setFormatter(logging.Formatter(logger_fmt, logger_date_fmt))
23
+ logger.handlers.clear()
24
+ logger.addHandler(stream_handler)
25
+ logger.setLevel(logging.INFO)
26
+ return logger
27
+
28
+
29
+ class ModbusTcpClient(object):
30
+ def __init__(self, ip, port=502, unit_id=0x01, logger=None):
31
+ if isinstance(logger, logging.Logger):
32
+ self.logger = logger
33
+ else:
34
+ self.logger = create_logger('modbus_tcp')
35
+ self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
36
+ self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
37
+ self.sock.setblocking(True)
38
+ self.sock.connect((ip, port))
39
+ self.logger.info('Connetc to ModbusTcpServer({}) success'.format(ip))
40
+ self._transaction_id = 0
41
+ self._protocol_id = 0x00
42
+ self._unit_id = unit_id
43
+ self._func_code = 0x00
44
+ self._lock = threading.Lock()
45
+
46
+ def close(self):
47
+ self.sock.close()
48
+
49
+ def __wait_to_response(self, transaction_id=None, unit_id=None, func_code=None, timeout=3):
50
+ expired = time.monotonic() + timeout
51
+ recv_data = b''
52
+ length = 0
53
+ code = -3 # TIMEOUT
54
+ send_transaction_id = transaction_id if transaction_id is not None else self._transaction_id
55
+ send_unit_id = unit_id if unit_id is not None else self._unit_id
56
+ send_func_code = func_code if func_code is not None else self._func_code
57
+ while time.monotonic() < expired:
58
+ if len(recv_data) < 7:
59
+ recv_data += self.sock.recv(7 - len(recv_data))
60
+ if len(recv_data) < 7:
61
+ continue
62
+ if length == 0:
63
+ length = struct.unpack('>H', recv_data[4:6])[0]
64
+ if len(recv_data) < length + 6:
65
+ recv_data += self.sock.recv(length + 6 - len(recv_data))
66
+ if len(recv_data) < length + 6:
67
+ continue
68
+ transaction_id = struct.unpack('>H', recv_data[0:2])[0]
69
+ protocol_id = struct.unpack('>H', recv_data[2:4])[0]
70
+ unit_id = recv_data[6]
71
+ func_code = recv_data[7]
72
+ if transaction_id != send_transaction_id:
73
+ self.logger.warning('Receive a reply with a mismatched transaction id (S: {}, R: {}), discard it and continue waiting.'.format(send_transaction_id, transaction_id))
74
+ length = 0
75
+ recv_data = b''
76
+ continue
77
+ elif protocol_id != self._protocol_id:
78
+ self.logger.warning('Receive a reply with a mismatched protocol id (S: {}, R: {}), discard it and continue waiting.'.format(self._protocol_id, protocol_id))
79
+ length = 0
80
+ recv_data = b''
81
+ continue
82
+ elif unit_id != send_unit_id:
83
+ self.logger.warning('Receive a reply with a mismatched unit id (S: {}, R: {}), discard it and continue waiting.'.format(send_unit_id, unit_id))
84
+ length = 0
85
+ recv_data = b''
86
+ continue
87
+ elif func_code != send_func_code and func_code != send_func_code + 0x80:
88
+ self.logger.warning('Receive a reply with a mismatched func code (S: {}, R: {}), discard it and continue waiting.'.format(send_func_code, func_code))
89
+ length = 0
90
+ recv_data = b''
91
+ continue
92
+ else:
93
+ code = 0
94
+ break
95
+ if code == 0 and len(recv_data) == 9:
96
+ self.logger.error('modbus tcp data exception, exp={}, res={}'.format(recv_data[8], recv_data))
97
+ return recv_data[8], recv_data
98
+ elif code != 0:
99
+ self.logger.error('recv timeout, len={}, res={}'.format(len(recv_data), recv_data))
100
+ return code, recv_data
101
+
102
+ def __pack_to_send(self, pdu_data, unit_id=None):
103
+ self._transaction_id = self._transaction_id % 65535 + 1
104
+ unit_id = unit_id if unit_id is not None else self._unit_id
105
+ data = struct.pack('>HHHB', self._transaction_id, self._protocol_id, len(pdu_data) + 1, unit_id)
106
+ data += pdu_data
107
+ self.sock.send(data)
108
+
109
+ def __request(self, pdu, unit_id=None):
110
+ with self._lock:
111
+ self._func_code = pdu[0]
112
+ self.__pack_to_send(pdu)
113
+ return self.__wait_to_response(unit_id=unit_id, func_code=pdu[0])
114
+
115
+ def __read_bits(self, addr, quantity, func_code=0x01):
116
+ assert func_code == 0x01 or func_code == 0x02
117
+ pdu = struct.pack('>BHH', func_code, addr, quantity)
118
+ code, res_data = self.__request(pdu)
119
+ if code == 0 and len(res_data) == 9 + (quantity + 7) // 8:
120
+ return code, [(res_data[9 + i // 8] >> (i % 8) & 0x01) for i in range(quantity)]
121
+ else:
122
+ return code, res_data
123
+
124
+ def __read_registers(self, addr, quantity, func_code=0x03, signed=False):
125
+ assert func_code == 0x03 or func_code == 0x04
126
+ pdu = struct.pack('>BHH', func_code, addr, quantity)
127
+ code, res_data = self.__request(pdu)
128
+ if code == 0 and len(res_data) == 9 + quantity * 2:
129
+ return 0, list(struct.unpack('>{}{}'.format(quantity, 'h' if signed else 'H'), res_data[9:]))
130
+ else:
131
+ return code, res_data
132
+
133
+ def read_coil_bits(self, addr, quantity):
134
+ """
135
+ func_code: 0x01
136
+ """
137
+ return self.__read_bits(addr, quantity, func_code=0x01)
138
+
139
+ def read_input_bits(self, addr, quantity):
140
+ """
141
+ func_code: 0x02
142
+ """
143
+ return self.__read_bits(addr, quantity, func_code=0x02)
144
+
145
+ def read_holding_registers(self, addr, quantity, signed=False):
146
+ """
147
+ func_code: 0x03
148
+ """
149
+ return self.__read_registers(addr, quantity, func_code=0x03, signed=signed)
150
+
151
+ def read_input_registers(self, addr, quantity, signed=False):
152
+ """
153
+ func_code: 0x04
154
+ """
155
+ return self.__read_registers(addr, quantity, func_code=0x04, signed=signed)
156
+
157
+ def write_single_coil_bit(self, addr, on):
158
+ """
159
+ func_code: 0x05
160
+ """
161
+ pdu = struct.pack('>BHH', 0x05, addr, 0xFF00 if on else 0x0000)
162
+ return self.__request(pdu)[0]
163
+
164
+ def write_single_holding_register(self, addr, reg_val):
165
+ """
166
+ func_code: 0x06
167
+ """
168
+ pdu = struct.pack('>BHH', 0x06, addr, reg_val)
169
+ return self.__request(pdu)[0]
170
+
171
+ def write_multiple_coil_bits(self, addr, bits):
172
+ """
173
+ func_code: 0x0F
174
+ """
175
+ datas = [0] * ((len(bits) + 7) // 8)
176
+ for i in range(len(bits)):
177
+ if bits[i]:
178
+ datas[i // 8] |= (1 << (i % 8))
179
+ pdu = struct.pack('>BHHB{}B'.format(len(datas)), 0x0F, addr, len(bits), len(datas), *datas)
180
+ return self.__request(pdu)[0]
181
+
182
+ def write_multiple_holding_registers(self, addr, regs):
183
+ """
184
+ func_code: 0x10
185
+ """
186
+ pdu = struct.pack('>BHHB{}H'.format(len(regs)), 0x10, addr, len(regs), len(regs) * 2, *regs)
187
+ return self.__request(pdu)[0]
188
+
189
+ def mask_write_holding_register(self, addr, and_mask, or_mask):
190
+ """
191
+ func_code: 0x16
192
+ """
193
+ pdu = struct.pack('>BHHH', 0x16, addr, and_mask, or_mask)
194
+ return self.__request(pdu)[0]
195
+
196
+ def write_and_read_holding_registers(self, r_addr, r_quantity, w_addr, w_regs, r_signed=False, w_signed=False):
197
+ """
198
+ func_code: 0x17
199
+ """
200
+ pdu = struct.pack('>BHHHHB{}{}'.format(len(w_regs), 'h' if w_signed else 'H'), 0x17, r_addr, r_quantity, w_addr, len(w_regs), len(w_regs) * 2, *w_regs)
201
+ code, res_data = self.__request(pdu)
202
+ if code == 0 and len(res_data) == 9 + r_quantity * 2:
203
+ return 0, struct.unpack('>{}{}'.format(r_quantity, 'h' if r_signed else 'H'), res_data[9:])
204
+ else:
205
+ return code, res_data
xarm/tools/threads.py ADDED
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env python3
2
+ # Software License Agreement (BSD License)
3
+ #
4
+ # Copyright (c) 2018, UFactory, Inc.
5
+ # All rights reserved.
6
+ #
7
+ # Author: Vinman <vinman.wen@ufactory.cc> <vinman.cub@gmail.com>
8
+
9
+
10
+ class ThreadManage(object):
11
+ def __init__(self):
12
+ self.threads = []
13
+
14
+ def append(self, thread):
15
+ self.threads.append(thread)
16
+
17
+ def remove(self, thread):
18
+ if thread in self.threads:
19
+ self.threads.remove(thread)
20
+
21
+ def join(self, timeout=None):
22
+ for t in self.threads:
23
+ try:
24
+ t.join(timeout=timeout)
25
+ except:
26
+ pass
27
+ self.threads.clear()
28
+
29
+ def count(self):
30
+ return len(self.threads)
xarm/tools/utils.py ADDED
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env python3
2
+ # Software License Agreement (BSD License)
3
+ #
4
+ # Copyright (c) 2020, UFACTORY, Inc.
5
+ # All rights reserved.
6
+ #
7
+ # Author: Vinman <vinman.wen@ufactory.cc> <vinman.cub@gmail.com>
8
+ import math
9
+ import time
10
+ import sys
11
+ import traceback
12
+
13
+
14
+ def pprint(*args, **kwargs):
15
+ try:
16
+ stack_tuple = traceback.extract_stack()[0]
17
+ # filename = stack_tuple[0]
18
+ linenumber = stack_tuple[1]
19
+ # funcname = stack_tuple[2]
20
+ print('[{}][line:{}]'.format(
21
+ time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())),
22
+ linenumber
23
+ ), end=' ')
24
+ except:
25
+ pass
26
+ print(*args, **kwargs)
27
+
28
+
29
+ def is_prime(n):
30
+ def _is_prime():
31
+ for i in range(6, int(math.sqrt(n) + 1), 6):
32
+ if n % (i - 1) == 0 or n % (i + 1) == 0:
33
+ return False
34
+ return True
35
+ return n == 2 or n == 3 or (n > 1 and n % 2 != 0 and n % 3 != 0 and _is_prime())
36
+
xarm/version.py ADDED
@@ -0,0 +1 @@
1
+ __version__ = '1.15.2'
@@ -0,0 +1 @@
1
+ from .xarm_api import XArmAPI
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env python3
2
+ # Software License Agreement (BSD License)
3
+ #
4
+ # Copyright (c) 2021, UFACTORY, Inc.
5
+ # All rights reserved.
6
+ #
7
+ # Author: Vinman <vinman.wen@ufactory.cc> <vinman.cub@gmail.com>
8
+
9
+ import functools
10
+ from ..x3.studio import Studio
11
+ from .xarm_api import XArmAPI
12
+
13
+
14
+ class XArmStudioAPI(Studio):
15
+ def __init__(self, ip, ignore_warnning=False):
16
+ super(XArmStudioAPI, self).__init__(ip, ignore_warnning=ignore_warnning)
17
+ self.arm = self.__RemoteXArmAPI(self.call_sdk_api)
18
+
19
+ class __RemoteXArmAPI(XArmAPI):
20
+ def __init__(self, call_sdk_func, **kwargs):
21
+ XArmAPI.__init__(self, do_not_open=True)
22
+ self._arm = self.__RemoteXArm(call_sdk_func, self._arm)
23
+
24
+ class __RemoteXArm:
25
+ def __init__(self, call_sdk_func, _arm):
26
+ self.__call_sdk_func = call_sdk_func
27
+ self.__arm = _arm
28
+
29
+ def __getattr__(self, item):
30
+ if item.startswith(('register', 'release', 'arm_cmd')):
31
+ raise Exception('Cannot remotely call interfaces that cannot serialize parameters or results')
32
+ attr = getattr(self.__arm, item)
33
+ remote_api = functools.partial(self.__call_sdk_func, api_name=item)
34
+ return remote_api if callable(attr) else remote_api()