Python Forum

Full Version: object base multi threading
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hi,
I am trying to automate the production system using multi-threading. I have a class workstation and it has a function "drawing_thread" that runs a separate thread for each instance of that class, currently, i have three instances of that class and they are supposed to run three treads on certain conditions but only first thread is working well not others even the check condition is true for other threads.
Workstation class code
# Import libraries
import requests,time,db_quries
import threading
from datetime import datetime
import helper_functions as HF
LocIP = '192.168.100.100'
# Local port for server
LocPort = 4321
class Workstation():
    # Call the Thread class's init function


    def __init__(self,FCell):
        """
        constructor for class workstation
        :param FCell:
        """
        self.FCell = FCell # cell number

        #initial values of component's flag
        self.frame_done = True
        self.screen_done = False
        self.kpad_done = False

        #flags for order compeltion
        self.make = 1
        self.complete = 0
        self.thread_flag=True



    #mutators for object variables

    def make_setter(self):
        self.make = self.make+1
        #print('FL1: Make ',self.make)

    def set_m(self,m):
        self.make=m

    def complete_setter(self,complete):
            self.complete =complete
            #print('FL1: complete ',self.complete)

    def set_frame(self, value):
        self.frame_done = value

    def set_screen(self, value):
        self.screen_done = value

    def set_kpad(self, value):
        self.kpad_done = value

    def set_thread_flag(self,value):

        self.thread_flag = value


    #******************************
    #   Events subscriptions
    #******************************
    # Event subscriptions for conveyor

    def event_subscriptions_4_zones(self, zone_name,LocIP, LocPort,i):
        """
        this method subscribe a workstation to the event for all zones of conveyor
        on that workstation

        :param zone_name:zones on convyor
        :param LocIP:IP of application
        :param LocPort:application port waiting for response from RTU
        :return: nothing
        """
        # application (192.168.103.200:4321) Subscribe  to events on Zones
        # Prepare URL and body for the environment
        URLb = 'http://192.168.' + self.FCell + '.2/rest/events/' + zone_name + '_Changed/notifs'
        # application URl
        body = {"destUrl": "http://" + LocIP + ':' + str(LocPort)+'/CNV_events'}
        # Submit POST request
        #print(body)
        r = requests.post(URLb, json=body)
        # Collect on cont the response's body
        cont = r.json()
        # Shows information and subscription id in console
        # populating subscription Table
        # db_quries.insert_subscriptions((self.FCell, 'CNV', 'Z' + str(i),
        #                            str(r.status_code),r.reason,
        #                            datetime.now().strftime("%m/%d/%Y, %H:%M:%S")))
        # time.sleep(2)
        print('Workstation ',self.FCell,'_EVENT_' + zone_name + '_Changed subscription',
              r.status_code, r.reason, cont['id'])

    # Event subscriptions for Robot

    def event_subscriptions_4_robot(self, LocIP, LocPort, event_name):
        """
        this method subscribe a workstation to the events for robot
        on that workstation

        :param event_name:robot actions
        :param LocIP:IP of application
        :param LocPort:application port waiting for response from RTU
        :return: nothing
        """
        # Subscribe 192.168.103.200:4321 to events on event_name
        # Prepare URL and body for the environment
        URLb = 'http://192.168.' + self.FCell + '.1/rest/events/' + event_name + '/notifs'
        body = {"destUrl": "http://" + LocIP + ':' + str(LocPort)+'/rob_events'}
        # Submit POST request
        r = requests.post(URLb, json=body)#,data={"FCell":self.FCell}
        # Collect on cont the response's body
        cont = r.json()
        # Shows information and subscription id in console
        # populating subscription Table
        # db_quries.insert_subscriptions((self.FCell, 'Robot', 'DrawStartExecution',
        #                            str(r.status_code),r.reason,
        #                            datetime.now().strftime("%m/%d/%Y, %H:%M:%S")))
        # time.sleep(2)

        print('Workstation ',self.FCell,'_EVENT_' + event_name + '_Changed subscription',
              r.status_code, r.reason, cont)


    #******************************
    #   Invoking services
    #******************************

    #invoking services on conveyor

    def get_zone_status(self, zone_name):
        """
        checks weather a zone is occupied or empty
        :param zone_name:zone at conveyor
        :return:pallet ID at zone
        """
        URLb = 'http://192.168.' + self.FCell + '.2/rest/services/' + zone_name
        # Submit POST request
        body = {}
        # if zone_name == 'Z1':
        r = requests.post(URLb, json=body)
        #print('Pallet status at ' + zone_name + ' :',r.json())
        #     print('Pallet status at ' + zone_name + ' :',r.text)
        #     try:
        #          return r.json()['PalletID']
        #
        #     except ValueError:
        #         print('Decoding JSON has failed......\nPlease rebot CNV RTU! at ',self.FCell)
        #     return r.json()['PalletID']
        # else:
            #r = requests.post(URLb, json=body)
            #status_all='-1'
            # r.content>>> to see contents in bytes
            # r.text>>> serilaized JSON (json string) then use json.loads to deserialized (python dict)
            # more simpler way to get deserialized use .json() method
        try:
            return r.json()['PalletID']

        except ValueError:
            print('Decoding JSON has failed......\nPlease rebot CNV RTU! at ',self.FCell)
        return r.json()['PalletID']
            #print('Pallet status at ' + zone_name + ' :',r.json()['PalletID'])

    def TransZone(self, transfer):
        """
        execute the pallet transfer on conveyor
        :param transfer:zone name according to FASTory API
        :return:
        """
        # Prepare URL for the environment

        URLa = 'http://192.168.' + self.FCell + '.2/rest/services/TransZone' + str(transfer)
        # Submit POST request to app for getting event body
        r = requests.post(URLa, json={"destUrl": ""})

        # Shows response in console
        # print('Service TransZone' + transfer, r.status_code, r.reason)
        # if r.status_code ==200:
        #     db_quries.insert_services((self.FCell,'Service TransZone ' + transfer,
        #                              str(r.status_code),r.reason,
        #                              datetime.now().strftime("%m/%d/%Y, %H:%M:%S")))
        #
        # else:
        #     db_quries.insert_services((self.FCell, 'Service TransZone ' + transfer,
        #                              str(r.status_code),r.reason,
        #                              datetime.now().strftime("%m/%d/%Y, %H:%M:%S")))

    #invoking services on robot

    def DrawingRecipes(self, drawing):
        """

        :param drawing:recipes of cell phone model
        :return:
        """
        # Prepare URL for the environment
        URLa = 'http://192.168.' + self.FCell + '.1/rest/services/' + drawing
        # Submit POST request
        headers={"Content-Type":"application/json"}
        r = requests.post(URLa, json={"destUrl": ""}, headers=headers)
        #Shows response in console
        print('\nService ',drawing, r.status_code, r.reason,URLa)
        # if r.status_code ==200:
        #     db_quries.insert_services((self.FCell,'Service ' +drawing,
        #                              str(r.status_code),r.reason,
        #                              datetime.now().strftime("%m/%d/%Y, %H:%M:%S")))
        #     time.sleep(2)
        # else:
        #     db_quries.insert_services((self.FCell, 'Service ' + drawing,
        #                              str(r.status_code),r.reason,
        #                              datetime.now().strftime("%m/%d/%Y, %H:%M:%S")))
        #     time.sleep(2)



    def changePenColor(self, desire_color):

        """
        All Grippers have incorrect offset and stuck with pallet during
        changing pen so i am not calling it.
        :param desire_color:
        :return:
        """
        # Prepare URL for the environment
        URLa = 'http://192.168.' + self.FCell + '.1/rest/services/' + desire_color
        # Submit POST request
        r = requests.post(URLa, json={"destUrl": ""})
        # Shows response in console
        #print('\nService ',desire_color, r.status_code, r.reason)

    #*******************************************
    #   Pallet control Logic and Drawing thread
    #*******************************************
    def pallet_control(self):
        """

        :param self:
        :return:
        """
        # routing between Z2 and Z4
        if (self.get_zone_status('Z1') != '-1' and
                self.get_zone_status('Z2') == '-1'
            ):
            self.TransZone('12')
            time.sleep(1)

        elif (self.get_zone_status('Z1') != '-1' and
              self.get_zone_status('Z2') != '-1'
            ):
            # print('Zone 2 is busy')
            self.TransZone('14')
            # print('Discarded Order is: ', pending_order.pop(2))
            time.sleep(1)
            if (self.get_zone_status('Z5') == '-1'):
              self.TransZone('45')
              time.sleep(1)
            # next station zone transfer

        if (self.get_zone_status('Z2') != '-1' and
                self.get_zone_status('Z3') == '-1'
            ):

            self.TransZone('23')
            time.sleep(1)
#######################################################
    def production(self,WS_obj, OrderList):
        # unpack orders
        for i in range(len(OrderList)):
            if len(OrderList) == 0:
                print('Order list is empty..........')
                break
            ord_under_prod = OrderList.pop(0)
            print(i, len(OrderList), ord_under_prod)
            ord_num = list(ord_under_prod.keys())[0]
            order_specs = ord_under_prod[ord_num][0:4]
            order_quantity = ord_under_prod[ord_num][-1]
            # Drawing process starts
            for j in range(1, order_quantity + 1):
                print(j, 'OUTside While\n')
                while WS_obj.complete != 1:
                    WS_obj.pallet_control()
                    # print('Helper  ',WS_obj.FCell)
                    time.sleep(5)  # modification
                    if WS_obj.get_zone_status('Z3') != '-1':
                        if (WS_obj.make == 1 and WS_obj.frame_done == True):
                            WS_obj.DrawingRecipes(order_specs[0])
                            print('app_6:Printing Frame on....' + WS_obj.FCell, WS_obj.frame_done)
                            WS_obj.set_frame(False)

                            # time.sleep(1)

                        if (WS_obj.make == 2 and WS_obj.screen_done == True):
                            WS_obj.DrawingRecipes(order_specs[1])
                            print('app_7:Printing Screen on....' + WS_obj.FCell, WS_obj.screen_done)
                            WS_obj.set_screen(False)

                            # time.sleep(1)

                        if (WS_obj.make == 3 and WS_obj.kpad_done == True):
                            WS_obj.DrawingRecipes(order_specs[2])
                            print('app_8:Printing Keypad on....' + WS_obj.FCell, WS_obj.kpad_done)
                            WS_obj.set_kpad(False)
                            # time.sleep(1)

                if WS_obj.complete == 1:
                    WS_obj.set_frame(True)
                    WS_obj.TransZone('35')
                    # passing to next station

                    print('completed order is: ', WS_obj.FCell,
                          tuple(
                              (ord_num, order_specs[0], order_specs[1], order_specs[2],
                               order_specs[3], str(j) + '/' + str(order_quantity))
                          )
                          )
                    WS_obj.complete_setter(0)
                    print(WS_obj.complete, WS_obj.frame_done,
                          WS_obj.screen_done, WS_obj.kpad_done)
                    time.sleep(1)
                    # WS_obj.set_thread_flag(False)
######################################################

    def drawing_thread(self,WS_obj, OrderList):
            self.thread_flag = False
            drawing = threading.Thread(target=self.production, args=(WS_obj, OrderList))
            drawing.start()
############################################################


Function in main that calls the drawing_thread function
WS_obj_list, contains the instances of class
OrderList, is global variable that contains the drawing model
def process_thread():
    while True:
        if WS_obj_list[0].thread_flag and WS_obj_list[0].get_zone_status('Z1') != '-1':
            WS_obj_list[0].drawing_thread((WS_obj_list[0], OrderList))

        if WS_obj_list[1].thread_flag and WS_obj_list[1].get_zone_status('Z1') != '-1':  #
            WS_obj_list[1].drawing_thread((WS_obj_list[1], OrderList))

     time.sleep(5)
  • I can't figure out why other threads are not working, it seems that they are hanged.
  • according to my understanding each object is starting its own threads so there is no conflict between common resource sharing