From 1e322b2724eddc0f6957a38d45392e02af57f808 Mon Sep 17 00:00:00 2001 From: Roberto Borghes <roberto.borghes@gaia.elettra.trieste.it> Date: Fri, 1 Oct 2021 13:01:05 +0200 Subject: [PATCH] Better reconnection phase, python3 compatible --- src/bcs.py | 371 +++++++++++++++++++++++++++-------------------------- 1 file changed, 188 insertions(+), 183 deletions(-) diff --git a/src/bcs.py b/src/bcs.py index 3f350e2..6f3d886 100755 --- a/src/bcs.py +++ b/src/bcs.py @@ -67,8 +67,8 @@ class BCS(PyTango.Device_4Impl): #------------------------------------------------------------------ def delete_device(self): #print "[Device delete_device method] for device",self.get_name() - if self.connectionOk: - self.s.close() + if self.connectionOk: + self.s.close() del self.s @@ -79,9 +79,10 @@ class BCS(PyTango.Device_4Impl): #print "In ", self.get_name(), "::init_device()" self.set_state(PyTango.DevState.ON) self.get_device_properties(self.get_device_class()) - self.connectionOk = False - self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - self.load_db() + self.connectionOk = False + self.s = None + self.lastConnectionTime = 0 + self.load_db() #------------------------------------------------------------------ # Always excuted hook method @@ -100,7 +101,7 @@ class BCS(PyTango.Device_4Impl): #------------------------------------------------------------------ def read_attr_hardware(self,data): #print "In ", self.get_name(), "::read_attr_hardware()" - return + return #------------------------------------------------------------------ @@ -128,24 +129,24 @@ class BCS(PyTango.Device_4Impl): def WriteRead(self, argin): #print "In ", self.get_name(), "::Acquire()" # Add your own code here - reply = None - if not self.connectToBCS(): - return reply - try: - self.s.sendall(argin+"\r\n") - # Sockets from which we expect to read - timeout=2.5 - readable = select([self.s],[],[],timeout) - if readable: - reply = self.s.recv(256) - except Exception,e: - self.failures += 1 - if self.failures == 10: - self.connectionOk = False - self.s.close() - self.error_stream("BCS Communication error %s" % str(reply)) - PyTango.Except.throw_exception("BCS Communication error",e.strip(),"readUesFromBCS") - return reply.split("\r\n")[0] + reply = None + if not self.connectToBCS(): + return reply + try: + self.s.sendall((argin+"\r\n").encode('utf-8')) + # Sockets from which we expect to read + timeout=2.5 + readable = select([self.s],[],[],timeout) + if readable: + reply = str(self.s.recv(1024)) + except Exception as e: + self.failures += 1 + if self.failures == 10: + self.connectionOk = False + self.s.close() + self.error_stream("BCS Communication error %s" % str(reply)) + PyTango.Except.throw_exception("BCS Communication error",e.strip(),"WriteRead") + return reply.split("\r\n")[0] #================================================================== @@ -160,32 +161,32 @@ class BCS(PyTango.Device_4Impl): #------------------------------------------------------------------ def readFromBCS(self, attr): # Add your own code here - bcs_full_cmd = "GET "+ self.BCS_cmds[attr.get_name()] - reply = self.WriteRead(bcs_full_cmd) - tokens = reply.strip().split(",") - if len(tokens) != 5: - self.error_stream("BCS Communication error %s" % str(reply)) - PyTango.Except.throw_exception("BCS Communication error",reply,"readFromBCS") + bcs_full_cmd = "GET "+ self.BCS_cmds[attr.get_name()] + reply = self.WriteRead(bcs_full_cmd) + tokens = reply.strip().split(",") + if len(tokens) != 5: + self.error_stream("BCS Communication error %s" % str(reply)) + PyTango.Except.throw_exception("BCS Communication error",reply,"readFromBCS") if attr.get_data_type() == PyTango.DevLong: - value = int(tokens[3]) - else: - value = float(tokens[3]) - attr.set_value(value) + value = int(tokens[3]) + else: + value = float(tokens[3]) + attr.set_value(value) #------------------------------------------------------------------ # writeToBCS attribute #------------------------------------------------------------------ def writeToBCS(self, attr): # Add your own code here - value_in = attr.get_write_value() - if attr.get_max_dim_x() > 1: - bcs_full_cmd = "SET " + (self.BCS_cmds[attr.get_name()] % tuple(value_in)) - else: - bcs_full_cmd = "SET " + (self.BCS_cmds[attr.get_name()] % (value_in)) - reply = self.WriteRead(bcs_full_cmd) - if not "OK" in reply: - self.error_stream("BCS Communication error %s" % str(reply)) - PyTango.Except.throw_exception("BCS Communication error",reply,"writeToBCS") + value_in = attr.get_write_value() + if attr.get_max_dim_x() > 1: + bcs_full_cmd = "SET " + (self.BCS_cmds[attr.get_name()] % tuple(value_in)) + else: + bcs_full_cmd = "SET " + (self.BCS_cmds[attr.get_name()] % (value_in)) + reply = self.WriteRead(bcs_full_cmd) + if not "OK" in reply: + self.error_stream("BCS Communication error %s" % str(reply)) + PyTango.Except.throw_exception("BCS Communication error",reply,"writeToBCS") #------------------------------------------------------------------ @@ -193,43 +194,47 @@ class BCS(PyTango.Device_4Impl): #------------------------------------------------------------------ def readUesFromBCS(self, attr): # Add your own code here - bcs_full_cmd = "GETUES "+ self.BCS_cmds[attr.get_name()] - reply = self.WriteRead(bcs_full_cmd) - tokens = reply.strip().split(",") - if len(tokens) != 2: - self.error_stream("BCS Communication error %s" % str(reply)) - yTango.Except.throw_exception("BCS Communication error",reply,"readUesFromBCS") - value = int(tokens[0]) - attr.set_value(value) + bcs_full_cmd = "GETUES "+ self.BCS_cmds[attr.get_name()] + reply = self.WriteRead(bcs_full_cmd) + tokens = reply.strip().split(",") + if len(tokens) != 2: + self.error_stream("BCS Communication error %s" % str(reply)) + yTango.Except.throw_exception("BCS Communication error",reply,"readUesFromBCS") + value = int(tokens[0]) + attr.set_value(value) #------------------------------------------------------------------ # writedUesToBCS attribute #------------------------------------------------------------------ def writedUesToBCS(self, attr): # Add your own code here - value_in = attr.get_write_value() - bcs_full_cmd = "UES %s %d" % (self.BCS_cmds[attr.get_name()], value_in) - reply = self.WriteRead(bcs_full_cmd) - if not "OK" in reply: - self.error_stream("BCS Communication error %s" % str(reply)) - PyTango.Except.throw_exception("BCS Communication error",reply,"writedUesToBCS") + value_in = attr.get_write_value() + bcs_full_cmd = "UES %s %d" % (self.BCS_cmds[attr.get_name()], value_in) + reply = self.WriteRead(bcs_full_cmd) + if not "OK" in reply: + self.error_stream("BCS Communication error %s" % str(reply)) + PyTango.Except.throw_exception("BCS Communication error",reply,"writedUesToBCS") #------------------------------------------------------------------ # readFromBCS attribute #------------------------------------------------------------------ def connectToBCS(self): - try: - if not self.connectionOk: - self.failures = 0 - self.info_stream("BCS connection") - self.s.connect((self.Bcs_server, self.Bcs_port)) - self.connectionOk = True - self.set_state(PyTango.DevState.ON) - except Exception,e: - self.connectionOk = False - self.set_state(PyTango.DevState.FAULT) - return self.connectionOk - + try: + if not self.connectionOk and (time.time() - self.lastConnectionTime) > 10: + self.failures = 0 + self.lastConnectionTime = time.time() + self.info_stream("BCS connection") + if self.s is not None: + del self.s + self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.s.connect((self.Bcs_server, self.Bcs_port)) + self.connectionOk = True + self.set_state(PyTango.DevState.ON) + except Exception as e: + self.connectionOk = False + self.set_state(PyTango.DevState.FAULT) + return self.connectionOk + #------------------------------------------------------------------ # load_db: @@ -238,116 +243,116 @@ class BCS(PyTango.Device_4Impl): # argin: #------------------------------------------------------------------ def load_db(self): - self.BCS_cmds = {} - if self.Use_local_file_DB: - fo = open(self.Bcs_db[0], "r") - self.Bcs_db = fo.readlines() - fo.close() - self.Bcs_db = filter(None,self.Bcs_db) - UES_lines = [] - GET_lines = [] - SET_lines = [] - section = None - UES_idx = self.Bcs_db.index("#UES") - GET_idx = self.Bcs_db.index("#GET") - SET_idx = self.Bcs_db.index("#SET") - # - if UES_idx == min(UES_idx,GET_idx,SET_idx): - UES_list_full = self.Bcs_db[UES_idx+1:min(GET_idx,SET_idx)] - elif UES_idx == max(UES_idx,GET_idx,SET_idx): - UES_list_full = self.Bcs_db[UES_idx+1:] - else: - UES_list_full = self.Bcs_db[UES_idx+1:max(GET_idx,SET_idx)] - # - if GET_idx == min(UES_idx,GET_idx,SET_idx): - GET_list_full = self.Bcs_db[GET_idx+1:min(UES_idx,SET_idx)] - elif GET_idx == max(UES_idx,GET_idx,SET_idx): - GET_list_full = self.Bcs_db[GET_idx+1:] - else: - GET_list_full = self.Bcs_db[GET_idx+1:max(UES_idx,SET_idx)] - # - if SET_idx == min(UES_idx,GET_idx,SET_idx): - SET_list_full = self.Bcs_db[SET_idx+1:min(UES_idx,GET_idx)] - elif SET_idx == max(UES_idx,GET_idx,SET_idx): - SET_list_full = self.Bcs_db[SET_idx+1:] - else: - SET_list_full = self.Bcs_db[SET_idx+1:max(UES_idx,GET_idx)] - # UES Sub-lists of 3 lines - UES_list = [UES_list_full[i:i+3] for i in range(0, len(UES_list_full), 3)] - # GET Sub-lists of 3 lines - GET_list = [GET_list_full[i:i+3] for i in range(0, len(GET_list_full), 3)] - # SET Sub-lists of different numbero of lines - count = 0 - SET_list = [] - is_new = True - tmp_list = None - for line in SET_list_full: - if (is_new) and ("," not in line): - if tmp_list: - SET_list.append(tmp_list) - tmp_list = [line] - is_new = False - continue - tmp_list.append(line) - if ("," in line): - is_new = True - if tmp_list: - SET_list.append(tmp_list) - # - for getpoint in GET_list: - attrName = getpoint[0] - attrinfo = getpoint[2].split(",") - if attrinfo[0] == "A": - attrtype = PyTango.ArgType.DevFloat - else: - attrtype = PyTango.ArgType.DevLong - self.BCS_cmds[attrName] = "%s" % getpoint[1] - dynAttr = PyTango.Attr(attrName, attrtype) - if attrinfo[1] != "": - def_prop = PyTango.UserDefaultAttrProp() - def_prop.set_unit(attrinfo[1]) - def_prop.set_display_unit(attrinfo[1]) - def_prop.set_standard_unit(attrinfo[1]) - def_prop.set_label(attrName); - dynAttr.set_default_properties(def_prop); - - a = self.add_attribute(dynAttr,self.readFromBCS) - if (PyTango.__version_info__[0] == 8) and (attrinfo[-2] == "C"): - # "Easy" Attribute Polling available only with PyTango 8.x - self.poll_attribute(attrName,int(attrinfo[-1])) - # - for uespoint in UES_list: - attrName = uespoint[0] - attrtype = PyTango.ArgType.DevLong - self.BCS_cmds[attrName] = uespoint[1] - dynAttr = PyTango.Attr(attrName, attrtype, PyTango.AttrWriteType.READ_WRITE) - a = self.add_attribute(dynAttr,self.readUesFromBCS,self.writedUesToBCS) - if (PyTango.__version_info__[0] == 8) and (attrinfo[-2] == "C"): - # "Easy" Attribute Polling available only with PyTango 8.x - self.poll_attribute(attrName,int(attrinfo[-1])) - # - for setpoint in SET_list: - attrName = setpoint[0] - num_args = int(setpoint[2]) - attrinfo = setpoint[3].split(",") - if attrinfo[0] == "A": - attrtype = PyTango.ArgType.DevFloat - else: - attrtype = PyTango.ArgType.DevLong - self.BCS_cmds[attrName] = "%s" % setpoint[1] - for line in setpoint[3:]: - attrinfo = line.split(",") - self.BCS_cmds[attrName] += " " - self.BCS_cmds[attrName] += attrinfo[-1] - if attrinfo[0] == "A": - self.BCS_cmds[attrName] += ",%g" - else: - self.BCS_cmds[attrName] += ",%d" - if num_args > 1: - dynAttr = PyTango.SpectrumAttr(attrName, attrtype, PyTango.AttrWriteType.WRITE,num_args) - else: - dynAttr = PyTango.Attr(attrName, attrtype, PyTango.AttrWriteType.WRITE) - a = self.add_attribute(dynAttr,None,self.writeToBCS) + self.BCS_cmds = {} + if self.Use_local_file_DB: + fo = open(self.Bcs_db[0], "r") + self.Bcs_db = fo.readlines() + fo.close() + self.Bcs_db = list(filter(None,self.Bcs_db)) + UES_lines = [] + GET_lines = [] + SET_lines = [] + section = None + UES_idx = self.Bcs_db.index("#UES") + GET_idx = self.Bcs_db.index("#GET") + SET_idx = self.Bcs_db.index("#SET") + # + if UES_idx == min(UES_idx,GET_idx,SET_idx): + UES_list_full = self.Bcs_db[UES_idx+1:min(GET_idx,SET_idx)] + elif UES_idx == max(UES_idx,GET_idx,SET_idx): + UES_list_full = self.Bcs_db[UES_idx+1:] + else: + UES_list_full = self.Bcs_db[UES_idx+1:max(GET_idx,SET_idx)] + # + if GET_idx == min(UES_idx,GET_idx,SET_idx): + GET_list_full = self.Bcs_db[GET_idx+1:min(UES_idx,SET_idx)] + elif GET_idx == max(UES_idx,GET_idx,SET_idx): + GET_list_full = self.Bcs_db[GET_idx+1:] + else: + GET_list_full = self.Bcs_db[GET_idx+1:max(UES_idx,SET_idx)] + # + if SET_idx == min(UES_idx,GET_idx,SET_idx): + SET_list_full = self.Bcs_db[SET_idx+1:min(UES_idx,GET_idx)] + elif SET_idx == max(UES_idx,GET_idx,SET_idx): + SET_list_full = self.Bcs_db[SET_idx+1:] + else: + SET_list_full = self.Bcs_db[SET_idx+1:max(UES_idx,GET_idx)] + # UES Sub-lists of 3 lines + UES_list = [UES_list_full[i:i+3] for i in range(0, len(UES_list_full), 3)] + # GET Sub-lists of 3 lines + GET_list = [GET_list_full[i:i+3] for i in range(0, len(GET_list_full), 3)] + # SET Sub-lists of different numbero of lines + count = 0 + SET_list = [] + is_new = True + tmp_list = None + for line in SET_list_full: + if (is_new) and ("," not in line): + if tmp_list: + SET_list.append(tmp_list) + tmp_list = [line] + is_new = False + continue + tmp_list.append(line) + if ("," in line): + is_new = True + if tmp_list: + SET_list.append(tmp_list) + # + for getpoint in GET_list: + attrName = getpoint[0] + attrinfo = getpoint[2].split(",") + if attrinfo[0] == "A": + attrtype = PyTango.ArgType.DevFloat + else: + attrtype = PyTango.ArgType.DevLong + self.BCS_cmds[attrName] = "%s" % getpoint[1] + dynAttr = PyTango.Attr(attrName, attrtype) + if attrinfo[1] != "": + def_prop = PyTango.UserDefaultAttrProp() + def_prop.set_unit(attrinfo[1]) + def_prop.set_display_unit(attrinfo[1]) + def_prop.set_standard_unit(attrinfo[1]) + def_prop.set_label(attrName); + dynAttr.set_default_properties(def_prop); + + a = self.add_attribute(dynAttr,self.readFromBCS) + if (PyTango.__version_info__[0] == 8) and (attrinfo[-2] == "C"): + # "Easy" Attribute Polling available only with PyTango 8.x + self.poll_attribute(attrName,int(attrinfo[-1])) + # + for uespoint in UES_list: + attrName = uespoint[0] + attrtype = PyTango.ArgType.DevLong + self.BCS_cmds[attrName] = uespoint[1] + dynAttr = PyTango.Attr(attrName, attrtype, PyTango.AttrWriteType.READ_WRITE) + a = self.add_attribute(dynAttr,self.readUesFromBCS,self.writedUesToBCS) + if (PyTango.__version_info__[0] == 8) and (attrinfo[-2] == "C"): + # "Easy" Attribute Polling available only with PyTango 8.x + self.poll_attribute(attrName,int(attrinfo[-1])) + # + for setpoint in SET_list: + attrName = setpoint[0] + num_args = int(setpoint[2]) + attrinfo = setpoint[3].split(",") + if attrinfo[0] == "A": + attrtype = PyTango.ArgType.DevFloat + else: + attrtype = PyTango.ArgType.DevLong + self.BCS_cmds[attrName] = "%s" % setpoint[1] + for line in setpoint[3:]: + attrinfo = line.split(",") + self.BCS_cmds[attrName] += " " + self.BCS_cmds[attrName] += attrinfo[-1] + if attrinfo[0] == "A": + self.BCS_cmds[attrName] += ",%g" + else: + self.BCS_cmds[attrName] += ",%d" + if num_args > 1: + dynAttr = PyTango.SpectrumAttr(attrName, attrtype, PyTango.AttrWriteType.WRITE,num_args) + else: + dynAttr = PyTango.Attr(attrName, attrtype, PyTango.AttrWriteType.WRITE) + a = self.add_attribute(dynAttr,None,self.writeToBCS) #================================================================== @@ -425,10 +430,10 @@ def main(): U.server_init() U.server_run() - except PyTango.DevFailed,e: - print '-------> Received a DevFailed exception:',e - except Exception,e: - print '-------> An unforeseen exception occured....',e + except PyTango.DevFailed as e: + print ('-------> Received a DevFailed exception:',e) + except Exception as se: + print ('-------> An unforeseen exception occured....',e) if __name__=='__main__': -- GitLab