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.
- xarm/__init__.py +2 -0
- xarm/build_backend.py +17 -0
- xarm/core/__init__.py +2 -0
- xarm/core/comm/__init__.py +5 -0
- xarm/core/comm/base.py +303 -0
- xarm/core/comm/serial_port.py +44 -0
- xarm/core/comm/socket_port.py +150 -0
- xarm/core/comm/uxbus_cmd_protocol.py +100 -0
- xarm/core/config/__init__.py +0 -0
- xarm/core/config/x_code.py +1427 -0
- xarm/core/config/x_config.py +553 -0
- xarm/core/utils/__init__.py +3 -0
- xarm/core/utils/convert.py +124 -0
- xarm/core/utils/crc16.py +76 -0
- xarm/core/utils/debug_print.py +21 -0
- xarm/core/utils/log.py +98 -0
- xarm/core/version.py +1 -0
- xarm/core/wrapper/__init__.py +11 -0
- xarm/core/wrapper/uxbus_cmd.py +1457 -0
- xarm/core/wrapper/uxbus_cmd_ser.py +94 -0
- xarm/core/wrapper/uxbus_cmd_tcp.py +305 -0
- xarm/tools/__init__.py +0 -0
- xarm/tools/blockly/__init__.py +1 -0
- xarm/tools/blockly/_blockly_base.py +416 -0
- xarm/tools/blockly/_blockly_handler.py +1338 -0
- xarm/tools/blockly/_blockly_highlight.py +94 -0
- xarm/tools/blockly/_blockly_node.py +61 -0
- xarm/tools/blockly/_blockly_tool.py +480 -0
- xarm/tools/blockly_tool.py +1864 -0
- xarm/tools/gcode.py +90 -0
- xarm/tools/list_ports.py +39 -0
- xarm/tools/modbus_tcp.py +205 -0
- xarm/tools/threads.py +30 -0
- xarm/tools/utils.py +36 -0
- xarm/version.py +1 -0
- xarm/wrapper/__init__.py +1 -0
- xarm/wrapper/studio_api.py +34 -0
- xarm/wrapper/xarm_api.py +4416 -0
- xarm/x3/__init__.py +2 -0
- xarm/x3/base.py +2638 -0
- xarm/x3/base_board.py +198 -0
- xarm/x3/code.py +62 -0
- xarm/x3/decorator.py +104 -0
- xarm/x3/events.py +166 -0
- xarm/x3/ft_sensor.py +264 -0
- xarm/x3/gpio.py +457 -0
- xarm/x3/grammar_async.py +21 -0
- xarm/x3/grammar_coroutine.py +24 -0
- xarm/x3/gripper.py +830 -0
- xarm/x3/modbus_tcp.py +84 -0
- xarm/x3/parse.py +110 -0
- xarm/x3/record.py +216 -0
- xarm/x3/report.py +204 -0
- xarm/x3/robotiq.py +220 -0
- xarm/x3/servo.py +485 -0
- xarm/x3/studio.py +138 -0
- xarm/x3/track.py +424 -0
- xarm/x3/utils.py +43 -0
- xarm/x3/xarm.py +1928 -0
- xarm_python_sdk-1.15.2.dist-info/METADATA +103 -0
- xarm_python_sdk-1.15.2.dist-info/RECORD +63 -0
- xarm_python_sdk-1.15.2.dist-info/WHEEL +4 -0
- 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
|
xarm/tools/list_ports.py
ADDED
|
@@ -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
|
xarm/tools/modbus_tcp.py
ADDED
|
@@ -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'
|
xarm/wrapper/__init__.py
ADDED
|
@@ -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()
|