Python Daemon status always results failed

I have prepared a urcap titled “ CapSens ” which consists of a Daemon (Python script running as an executable in the background ) process along with the Program Node and Installation Node. Inside the Python script the following tasks are performed.

  • Task 1 => Acquiring data from the sensors
  • Task 2 => Setting a certain register in the robot control unit to 1 or 0 depending upon the acquired data from the sensors

To do the above-mentioned tasks, i implemented two individual threads. To perform task 1, i have defined the class “SensorEvaluationBoard(Thread)” and for performing task 2 i have defined the class “UR_RTDE(Thread)”. Part of the Python script where it contains the threads and the XMLRPC server way of registering class objects as individual instances is specified in the following way.

#!/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 = "10.0.2.15" # UR robot's Offline Simulator 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()

# seed the pseudorandom number generator

from random import seed

from random import random

title = ""

tmp = ""

def set_title(new_title):

    global title

    title = new_title

    return title

def get_title():

    tmp = ""

    if str(title):

        tmp = title

    else:

        tmp = "No title set"

    return tmp + " (Python)"

def get_message(name):

    if str(name):

        return "Hello " + str(name) + ", welcome to PolyScope!"

    else:

        return "No name set"

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

def set_led(sid, val): 

    global data, sebSocket 

    data = bytearray() 

    data.append(0x2) 

    data.append(int (sid)) 

    data.append(int (val)) 

    

    mutexSEBSocket.acquire() 

    sebSocket.send(data) 

    mutexSEBSocket.release() 

    

def set_rgb(sid, r, g, b): 

    global data, sebSocket 

    data = bytearray() 

    data.append(0x4) 

    data.append(int (sid)) 

    data.append(int (r)) 

    data.append(int (g)) 

    data.append(int (b)) 

    

    mutexSEBSocket.acquire() 

    sebSocket.send(data) 

    mutexSEBSocket.release() 

def get_loadingCycleOfCapSen1(): 

    global loadCycleOfSensor1

    

    return loadCycleOfSensor1

def get_loadingCycleOfCapSen2():

    global loadCycleOfSensor2 

    

    return loadCycleOfSensor2

def get_loadingCycleOfCapSen3():

    global loadCycleOfSensor3 

    

    return loadCycleOfSensor3

def acq_loading_cycles():

    global loadCycleOfSensor1, loadCycleOfSensor2, loadCycleOfSensor3

    mutexSensVal.acquire()

    retString = loadCycleOfSensor1

    retString += ","

    retString += loadCycleOfSensor2

    retString += ","

    retString += loadCycleOfSensor3 

    mutexSensVal.release()  

    

    return retString

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_title, "set_title")

server.register_function(get_title, "get_title")

server.register_function(get_message, "get_message")

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_function(set_led, "set_led")

server.register_function(set_rgb, "set_rgb")

server.register_function(get_loadingCycleOfCapSen1, "get_loadingCycleOfCapSen1")

server.register_function(get_loadingCycleOfCapSen2, "get_loadingCycleOfCapSen2")

server.register_function(get_loadingCycleOfCapSen3, "get_loadingCycleOfCapSen3")

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()

In the main() function of the above-mentioned Python script, i initialize the two threads ‘th_sensevalboard’ and ‘th_rtde’ and start them one after the other. After the main() function, i tried to register the class objects which are individual threads as instances to the XMLRPC server.

The Daemon process is called via remote-procedure-call from the Installation Node of “CapSens” urcap.

Problem => Python Daemon status always results failed whenever the Daemon is started from the installation tab of the Polyscope GUI programming environment (UR control software). This is before i use the “CapSens” urcap in a given .urp robot program. I am facing difficulty in figuring out the cause behind the Python Daemon’s status being resulted as fail.

Probabale cause behind the problem => May be the way in which i register multiple class objects which are individual threads as instances to an XMLRPC server is not appropriately done. I am not sure if this is the case.

Can anyone of you have a look at the above-mentioned Python script and give me your invaluable suggestions to resolve the above-mentioned problem?

The following are the technical details of “CapSens” urcap.

Virtual Machine => URCapsStarterPackage (https://plus.universal-robots.com/download-center/urcaps-starter-package/?f=1.9.0) which is included with URCaps SDK version 1.9.0

URCap API version utilized to develop “CapSens” urcap => 1.8.0

UR10 Universal Robot Control Software => URSoftware 3.12.0.90886 (Nov 15, 2019) & URSoftware 3.11.0.82155 (Aug 20, 2019)

“CapSens” urcap => com.profactor.capsens.zip (332.9 KB)

I removed the two individual Classes which run as threads before. I implemented relevant functions to perform the above-mentioned Task 1 and then these functions are registered as methods to the XMLRPC server. Now, when i click the ‘Start Daemon’ button the in the InstallationView of the “CapSens” urcap the python Daemon runs.

The revised Python Daemon script is as follows.

#!/usr/bin/env python

import time
import sys
import string
import traceback
import logging

import socket
import struct
from time import sleep

# seed the pseudorandom number generator
from random import seed
from random import random

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 
import threading 
from threading import Thread, Lock 

sensEvalBoard_ipAddr = "" # IP address of sensor evaluation board 
sensEvalBoard_port = 0 # Port number of  of sensor evaluation board 
DEFAULT_TIMEOUT = 1 
sebSocket = None # initializing the socket object for sensor evaluation board 
sebSocketConnState = 0 
send_data_on_socket_flag, receive_data_on_socket_flag = False, False
mutexSEBSocket = Lock() 

mutexSensVal = Lock() 
loadCycleOfSensor1, loadCycleOfSensor2, loadCycleOfSensor3 = "", "", "" 
c1, c2, c3 = 0, 0, 0 
inputData, receivedData = None, None 
sensevalboard_stop_flag = False 
cnt = 0 

title = ""
tmp = ""

def set_title(new_title):
	global title
	title = new_title
	return title

def get_title():
	tmp = ""
	if str(title):
		tmp = title
	else:
		tmp = "No title set"
	return tmp + " (Python)"

def get_message(name):
	if str(name):
		return "Hello " + str(name) + ", welcome to PolyScope!"
	else:
		return "No name set"


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


def set_led(sid, val): 
    global inputData 
    
    inputData = bytearray() 
    inputData.append(0x2) 
    inputData.append(int (sid)) 
    inputData.append(int (val)) 

    send_dataOnSocket(inputData)
    
    
def set_rgb(sid, r, g, b): 
	global inputData
	
	inputData = bytearray()
	inputData.append(0x4)
	inputData.append(int (sid))
	inputData.append(int (r))
	inputData.append(int (g))
	inputData.append(int (b))
	
	send_dataOnSocket(inputData)

class ConnectionState:
    DISCONNECTED = 0
    CONNECTED = 1
    STARTED = 2
    PAUSED = 3

def connect_socket(): 
    global sebSocket 
    global sebSocketConnState 

    try:
        sebSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        # sebSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        # sebSocket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
        sebSocket.settimeout(DEFAULT_TIMEOUT)
        sebSocket.connect((sensEvalBoard_ipAddr, sensEvalBoard_port))
        sebSocketConnState = ConnectionState.CONNECTED
    except (socket.timeout, socket.error):
        sebSocket = None
        raise

def send_dataOnSocket(data): 
    global sebSocket 
    global send_data_on_socket_flag 
    
    # client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # client_socket.connect((daemon_host, daemon_port))
    # client_socket.send(data) 
    # client_socket.close()

    if sebSocket != None: 
        sebSocket.send(data) 
        send_data_on_socket_flag = True 
    else: 
        send_data_on_socket_flag = False  
        print("socket connection not established")
        print("socket reconnecting")
        connect_socket() 
    
    return send_data_on_socket_flag

def receive_dataOnSocket(data): 
    global sebSocket 
    global receive_data_on_socket_flag 
    global receivedData 
    
    # client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # client_socket.connect((daemon_host, daemon_port))
    # client_socket.send(data);  
    
    # receivedData = client_socket.recv(1024)
    # client_socket.close()

    if (send_dataOnSocket(data)): 
        receivedData = sebSocket.recv(1024) 
        receive_data_on_socket_flag = True
    else: 
        receivedData = None
        receive_data_on_socket_flag = False 
        print("socket connection not established")
        print("socket reconnecting...")
        connect_socket() 
    
    return receivedData

def get_loadingCycleOfCapSen1(): 
    global loadCycleOfSensor1
    
    return loadCycleOfSensor1

def get_loadingCycleOfCapSen2():
    global loadCycleOfSensor2 
    
    return loadCycleOfSensor2

def get_loadingCycleOfCapSen3():
    global loadCycleOfSensor3 
    
    return loadCycleOfSensor3

def acq_loading_cycles():
    global cnt, loadCycleOfSensor1, loadCycleOfSensor2, loadCycleOfSensor3
    global inputData, receivedData
    global loadingCycles
        
    while True:         
        inputData = bytearray()
        inputData.append(0x1)
        
        receivedData = receive_dataOnSocket(inputData) 
        if (receivedData != None): 
            unpacker_string = 3*'I I I I I B B B B'
            unpacker = struct.Struct('<B '+ unpacker_string)
            unpacked = unpacker.unpack(receivedData)
            
            loadCycleOfSensor1 = str(unpacked[1])
            loadCycleOfSensor2 = str(unpacked[12])
            loadCycleOfSensor3 = str(unpacked[20]) 

            cnt  = cnt + 1 		
            retString = loadCycleOfSensor1
            retString += ","
            retString += loadCycleOfSensor2
            retString += ","
            retString += loadCycleOfSensor3
            
            if (cnt == 1):
                cnt = 0 
                return retString
        else: 
            print("Received data on the socket is invalid")
            return loadCycleOfSensor1 + "," + loadCycleOfSensor2 + "," + loadCycleOfSensor3

def generate_random_values(): 
	global cnt
    
	while True: 		
		cnt  = cnt + 1
		# seed random number generator
		seed(1)
		# generate some random numbers
		val1 = round(random(), 3)
		val2 = round(random(), 3)
		val3 = round(random(), 3)
		if (cnt == 1):
			cnt = 0	 
			return str(val1) + ", " + str(val2) + ", " + str(val3)


sys.stdout.write("CapSens daemon started")
sys.stderr.write("CapSens daemon started with caught exception")

# server = SimpleXMLRPCServer(("127.0.0.1", 40405))
server = SimpleXMLRPCServer(("127.0.0.1", 40405), allow_none=True)
# server = SimpleXMLRPCServer(("127.0.0.1", 40405), logRequests=True, allow_none=True)
server.register_introspection_functions()

server.register_function(set_title, "set_title")
server.register_function(get_title, "get_title")
server.register_function(get_message, "get_message")

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_function(set_led, "set_led")
server.register_function(set_rgb, "set_rgb")

server.register_instance(ConnectionState())
server.register_function(connect_socket, "connect_socket")

server.register_function(send_dataOnSocket, "send_dataOnSocket")
server.register_function(receive_dataOnSocket, "receive_dataOnSocket")

server.register_function(get_loadingCycleOfCapSen1, "get_loadingCycleOfCapSen1")
server.register_function(get_loadingCycleOfCapSen2, "get_loadingCycleOfCapSen2")
server.register_function(get_loadingCycleOfCapSen3, "get_loadingCycleOfCapSen3")
server.register_function(acq_loading_cycles, "acq_loading_cycles")

server.register_function(generate_random_values, "generate_random_values")
server.serve_forever()

Hi,
one potential cause of a Daemon process failing are not available classes or wrong syntax in the python script.
You normally find the correspondent Log file under the directory /GUI/felix-cache/bundlexxx in either the root folder on the real robot or in the ursim-folder on the simulator.

Hello Stefan,

Thanks for pointing me in the right direction as far as debugging the Python script in combination with a URCap is concerned. This really solved all my troubles.

Now, i am able to confirm myself the following thing.

  • Individual class instances can be run as threads inside a given function which starts the threads. This particular function can be registered as a method to the XML-RPC server. When the Daemon starts, the function can be called from the URCap (in my case the function is called from the ‘XXXXXXXInstallationNodeContribution.java’ file of the URCap)

Once again, thank for your time and consideration!

Best Regards,
Sriniwas

1 Like