def get_prgm_name(self, N): reg = 16886 + (N - 1) * 40 self.__range_check(N, 1, 40) if not self.profiles: raise ControllerInterfaceError( "This watlow does not impliment profiles") return self.client.read_holding_string(reg, 20)
def prgm_delete(self, N): self.__range_check(N, 1, 40) if not self.profiles: raise ControllerInterfaceError( "This watlow does not impliment profiles") try: self.client.write_holding(18888, N) #set active profile self.client.write_holding( 18890, self.inv_watlow_val_dict('delete')) #delete profile except ModbusError, exp: exp.message = 'Cannot delete program. (original message: %s)' % exp.message raise # something else went wrong pass the exception on up.
def prgm_start(self, N, step): self.__range_check(N, 1, 40) if step > self.get_prgm_steps(N, exclusive=False): raise ControllerInterfaceError( "Program #%d does not have step #%d." % (N, step)) if self.get_status(exclusive=False).find("Program") >= 0: self.client.write_holding(16566, self.inv_watlow_val_dict('terminate')) time.sleep(2) self.client.write_holding(16558, N) #profile to start self.client.write_holding(16560, step) #step to start self.client.write_holding( 16562, self.inv_watlow_val_dict('start')) #start the profile
def __profile_units(self, num): ''' Get the units for the profile loops pv/sp ''' if not self.profiles: raise ControllerInterfaceError( "Profile support is required to read units.") reg = 16536 + (num - 1) * 2 profpv = self.client.read_holding(reg, 1)[0] try: tlist = [ 'absoluteTemperature', 'relativeTemperature', 'notsourced' ] if self.watlow_val_dict[profpv] in tlist: tval = self.client.read_holding( 14080 if self.interface == "RTU" else 6730, 1)[0] return u'\xb0%s' % self.watlow_val_dict[tval] else: return u'%s' % self.watlow_val_dict[profpv] except LookupError: return u'ERROR'
def get_prgm(self, N): if N == 0: return self.__get_prgm_empty() rbase = 4003 #first register to read self.__range_check(N, 1, 40) self.client.write_holding(4000, N) program = { 'steps':[], 'name': self.get_prgm_name(N, exclusive=False), 'steps_available': self.client.read_holding(1219)[0] } daylookup = ['daily', 'sun', 'mon', 'tue', 'wed', 'thur', 'fri', 'sat'] dins = [self.client.read_holding(1060+i*2)[0] == 10 for i in range(4)] analogs = self.__get_analog_input_setup() for step in range(1, 257): self.client.write_holding(4001, step) params = self.client.read_holding_signed(rbase, 4062-rbase+1) #registers 4003-4062 step_params = { 'type':'soak', 'start_type':'day', 'start_date':{'month':1, 'day':1, 'year':2000}, 'start_time':{'day':'sunday', 'hours':0, 'minutes':0, 'seconds':0}, 'loops':[ { 'enable':True, 'target':0, 'pidset':1 + 5*i, 'gsoak':False, 'isCascade': self.cascades > 0 if i == 0 else False, 'showEnable': self.combined_event[i] > 0 } for i in range(self.loops + self.cascades) ], 'events':[ {'number':i, 'value':'off'} for i in range(1, 9) if i not in self.combined_event and i != self.cond_event ], 'wait':{ 'enable':False, 'digital':[ {'number':i+1, 'enable':False, 'value':'off'} for i in range(4) if dins[i] ], 'analog':[ {'number':i+1, 'enable':False, 'value':0.0} for i in range(len(analogs)) if analogs[i] != 'off' ] }, 'duration':{'hours':0, 'minutes':0, 'seconds':0}, 'jprofile':0, 'jstep':0, 'jcount':0, 'action':'hold' } if self.loops + self.cascades == 1: step_params['loops'][0]['rate'] = 0 if params[4003-rbase] == 0:#Auto start step_params.update({ 'type':'autostart', 'start_type':['date', 'day'][params[4004-rbase]], 'start_date':{ 'month':params[4005-rbase], 'day':params[4006-rbase], 'year':params[4007-rbase] }, 'start_time':{ 'day':daylookup[params[4008-rbase]], 'hours':params[4009-rbase], 'minutes':params[4010-rbase], 'seconds':params[4011-rbase] } }) elif params[4003-rbase] in [1, 2, 3]: #ramptime, ramprate, soak step_params.update({ 'type': ['', 'ramptime', 'ramprate', 'soak'][params[4003-rbase]], 'wait':{'enable': params[4012-rbase] == 1}, 'events':[ {'number':i, 'value':'on' if params[4030-rbase-1+i] else 'off'} for i in range(1, 9) if i not in self.combined_event and i != self.cond_event ], 'loops':[ { 'enable':params[4030-rbase-1+self.combined_event[i]] == 1 \ if self.combined_event[i] else True, 'target':params[4044-rbase+i] * self.__get_scalar(i+1), 'pidset':params[4046-rbase+i] + 1 + 5*i, 'gsoak':params[4048-rbase+i] == 1, 'isCascade': self.cascades > 0 if i == 0 else False, 'showEnable': self.combined_event[i] > 0 } for i in range(self.loops + self.cascades) ] }) if self.loops + self.cascades == 1: step_params['loops'][0]['rate'] = 0 if params[4003-rbase] != 2: step_params['duration'] = { 'hours':params[4009-rbase], 'minutes':params[4010-rbase], 'seconds':params[4011-rbase] } else: step_params['loops'][0]['rate'] = params[4043-rbase] / 10.0 step_params['wait'].update({ 'digital':[ { 'number':i+1, 'enable':params[4013-rbase+i] != 0, 'value':['off', 'off', 'on'][params[4013-rbase+i]] } for i in range(4) if dins[i] ], 'analog':[ { 'number':i+1, 'enable':params[4021-rbase+i*2] == 1, 'value':params[4022-rbase+i*2] * self.__get_scalar(i+1) } for i in range(len(analogs)) if analogs[i] != 'off' ] }) elif params[4003-rbase] == 4:#Jump #if we are jumping to the same profile hprofile will be 0 prof_num = params[4050-rbase] prof_num = 0 if prof_num == N else prof_num step_params.update({ 'type':'jump', 'jprofile':prof_num, 'jstep':params[4051-rbase], 'jcount':params[4052-rbase] }) elif params[4003-rbase] == 5:#End step_params.update({ 'type':'end', 'action':['hold', 'controloff', 'alloff', 'idle'][params[4060-rbase]], 'loops':[ { 'enable':True, 'target':params[4061-rbase+i]*self.__get_scalar(i+1), 'pidset':1 + 5*i, 'gsoak':False, 'isCascade': self.cascades > 0 if i == 0 else False, 'showEnable': self.combined_event[i] > 0 } for i in range(self.loops + self.cascades) ] }) if self.loops + self.cascades == 1: step_params['loops'][0]['rate'] = 0 else:#Not a program raise ControllerInterfaceError('Program #%d does not exist' % N) program['steps'].append(step_params) if step_params['type'] == 'end': break return program
def get_prgm(self, N): try: return self.client.read_prgm(N, self.cascades > 0) except EspecError: raise ControllerInterfaceError( 'Could not read program from chamber controller.')
def get_prgm(self, N): def event_mod(vals, event): '''Get event from events/gs register block''' event -= 1 if event < 4: return self.watlow_val_dict[vals[8 + event * 2]] else: return self.watlow_val_dict[vals[24 + (event - 4) * 2]] if N == 0: return self.__get_prgm_empty() self.__range_check(N, 1, 40) if not self.profiles: raise ControllerInterfaceError( "This watlow does not impliment profiles") self.client.write_holding(18888, N) #set active profile step_count = self.client.read_holding( 18920, 1)[0] #get the number of steps in the profile if not step_count > 0: raise ControllerInterfaceError("Profile %d does not exist." % N) prgm_dict = { 'name': self.client.read_holding_string(18606, 20), 'log': self.client.read_holding(19038, 1)[0] == 106 } #is wait a valid step type haswaits = self.waits[0] != '' or self.waits[1] != '' haswaits = haswaits or self.waits[2] != '' or self.waits[3] != '' prgm_dict['haswaits'] = haswaits prgm_dict['hasenables'] = sum(self.loop_event + self.cascade_event) > 0 ranges, gsd, steps = [], [], [] for i in range(self.loops + self.cascades): tmap = self.loop_map[i] gsd.append( {'value': self.client.read_holding_float(19086 + i * 2)[0]}) if tmap['type'] == 'loop': ranges.append(self.get_loop_range(tmap['num'], exclusive=False)) else: ranges.append( self.get_cascade_range(tmap['num'], exclusive=False)) for i in range(step_count): ldata, wdata = [], [] step_type = self.watlow_val_dict[self.client.read_holding( 19094 + 170 * i, 1)[0]] sdata = {'type': step_type} #step type if step_type in ['soak', 'ramptime', 'instant']: # this step has duration. duration = self.client.read_holding(19096 + 170 * i, 6) sdata['duration'] = { 'hours': duration[0], 'minutes': duration[2], 'seconds': duration[4] } else: sdata['duration'] = {'hours': 0, 'minutes': 0, 'seconds': 0} if step_type in ['instant', 'ramptime']: params = self.client.read_holding(19114 + 170 * i, 8) #targets if step_type == 'ramprate': params = self.client.read_holding(19106 + 170 * i, 16) #rates and targets if step_type == 'end': params = self.client.read_holding(19170 + i * 170, 7) #endmodes #get all guaranteed soak enables and events gse_event = self.client.read_holding(19138 + 170 * i, 32) for j in range(self.cascades + self.loops): tmap = self.loop_map[j] if tmap['type'] == 'loop': enable_event = self.loop_event[tmap['num'] - 1] else: enable_event = self.cascade_event[tmap['num'] - 1] clp = ranges[j].copy() clp.update({ 'mode': '', 'gsoak': False, 'target': 0.0, 'rate': 0.0, 'showEnable': False, 'isCascade': False, 'cascade': False }) if step_type == 'ramprate': clp['target'] = self.mod_to_float(params[8 + j * 2:10 + j * 2]) clp['rate'] = self.mod_to_float(params[j * 2:2 + j * 2]) elif step_type in ['instant', 'ramptime']: clp['target'] = self.mod_to_float(params[j * 2:2 + j * 2]) elif step_type == 'end': if params[j * 2] == 100: clp['mode'] = 'user' elif params[j * 2] == 62: clp['mode'] = 'off' else: clp['mode'] = 'hold' clp['enable'] = True if enable_event == 0 or params[ j * 2] != 62 else False #if stepType in ['instant','ramptime','ramprate','soak']: clp['gsoak'] = gse_event[j * 2] == 63 clp['showEnable'] = enable_event != 0 clp['enable'] = True if enable_event != 0: clp['enable'] = event_mod(gse_event, enable_event) == 'on' if tmap['type'] == 'cascade': clp['isCascade'] = True clp['cascade'] = event_mod( gse_event, self.cascade_ctl_event[tmap['num'] - 1]) == 'on' ldata.append(clp) sdata['loops'] = ldata wdraw = self.client.read_holding(19122 + i * 170, 16) for j in range(4): if self.waits[j]: cwt = wdraw[j * 4] cws = self.mod_to_float(wdraw[2 + j * 4:4 + j * 4]) wts = self.watlow_val_dict[cwt] wdata.append({ 'number': j + 1, 'condition': wts, 'value': cws }) sdata['waits'] = wdata jraw = self.client.read_holding(19102 + i * 170, 3) sdata.update({'jstep': jraw[0], 'jcount': jraw[2]}) sdata['events'] = [{ 'number': j + 1, 'value': event_mod(gse_event, j + 1) } for j in range(8)] steps.append(sdata) prgm_dict['steps'] = steps prgm_dict['gs_dev'] = gsd return prgm_dict