Jan-29-2020, 11:21 AM
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
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
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
