多线程-XMLRPC服务器在Python 2.7.12中将类对象注册为单个线程
在服务器端,我准备了一个python脚本,其中执行了以下任务多线程-XMLRPC服务器在Python 2.7.12中将类对象注册为单个线程,python,multithreading,xmlrpclib,Python,Multithreading,Xmlrpclib,在服务器端,我准备了一个python脚本,其中执行了以下任务 任务1=>从传感器获取数据 任务2=>根据从传感器获取的数据,将机器人控制单元中的某个寄存器设置为1或0 为了完成上述任务,我实现了两个单独的线程。为了执行任务1,我定义了类“SensorEvaluationBoard(Thread)”,为了执行任务2,我定义了类“UR_RTDE(Thread)”。有关更多详细信息,请从服务器端查看以下python脚本 服务器端: #!/usr/bin/env python import tim
- 任务1=>从传感器获取数据
- 任务2=>根据从传感器获取的数据,将机器人控制单元中的某个寄存器设置为1或0
#!/usr/bin/env python
import time
from time import sleep
import sys
import string
import traceback
import logging
import socket
import struct
import copy
import xmlrpclib
# xmlrpclib.Marshaller.dispatch[type(0L)] = lambda _, v, w: w("<value><i8>%d</i8></value>" % v)
# xmlrpclib.dumps((2**63-1,))
xmlrpclib.Binary
from SimpleXMLRPCServer import SimpleXMLRPCServer, SimpleXMLRPCRequestHandler
import threading
from threading import Thread, Lock
# "https://www.universal-robots.com/articles/ur-articles/real-time-data-exchange-rtde-guide/"
import rtde.rtde as rtde
import rtde.rtde_config as rtde_config
# urHost = "127.0.0.1" # UR robot's IP address
# "https://www.universal-robots.com/articles/ur-articles/remote-control-via-tcpip/"
urPort = 30004 # Port number dedicated for UR robot's secondary interface
config_filename = 'control_loop_configuration.xml'
mutexFreedriveMode = Lock()
loadCycleOfSensor1, loadCycleOfSensor2, loadCycleOfSensor3 = "", "", ""
c1, c2, c3 = 0, 0, 0
cnt = 0
data = bytearray()
sensEvalBoard_ipAddr = "" # IP address of sensor evaluation board
sensEvalBoard_port = 0 # Port number of of sensor evaluation board
DEFAULT_TIMEOUT = 1
mutexSensVal = Lock()
sebSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # initializing the socket object
mutexSEBSocket = Lock()
def set_ipaddr(new_daemon_host):
global sensEvalBoard_ipAddr
sensEvalBoard_ipAddr = new_daemon_host
return sensEvalBoard_ipAddr
def get_ipaddr():
tmp = ""
if str(sensEvalBoard_ipAddr):
tmp = sensEvalBoard_ipAddr
else:
tmp = "No ip address set"
return tmp
def set_portnum(new_daemon_port):
global sensEvalBoard_port
sensEvalBoard_port = int (new_daemon_port)
return sensEvalBoard_port
def get_portnum():
tmp = 0
if sensEvalBoard_port != 0:
tmp = sensEvalBoard_port
else:
tmp = 0
return tmp
class ConnectionState:
DISCONNECTED = 0
CONNECTED = 1
STARTED = 2
PAUSED = 3
class SensorEvaluationBoardException(Exception):
def __init__(self, msg):
self.msg = msg
def __str__(self):
return repr(self.msg)
class SensorEvaluationBoard(Thread):
def __init__(self, hostname, port):
# Call the Thread class's init function
Thread.__init__(self)
self.__hostname = hostname
self.__port = port
self.__conn_state = ConnectionState.DISCONNECTED
self.__sock = None
logging.basicConfig(level=logging.DEBUG)
self.__logger = logging.getLogger(self.__class__.__name__)
# self.__streamHandler = logging.StreamHandler()
# self.__streamHandler.setLevel(logging.DEBUG)
# self.__formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
# self.__streamHandler.setFormatter(self.__formatter)
# self.__logger.addHandler(self.__streamHandler)
def connect(self):
global sebSocket
if self.__sock:
return
self.__buf = b''
try:
self.__sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.__sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.__sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
self.__sock.settimeout(DEFAULT_TIMEOUT)
self.__sock.connect((self.__hostname, self.__port))
self.__conn_state = ConnectionState.CONNECTED
sebSocket = copy.deepcopy(self.__sock)
except (socket.timeout, socket.error):
self.__sock = None
raise
def disconnect(self):
if self.__sock:
self.__sock.close()
self.__sock = None
self.__conn_state = ConnectionState.DISCONNECTED
def is_connected(self):
return self.__conn_state is not ConnectionState.DISCONNECTED
def get_connection_state(self):
return self.__conn_state
def send_input_data(self, data):
self.__sock.send(data)
def receive_output_data(self, input_data):
self.send_input_data(input_data)
self.__rcvData = self.__sock.recv(1024)
return self.__rcvData
def run(self):
global loadCycleOfSensor1, loadCycleOfSensor2, loadCycleOfSensor3
self.connect()
while True:
if self.is_connected:
# print("Socket => connection state: " + str(self.get_connection_state()) + " means CONNECTED")
self.__input_data = bytearray()
self.__input_data.append(0x1)
self.__rcvData = self.receive_output_data(self.__input_data)
self.__unpacker_string = 3*'I I I I I B B B B'
self.__unpacker = struct.Struct('<B '+ self.__unpacker_string)
self.__unpacked = self.__unpacker.unpack(self.__rcvData)
# print("Slave 1: "+ repr(self.__unpacked[1:10]))
# print("Slave 2: "+ repr(self.__unpacked[10:19]))
# print("Slave 3: "+ repr(self.__unpacked[19:28]))
mutexSensVal.acquire()
loadCycleOfSensor1 = str(self.__unpacked[1])
loadCycleOfSensor2 = str(self.__unpacked[12])
loadCycleOfSensor3 = str(self.__unpacked[20])
# print("Load cycle of sensors 1, 2 and 3: ["+ loadCycleOfSensor1 + ", " + loadCycleOfSensor2 + ", " + loadCycleOfSensor3 + "]")
mutexSensVal.release()
sleep(0.1)
else:
print("Socket => connection state: " + str(self.get_connection_state()) + " means DISCONNECTED")
class UR_RTDE(Thread):
def __init__(self, host, port, config_filename):
# Call the Thread class's init function
Thread.__init__(self)
self.__host = host
self.__port = port
self.__config_filename = config_filename
logging.basicConfig(level=logging.DEBUG)
self.__logger = logging.getLogger(self.__class__.__name__)
# self.__streamHandler = logging.StreamHandler()
# self.__streamHandler.setLevel(logging.INFO)
# self.__formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
# self.__streamHandler.setFormatter(self.__formatter)
# self.__logger.addHandler(self.__streamHandler)
self.__con = None
self._rtde_ok = False
self._recept_ok = False
self._dataAccessConfig = Lock()
self.__keep_running = True
def init_rtde(self):
self.__logger.debug("init_rtde")
if not self._rtde_ok :
if self.__con is None:
self.connect_rtde()
if not self._recept_ok:
self.init_conf()
self.send_conf_to_robot()
self.start_communication()
self._rtde_ok = True
def connect_rtde(self):
self.__logger.debug("connect_rtde")
try:
self.__con = rtde.RTDE(self.__host, self.__port)
self.__con.connect()
except socket.timeout as e:
self.__logger.error("failed to connect with robot", exc_info=True)
self.__controller_info = None
self.__con = None
self.__controller_info = self.__con.get_controller_version()
self.__logger.info("connected with UR established")
self.__logger.info(self.__controller_info)
return True
def disconnect_rtde(self):
self.__con.send_pause()
self.__con.disconnect()
self.__logger.debug("disconnect_rtde")
def init_conf(self):
self.__logger.debug("init_conf")
with self._dataAccessConfig:
self._conf = rtde_config.ConfigFile(self.__config_filename)
self._state_names, self._state_types = self._conf.get_recipe('state')
self._set_freedrive_name, self._set_freedrive_type = self._conf.get_recipe('set_freedrive')
def send_conf_to_robot(self):
self.__logger.debug("send_conf_to_robot")
print("in send conf")
try:
self.__con.send_output_setup(self._state_names, self._state_types)
self.__set_freedrive = self.__con.send_input_setup(self._set_freedrive_name, self._set_freedrive_type)
self.__set_freedrive.__dict__[b"input_bit_register_64"] = 0
self._recept_ok = True
except Exception as e:
self.__set_freedrive = None
self.__logger.error("rtde recepts error", exc_info=True)
self._recept_ok = False
def start_communication(self):
self.__logger.debug("start_communication")
if not self.__con.is_connected():
self.__logger.warning("no connection established")
if not self.__con.send_start():
self.__logger.warning("starting data_sync failed")
sys.exit()
self.__logger.info("started communication")
return True
def run(self):
global loadCycleOfSensor1, loadCycleOfSensor2, loadCycleOfSensor3
global c1, c2, c3
lowerThr_loadCycleOfSensor1, upperThr_loadCycleOfSensor1 = 400, 700
lowerThr_loadCycleOfSensor2, upperThr_loadCycleOfSensor2 = 100, 400
lowerThr_loadCycleOfSensor3, upperThr_loadCycleOfSensor3 = 200, 425
lTh_c1 = lowerThr_loadCycleOfSensor1
uTh_c1 = upperThr_loadCycleOfSensor1
lTh_c2 = lowerThr_loadCycleOfSensor2
uTh_c2 = upperThr_loadCycleOfSensor2
lTh_c3 = lowerThr_loadCycleOfSensor3
uTh_c3 = upperThr_loadCycleOfSensor3
self.init_rtde()
# Set the 'input_bit_register_64' to 0 by default
self.__set_freedrive.__dict__[b"input_bit_register_64"] = 0
if self.__con.is_connected():
while self.__keep_running:
# receive the current state
self.__state = self.__con.receive()
if self.__state is None:
break
mutexSensVal.acquire()
c1 = int (loadCycleOfSensor1)
self.__logger.info("Loading cycle of CapSen1 is " + str(c1))
c2 = int (loadCycleOfSensor2)
self.__logger.info("Loading cycle of CapSen2 is " + str(c2))
c3 = int (loadCycleOfSensor3)
self.__logger.info("Loading cycle of CapSen3 is " + str(c3))
mutexSensVal.release()
mutexFreedriveMode.acquire()
# input_bit_register_64 refers to "general purpose input register 64"
# if "general purpose input register 64" variable is set to 1 => Freedrive mode is activated
if ((lTh_c1 < c1 < uTh_c1) and (lTh_c2 < c2 < uTh_c2)):
self.__set_freedrive.__dict__[b"input_bit_register_64"] = 1
self.__logger.info("Capacitive sensors 1 and 2 are touched by the human operator, Freedrive mode activated")
elif ((lTh_c2 < c2 < uTh_c2) and (lTh_c3 < c3 < uTh_c3)):
self.__set_freedrive.__dict__[b"input_bit_register_64"] = 1
self.__logger.info("Capacitive sensors 2 and 3 are touched by the human operator, Freedrive mode activated")
elif ((lTh_c3 < c3 < uTh_c3) and (lTh_c1 < c1 < uTh_c1)):
self.__set_freedrive.__dict__[b"input_bit_register_64"] = 1
self.__logger.info("Capacitive sensors 1 and 3 are touched by the human operator, Freedrive mode activated")
else:
self.__set_freedrive.__dict__[b"input_bit_register_64"] = 0
self.__logger.info("No two capacitive sensors are touched by the human operator, Freedrive mode deactivated")
self.__con.send(self.__set_freedrive)
mutexFreedriveMode.release()
sleep(0.1)
self.disconnect_rtde()
def main():
try:
# threadevent = threading.Event()
# Create an object of Thread
th_sensevalboard = SensorEvaluationBoard(sensEvalBoard_ipAddr, sensEvalBoard_port)
# start the SensorEvaluationBoard thread
th_sensevalboard.start()
sleep(1)
# Create an object of Thread
th_rtde = UR_RTDE(urHost, urPort, config_filename)
# start the RTDE thread
th_rtde.start()
return "SensorEvaluationBoard and RTDE threads has started..."
except KeyboardInterrupt:
print("Terminating communication with the sensor evaluation board... ")
th_sensevalboard.disconnect()
print("Socket => connection state: " + str(th_sensevalboard.get_connection_state()) + " means DISCONNECTED")
th_sensevalboard.join()
print ("SensorEvaluationBoard thread successfully closed")
print("Terminating communication with the RTDE server... ")
th_rtde.disconnect()
th_rtde.join()
print ("RTDE thread successfully closed")
return "SensorEvaluationBoard and RTDE threads has stopped..."
sys.stdout.write("CapSens daemon started")
sys.stderr.write("CapSens daemon started with caught exception")
# server_addr = ("127.0.0.1", 40405)
# server = SimpleXMLRPCServer(server_addr, SimpleXMLRPCRequestHandler, allow_none=True)
server = SimpleXMLRPCServer(("127.0.0.1", 40405), allow_none=True)
server.register_function(set_ipaddr, "set_ipaddr")
server.register_function(get_ipaddr, "get_ipaddr")
server.register_function(set_portnum, "set_portnum")
server.register_function(get_portnum, "get_portnum")
server.register_instance(UR_RTDE(urHost, urPort, config_filename), allow_dotted_names=True)
server.register_instance(SensorEvaluationBoard(sensEvalBoard_ipAddr, sensEvalBoard_port), allow_dotted_names=True)
server.register_function(main, "main")
server.serve_forever()
#/usr/bin/env python
导入时间
从时间上导入睡眠
导入系统
导入字符串
导入回溯
导入日志记录
导入套接字
导入结构
导入副本
导入xmlrpclib
#xmlrpclib.Marshaller.dispatch[type(0L)]=lambda,v,w:w(“%d”%v)
#xmlrpclib.dumps((2**63-1,)
二进制文件
从SimpleXMLRPCServer导入SimpleXMLRPCServer,SimpleXMLRPCRequestHandler
导入线程
从线程导入线程,锁定
# "https://www.universal-robots.com/articles/ur-articles/real-time-data-exchange-rtde-guide/"
将rtde.rtde作为rtde导入
将rtde.rtde_配置导入为rtde_配置
#urHost=“127.0.0.1”#您的机器人的IP地址
# "https://www.universal-robots.com/articles/ur-articles/remote-control-via-tcpip/"
urPort=30004#专用于UR机器人二次接口的端口号
config\u filename='control\u loop\u configuration.xml'
mutexFreedriveMode=Lock()
loadCycleOfSensor1、loadCycleOfSensor2、loadCycleOfSensor3=“”、“”、“”
c1,c2,c3=0,0,0
cnt=0
数据=字节数组()
传感器评估板的IP地址
sensEvalBoard_端口=0#传感器评估板的端口号
默认超时=1
mutexsenval=Lock()
sebSocket=socket.socket(socket.AF_INET,socket.SOCK_STREAM)#初始化套接字对象
mutexSEBSocket=Lock()
def set_ipaddr(新的守护进程主机):
全球感应板
sensEvalBoard\u ipAddr=新的\u守护进程\u主机
返回感应板\u ipAddr
def get_ipaddr():
tmp=“”
如果str(传感器板\u ipAddr):
tmp=传感器板\u ipAddr
其他:
tmp=“未设置ip地址”
返回tmp
def set_portnum(新的_守护进程_端口):
全球传感板端口
sensEvalBoard_端口=int(新的_守护进程_端口)
返回感应板\u端口
def get_portnum():
tmp=0
如果传感器板_端口!=0:
tmp=传感器板\u端口
其他:
tmp=0
返回tmp
类连接状态:
断开连接=0
已连接=1
开始=2
暂停=3
类SensorEvaluationBoardException(异常):
定义初始化(self,msg):
self.msg=msg
定义(自我):
返回报告(self.msg)
类传感器评估板(线程):
def uuu init uuuu(自身、主机名、端口):
#调用线程类的init函数
线程。\uuuu初始化\uuuuu(自)
self.\uuuhostname=主机名
self.\uuu端口=端口
self.\uuuu conn\u state=ConnectionState.DISCONNECTED
self.\uu sock=无
logging.basicConfig(级别=logging.DEBUG)
self.\uuuuu logger=logging.getLogger(self.\uuuuuuuuuu类\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu名称)
#self.\uuu streamHandler=logging.streamHandler()
#self.\uu streamHandler.setLevel(logging.DEBUG)
#self.\uu formatter=logging.formatter('%(asctime)s-%(name)s-%(levelname)s-%(message)s')
#self.\u streamHandler.setFormatter(self.\u格式化程序)
#self.\u logger.addHandler(self.\u streamHandler)
def连接(自):
全球SEB插座
如果是自吸式:
返回
自
尝试:
self.\u sock=socket.socket(socket.AF\u INET,socket.sock\u流)
self.\u sock.setsockopt(socket.SOL\u socket,socket.SO\u REUSEADDR,1)
self._sock.setsockopt(socket.IPPROTO_TCP,socket.TCP_NODELAY,1)
self.\u sock.settimeout(默认超时)
self.\u sock.connect((self.\u主机名,self.\u端口))
self.\uuuu conn\u state=ConnectionState.CONNECTED
sebSocket=copy.deepcopy(self.\uu sock)
除了(socket.timeout、socket.error):
self.\uu sock=无
提升
def断开(自):
如果是自吸式:
self.\uu sock.close()
self.\uu sock=无
self.\uuuu conn\u state=ConnectionState.DISCONNECTED
def已连接(自):
返回自我。连接状态不是ConnectionState.DISCONNECTED
def获取连接状态(自身):
返回自我连接状态
def发送输入数据(自身、数据):
自存储发送(数据)
def接收\输出\数据(自身、输入\数据):
发送输入数据(输入数据)
self.\uu rcvData=self.\uu sock.recv(1024)
返回自我。\uu rcvData
def运行(自):
全局loadCycleOfSensor1、loadCycleOfSensor2、loadCycleOfSensor3
self.connect()
尽管如此:
如果self.u已连接:
#打印(“套接字=>连接状态:“+str(self.get\u connection\u state())+”表示已连接)
self.\uuuu input\u data=bytearray()
self.\u输入\u数据.append(0x1)
self.\uuu rcvData=self.接收输出数据(self.\uu输入数据)
self.\uu解包程序\u string=3*'I B'
self.\uu unpacker=struct.struct('Freedrive模式已激活
如果((长周期c1