def connectDevice(self): if not self.iface: self.iface = self.ifaces[self.listDevices.currentRow()] if self.iface: if not self.iface.isConnected(): self.iface = SerialInterface(self.port, self.baud) self.iface.connectToArduino() if not self.iface.serial_conn.isOpen(): self.iface.serial_conn.open() if self.iface.isConnected(): if self.iface_thread: del self.iface_thread self.iface_thread = SerialThread(self.iface) self.iface_thread.n_samples = 1000 self.iface_thread.gotSamples[tuple, int].connect( self.plotWindow.plotSamples) #self.iface_thread.deviceDisconnected.connect(self.disconnectFromCurrentDevice) self.startSampling() return True return False
def __init__(self,*args,**kwargs): if 'debug' in kwargs: self.debug = kwargs['debug'] else: kwargs.update({'debug': DEBUG}) self.debug = DEBUG if 'baudrate' not in kwargs: kwargs.update({'baudrate': BAUDRATE}) elif (kwargs['baudrate'] is None) or (str(kwargs['baudrate']).lower() == 'default'): kwargs.update({'baudrate': BAUDRATE}) if 'timeout' not in kwargs: kwargs.update({'timeout': self._TIMEOUT}) if 'write_write_delay' not in kwargs: kwargs.update({'write_write_delay': self._WRITE_WRITE_DELAY}) if ('port' not in kwargs) or (kwargs['port'] is None): err_string = 'Specify port.\n' raise RuntimeError(err_string) else: self.port = kwargs['port'] t_start = time.time() self._serial_device = SerialInterface(*args,**kwargs) atexit.register(self._exit_mettler_toledo_device) time.sleep(self._RESET_DELAY) t_end = time.time() self._debug_print('Initialization time =', (t_end - t_start))
def __init__(self, device): self.timeout = 1 self.device = device self.speed = 57600 SerialInterface.__init__(self) self.open()
def __init__(self, device, radio_locale=None): self.timeout = 1 self.device = device self.speed = 57600 # radio_locale is not supported here SerialInterface.__init__(self) self.open()
def connectDevice(self): if not self.iface: self.iface = self.ifaces[self.listDevices.currentRow()] if self.iface: if not self.iface.isConnected(): self.iface = SerialInterface(self.port, self.baud) self.iface.connectToArduino() if not self.iface.serial_conn.isOpen(): self.iface.serial_conn.open() if self.iface.isConnected(): if self.iface_thread: del self.iface_thread self.iface_thread = SerialThread(self.iface) self.iface_thread.n_samples = 1000 self.iface_thread.gotSamples[tuple, int].connect(self.plotWindow.plotSamples) #self.iface_thread.deviceDisconnected.connect(self.disconnectFromCurrentDevice) self.startSampling() return True return False
def __init__(self, server_com_port, baudrate): # Setup serial interface. self._serial_interface = SerialInterface(server_com_port, baudrate, 50) self._serial_interface.set_read_callback(self._on_serial_read) # The byte parser analyses the byte string from the sensor # and divides it into individual sentences. self._byte_parser = ByteParser() self._current_sentence = bytearray() # If set, all raw data from serial port will be stored to this file. self._log_file = None # Locks #self._ack_lock = threading.Condition() self._wait_for_sentence_lock = threading.Condition() self._wait_for_sentence_type = None self._wait_for_sentence_data = None # Callbacks for NMEA sentences. self._GGA_cb = None self._RMC_cb = None self._GSV_cb = None self._GST_cb = None # Callbacks for ASCII sentences. self._BESTPOS_cb = None self._BESTVEL_cb = None self._TIME_cb = None self._PSRDOP_cb = None # Special callbacks. self._reset_cb = None # GSV information is sometimes split up into multiple sentences. # Need to gather all informations before calling callback. self._GSV_data = None # Total number of sentences until the GSV data we are currently # waiting for is complete self._received_GSV_sentences = 0
def __init__(self,*args,**kwargs): name = None form_factor = None serial_number = None if 'debug' in kwargs: self.debug = kwargs['debug'] else: kwargs.update({'debug': DEBUG}) self.debug = DEBUG if 'try_ports' in kwargs: try_ports = kwargs.pop('try_ports') else: try_ports = None if 'baudrate' not in kwargs: kwargs.update({'baudrate': BAUDRATE}) elif (kwargs['baudrate'] is None) or (str(kwargs['baudrate']).lower() == 'default'): kwargs.update({'baudrate': BAUDRATE}) if 'timeout' not in kwargs: kwargs.update({'timeout': self._TIMEOUT}) if 'write_read_delay' not in kwargs: kwargs.update({'write_read_delay': self._WRITE_READ_DELAY}) if 'write_write_delay' not in kwargs: kwargs.update({'write_write_delay': self._WRITE_WRITE_DELAY}) if 'name' in kwargs: name = kwargs.pop('name') if 'form_factor' in kwargs: form_factor = kwargs.pop('form_factor') if 'serial_number' in kwargs: serial_number = kwargs.pop('serial_number') if ('port' not in kwargs) or (kwargs['port'] is None): port = find_modular_device_port(baudrate=kwargs['baudrate'], name=name, form_factor=form_factor, serial_number=serial_number, try_ports=try_ports, debug=kwargs['debug']) kwargs.update({'port': port}) t_start = time.time() self._serial_interface = SerialInterface(*args,**kwargs) atexit.register(self._exit_modular_client) time.sleep(self._RESET_DELAY) self._method_dict = self._get_method_dict() try: self._method_dict_inv = dict([(v,k) for (k,v) in self._method_dict.items()]) except AttributeError: self._method_dict_inv = dict([(v,k) for (k,v) in self._method_dict.iteritems()]) self._create_methods() t_end = time.time() self._debug_print('Initialization time =', (t_end - t_start))
def run(self): while True: for port in self.ports: if port in self.found: continue try: serial = SerialInterface(port, 115200) serial.connectToArduino() if serial.isConnected(): serial.serial_conn.timeout = 0.2 # read timeout of 200 millisecond samples = serial.getSamples(20) if samples: serial.serial_conn.timeout = None self.foundDevice.emit(port, serial) self.found.append(port) else: serial.disconnect() except Exception, e: #print port, e continue finally: if serial.isConnected() and not port in self.found:
class ModularClient(object): ''' ModularClient contains an instance of serial_interface.SerialInterface and adds methods to it, like auto discovery of available modular devices in Linux, Windows, and Mac OS X. This class automatically creates methods from available functions reported by the modular device when it is running the appropriate firmware. This is the modular device client library for communicating with and calling remote methods on modular device servers. Example Usage: dev = ModularClient() # Might automatically find device if one available # if it is not found automatically, specify port directly dev = ModularClient(port='/dev/ttyACM0') # Linux specific port dev = ModularClient(port='/dev/tty.usbmodem262471') # Mac OS X specific port dev = ModularClient(port='COM3') # Windows specific port dev.get_device_id() dev.get_methods() ''' _TIMEOUT = 0.05 _WRITE_READ_DELAY = 0.001 _WRITE_WRITE_DELAY = 0.005 _RESET_DELAY = 2.0 _METHOD_ID_GET_METHOD_IDS = 0 def __init__(self,*args,**kwargs): name = None form_factor = None serial_number = None if 'debug' in kwargs: self.debug = kwargs['debug'] else: kwargs.update({'debug': DEBUG}) self.debug = DEBUG if 'try_ports' in kwargs: try_ports = kwargs.pop('try_ports') else: try_ports = None if 'baudrate' not in kwargs: kwargs.update({'baudrate': BAUDRATE}) elif (kwargs['baudrate'] is None) or (str(kwargs['baudrate']).lower() == 'default'): kwargs.update({'baudrate': BAUDRATE}) if 'timeout' not in kwargs: kwargs.update({'timeout': self._TIMEOUT}) if 'write_read_delay' not in kwargs: kwargs.update({'write_read_delay': self._WRITE_READ_DELAY}) if 'write_write_delay' not in kwargs: kwargs.update({'write_write_delay': self._WRITE_WRITE_DELAY}) if 'name' in kwargs: name = kwargs.pop('name') if 'form_factor' in kwargs: form_factor = kwargs.pop('form_factor') if 'serial_number' in kwargs: serial_number = kwargs.pop('serial_number') if ('port' not in kwargs) or (kwargs['port'] is None): port = find_modular_device_port(baudrate=kwargs['baudrate'], name=name, form_factor=form_factor, serial_number=serial_number, try_ports=try_ports, debug=kwargs['debug']) kwargs.update({'port': port}) t_start = time.time() self._serial_interface = SerialInterface(*args,**kwargs) atexit.register(self._exit_modular_client) time.sleep(self._RESET_DELAY) self._method_dict = self._get_method_dict() try: self._method_dict_inv = dict([(v,k) for (k,v) in self._method_dict.items()]) except AttributeError: self._method_dict_inv = dict([(v,k) for (k,v) in self._method_dict.iteritems()]) self._create_methods() t_end = time.time() self._debug_print('Initialization time =', (t_end - t_start)) def _debug_print(self, *args): if self.debug: print(*args) def _exit_modular_client(self): pass def _args_to_request(self,*args): request = json.dumps(args,separators=(',',':')) request += '\n'; return request def _handle_response(self,response,request_id): if response is None: error_message = 'Did not receive server response.' raise IOError(error_message) try: response_dict = json_string_to_dict(response) except Exception as e: error_message = 'Unable to parse server response {0}.'.format(str(e)) raise IOError(error_message) try: id = response_dict.pop('id') except KeyError: error_message = 'Server response does not contain id member.' raise IOError(error_message) if not id == request_id: raise IOError('Response id does not match request id.') try: error = response_dict.pop('error') try: message = error.pop('message') except KeyError: message = '' try: data = error.pop('data') except KeyError: data = '' try: code = error.pop('code') except KeyError: code = '' error_message = '(from server) message: {0}, data: {1}, code: {2}'.format(message,data,code) raise IOError(error_message) except KeyError: pass try: result = response_dict.pop('result') except KeyError: error_message = 'Server response does not contain result member.' raise IOError(error_message) return result def _send_request_get_result(self,*args): ''' Sends request to server over serial port and returns response result ''' request = self._args_to_request(*args) self._debug_print('request', request) response = self._serial_interface.write_read(request,use_readline=True,check_write_freq=True) self._debug_print('response', response) if (type(response) != str): response = response.decode('utf-8') self._debug_print('type(response)', type(response)) result = self._handle_response(response,args[0]) return result def _get_method_dict(self): method_dict = self._send_request_get_result(self._METHOD_ID_GET_METHOD_IDS) return method_dict def _send_request_by_method_name(self,name,*args): method_id = self._method_dict[name] method_args = [method_id] method_args.extend(args) result = self._send_request_get_result(*method_args) return result def _method_func_base(self,method_name,*args): if len(args) == 1 and type(args[0]) is dict: args_dict = args[0] args_list = self._args_dict_to_list(args_dict) else: args_list = args result = self._send_request_by_method_name(method_name,*args_list) return result def _create_methods(self): self._method_func_dict = {} for method_id, method_name in sorted(self._method_dict_inv.items()): method_func = functools.partial(self._method_func_base, method_name) setattr(self,inflection.underscore(method_name),method_func) self._method_func_dict[method_name] = method_func def _args_dict_to_list(self,args_dict): key_set = set(args_dict.keys()) try: order_list = sorted([(num,name) for (name,num) in order_dict.items()]) except AttributeError: order_list = sorted([(num,name) for (name,num) in order_dict.iteritems()]) args_list = [args_dict[name] for (num, name) in order_list] return args_list def close(self): ''' Close the device serial port. ''' self._serial_interface.close() def get_port(self): return self._serial_interface.port def get_methods(self): ''' Get a list of modular methods automatically attached as class methods. ''' return [inflection.underscore(key) for key in list(self._method_dict.keys())] def call_get_result(self,method_name,*args): method_name = inflection.camelize(method_name,False) return self._send_request_get_result(method_name,*args) def call(self,method_name,*args): self.call_get_result(method_name,*args) def send_json_request(self,request): ''' Sends json request to device over serial port and returns result ''' request_python = json.loads(request) try: request_id = request_python["id"] except TypeError: pass except KeyError: error_message = 'Request does not contain an id.' raise IOError(error_message) try: request_python["method"] = inflection.camelize(request_python["method"],False) except TypeError: pass except KeyError: error_message = 'Request does not contain a method.' raise IOError(error_message) try: request_python[0] = inflection.camelize(request_python[0],False) request_id = request_python[0] except IndexError: error_message = 'Request does not contain a method.' raise IOError(error_message) request = json.dumps(request_python,separators=(',',':')) request += '\n' self._debug_print('request', request) response = self._serial_interface.write_read(request,use_readline=True,check_write_freq=True) self._debug_print('response', response) result = self._handle_response(response,request_id) return result def convert_to_json(self,python_to_convert,response_indent=None): ''' Convert python object to json string. ''' converted_json = json.dumps(python_to_convert,separators=(',',':'),indent=response_indent) return converted_json def save_device_id(self,output_directory): ''' Save device_id as a json file. ''' if output_directory is None: output_directory = os.path.join(os.path.curdir) elif len(os.path.splitext(output_directory)[1]) > 0: output_directory = os.path.dirname(output_directory) if not os.path.exists(output_directory): os.makedirs(output_directory) result = self.call_get_result('getDeviceId') output = {} output['id'] = 'getDeviceId' output['result'] = result output_path = os.path.join(output_directory,'device_id.json') with open(output_path,'w') as output_file: json.dump(output,output_file,separators=(',',':'),indent=2) try: os.removedirs(output_directory) except OSError: pass def save_device_info(self,output_directory): ''' Save device_info as a json file. ''' if output_directory is None: output_directory = os.path.join(os.path.curdir) elif len(os.path.splitext(output_directory)[1]) > 0: output_directory = os.path.dirname(output_directory) if not os.path.exists(output_directory): os.makedirs(output_directory) result = self.call_get_result('getDeviceInfo') output = {} output['id'] = 'getDeviceInfo' output['result'] = result output_path = os.path.join(output_directory,'device_info.json') with open(output_path,'w') as output_file: json.dump(output,output_file,separators=(',',':'),indent=2) try: os.removedirs(output_directory) except OSError: pass def save_api(self,output_directory,verbosity='DETAILED',firmware='ALL'): ''' Save api as a set of json files. ''' if output_directory is None: output_directory = os.path.join(os.path.curdir,'api') elif len(os.path.splitext(output_directory)[1]) > 0: output_directory = os.path.dirname(output_directory) if not os.path.exists(output_directory): os.makedirs(output_directory) device_info = self.call_get_result('getDeviceInfo') for firmware_info in device_info['firmware']: if (firmware == 'ALL') or (firmware == firmware_info['name']): result = self.call_get_result('getApi',verbosity,[firmware_info['name']]) api = {} api['id'] = 'getApi' api['result'] = result output_path = os.path.join(output_directory,firmware_info['name'] + '.json') with open(output_path,'w') as api_file: json.dump(api,api_file,separators=(',',':'),indent=2) try: os.removedirs(output_directory) except OSError: pass
def setUp(self): # Create instance self.serial_interface = SerialInterface("test") # Start self.serial_interface.start()
import wx import thread import time import Queue from Tkinter import Tk, Canvas, Frame, BOTH from serial_interface import SerialInterface ser = SerialInterface("/dev/ttyUSB0") packets = Queue.Queue() commands = Queue.Queue() root = Tk() # FE FE E0 94 27 00 00 02 11 # 3D 41 3E 39 40 47 4B 3D 32 3A 3E 34 31 40 3B 4D 4A 48 38 3A 43 52 4D 38 2C # 33 3D 3C 2E 24 40 33 25 11 31 3C 3E 3F 33 2D 48 5E 6D 5E 3B 27 41 3C 42 47 FD def task(): canvas.delete("all") root.after(1000, task) #print "frame" while (not packets.empty()): pkt = packets.get() print(' '.join("{:02X}".format(ord(i)) for i in pkt)) if (pkt[0:4] == "\xfe\xe0\x94\x27"): if pkt[6] != chr(0x01): a = pkt.split(chr(0x11))[1] values = [ord(i) for i in a]
class MettlerToledoDevice(object): ''' This module (mettler_toledo_quantos) creates a class named MettlerToledoDevice, to interface to Mettler Toledo Quantos using the Mettler Toledo Standard Interface Command Set for Quantos system (MT-SICS-Quantos). ''' _TIMEOUT = 0.05 _WRITE_WRITE_DELAY = 0.05 _RESET_DELAY = 2.0 def __init__(self,*args,**kwargs): if 'debug' in kwargs: self.debug = kwargs['debug'] else: kwargs.update({'debug': DEBUG}) self.debug = DEBUG if 'baudrate' not in kwargs: kwargs.update({'baudrate': BAUDRATE}) elif (kwargs['baudrate'] is None) or (str(kwargs['baudrate']).lower() == 'default'): kwargs.update({'baudrate': BAUDRATE}) if 'timeout' not in kwargs: kwargs.update({'timeout': self._TIMEOUT}) if 'write_write_delay' not in kwargs: kwargs.update({'write_write_delay': self._WRITE_WRITE_DELAY}) if ('port' not in kwargs) or (kwargs['port'] is None): err_string = 'Specify port.\n' raise RuntimeError(err_string) else: self.port = kwargs['port'] t_start = time.time() self._serial_device = SerialInterface(*args,**kwargs) atexit.register(self._exit_mettler_toledo_device) time.sleep(self._RESET_DELAY) t_end = time.time() self._debug_print('Initialization time =', (t_end - t_start)) def _debug_print(self, *args): if self.debug: print(*args) def _exit_mettler_toledo_device(self): pass def close(self): ''' Close the device serial port. ''' self._serial_device.close() def _args_to_request(self,*args): request = ''.join(map(str,args)) request = request + '\r\n';MettlerToledoError return request def _send_request_get_response(self,*args): '''Sends request to device over serial port and returns response''' request = self._args_to_request(*args) self._debug_print('request', request) response = self._serial_device.write_read(request,use_readline=True,check_write_freq=True) response = response.decode().replace('"','') response_list = response.split() if 'L' in response_list: raise MettlerToledoError('Syntax Error!') return response_list def move_frontdoor_open(self): ''' Opens the Quantos front door. ''' response = self._send_request_get_response('QRA 60 7 3') if 'I' in response[3]: if '1' in response[4]: raise MettlerToledoError('Not mounted.') elif '2'in response[4]: self._debug_print('Another job is running -- retrying.') self.move_frontdoor_open() #raise MettlerToledoError('Another job is running.') elif '3'in response[4]: raise MettlerToledoError('Timeout.') elif '4'in response[4]: raise MettlerToledoError('Not selected.') elif '5'in response[4]: raise MettlerToledoError('Not allowed at the moment') else: raise MettlerToledoError('Stopped by external action.') return response def move_frontdoor_close(self): ''' Close the Quantos front door. ''' #response = self._send_request_get_response('QRA 60 2 4') response = self._send_request_get_response('QRA 60 7 2') if 'I' in response[3]: if '1' in response[4]: raise MettlerToledoError('Not mounted.') elif '2'in response[4]: self._debug_print('Another job is running -- retrying.') self.move_frontdoor_close() #raise MettlerToledoError('Another job is running.') elif '3'in response[4]: raise MettlerToledoError('Timeout.') elif '4'in response[4]: raise MettlerToledoError('Not selected.') elif '5'in response[4]: raise MettlerToledoError('Not allowed at the moment.') else: raise MettlerToledoError('Stopped by external action.') return response def move_to(self,position): ''' Move Quantos sampler, taking the position as an argument. ''' response = self._send_request_get_response('QRA 60 8 ' + str(position)) return response def unlock_dosing_pin(self): ''' Unlock dosing pin, allowing removal of dosing head. ''' response = self._send_request_get_response('QRA 60 2 3') return response def lock_dosing_pin(self): ''' Lock dosing pin, readying dosing head for dispensing. ''' response = self._send_request_get_response('QRA 60 2 4') return response def set_target_value_mg(self, value): ''' Sets the target dosing value in mg. Value must be between 0.1 and 250000. Simple error handling incorporated. ''' if int(value) < 0.10: self._debug_print('The target value must be greater than 0.1 mg. -' 'Change the value and try again.') elif int(value) > 250000: self._debug_print('The target value must be less than 250,000 mg. -' 'Change the value and try again.') else: response = self._send_request_get_response('QRD 1 1 5 ' + str(value)) return response def set_tolerance_value_pct(self, value): ''' Sets the tolerance value as a percentage. Value must be between 0.1 and 40. Simple error handling incorporated. ''' if int(value) < 0.10: self._debug_print('The tolerance must be greater than 0.1% -' 'Change the value and try again.') elif int(value) > 40: self._debug_print('The tolerance must be less than 40% -' 'Change the value and try again.') else: response = self._send_request_get_response('QRD 1 1 6 ' + str(value)) return response def start_dosing(self): ''' Starts dosing. Uses previously set parameters including: target, tolerance and powder dosing algorithm ''' response = self._send_request_get_response('QRA 61 1') # Error handling if 'I' in response[3]: if '1' in response[4]: raise MettlerToledoError('Not mounted.') elif '2' in response[4]: self._debug_print('Another job is running -- retrying.') self.start_dosing() elif '3' in response[4]: raise MettlerToledoError('Timeout.') elif '4' in response[4]: raise MettlerToledoError('Not selected.') elif '5' in response[4]: raise MettlerToledoError('Not allowed at the moment.') elif '6' in response[4]: self._debug_print('Weight not stable - trying again in 5 seconds.') time.sleep(5) self.start_dosing() elif '7' in response[4]: raise MettlerToledoError('Powderflow error.') elif '8' in response[4]: raise MettlerToledoError('Stopped by external action.') elif '9' in response[4]: raise MettlerToledoError('Safe position error.') elif '10' in response[4]: raise MettlerToledoError('Head not allowed.') elif '11' in response[4]: raise MettlerToledoError('Head limit reached.') elif '12' in response[4]: raise MettlerToledoError('Head expiry date reached.') elif '13' in response[4]: raise MettlerToledoError('Sampler blocked.') return response def request_frontdoor_position(self): ''' Requests the position of the front door. ''' response = self._send_request_get_response('QRD 2 3 7') # return position as text if '2' in response[4]: return self._debug_print('Door is closed.') if '3' in response[4]: return self._debug_print('Door is opened.') if '8' in response[4]: return self._debug_print('Door is not detectable.') if '9' in response[4]: return self._debug_print('Running.') # Error handling if 'I' in response[4]: if '1' in response[5]: raise MettlerToledoError('Not mounted.') elif '2' in response[5]: self._debug_print('Another job is running - waiting 5 seconds and trying again.') time.sleep(5) self.request_frontdoor_position() elif '3' in response[5]: raise MettlerToledoError('Timeout.') elif '4' in response[5]: raise MettlerToledoError('Not selected.') elif '5' in response[5]: raise MettlerToledoError('Not allowed at the moment.') elif '8' in response[5]: raise MettlerToledoError('Stopped by external action.') return response def request_autosampler_position(self): ''' Requests the position of the autosampler. !!! This is currently not working - throwing up 'Syntax error', command is understood but not executable. !!! ''' response = self._send_request_get_response('QRD 2 3 8') # Return position as text if 'I' in response[4]: if '1' in response[5]: raise MettlerToledoError('Not mounted.') elif '2' in response[5]: self._debug_print('Another job is running - waiting 5 seconds and trying again.') time.sleep(5) self.request_frontdoor_position() elif '3' in response[5]: raise MettlerToledoError('Timeout.') elif '4' in response[5]: raise MettlerToledoError('Not selected.') elif '5' in response[5]: raise MettlerToledoError('Not allowed at the moment.') elif '8' in response[5]: raise MettlerToledoError('Stopped by external action.') else: return response def quantos_test(self): ''' Close the Quantos front door. ''' response = self._send_request_get_response('QRD 1 1 2 1') #response = self._send_request_get_response('QRA 60 2 3') ''' if 'I' in response[3]: if '1' in response[4]: raise MettlerToledoError('Not mounted.') elif '2'in response[4]: self._debug_print('Another job is running -- retrying.') self.move_frontdoor_close() #raise MettlerToledoError('Another job is running.') elif '3'in response[4]: raise MettlerToledoError('Timeout.') elif '4'in response[4]: raise MettlerToledoError('Not selected.') elif '5'in response[4]: raise MettlerToledoError('Not allowed at the moment.') else: raise MettlerToledoError('Stopped by external action.') ''' return response
class MainWindow(QtGui.QMainWindow): def __init__(self): QtGui.QMainWindow.__init__(self, None) uic.loadUi('mainwindow.ui', self) self.resize(700, 500) self.plotWindow = PlotWindow() self.stackedPlots.addWidget(self.plotWindow) self.stackedPlots.setCurrentIndex(0) self.actionRefresh.triggered[bool].connect(self.refreshList) self.actionConnect.triggered[bool].connect(self.connectFromList) self.actionDisconnect.triggered[bool].connect(self.disconnectFromCurrentDevice) self.actionLock.toggled[bool].connect(self.hold) self.actionViewAll.toggled[bool].connect(self.autoSet) self.actionExport.triggered[bool].connect(self.exportData) self.actionQuit.triggered[bool].connect(self.quitApp) self.actionAbout.triggered[bool].connect(self.aboutApp) self.listDevices.itemSelectionChanged.connect(self.deviceListChanged) self.actionViewAll.setChecked(True) self.autoSet(self.actionViewAll.isChecked()) self.ifaces = [] self.port = None self.baud = 115200 self.iface = None self.iface_thread = None self.initDeviceFinder() self.disableControls() self.deviceListChanged() self.statusBar().showMessage('Ready.') def deviceListChanged(self): if self.listDevices.count() > 0: self.actionConnect.setEnabled(True) self.enableControls() else: self.actionConnect.setEnabled(False) self.disableControls() def disableControls(self): self.plotWindow.setEnabled(False) self.actionDisconnect.setEnabled(False) self.actionLock.setEnabled(False) self.actionViewAll.setEnabled(False) self.actionExport.setEnabled(False) def enableControls(self): self.plotWindow.setEnabled(True) self.actionDisconnect.setEnabled(True) self.actionLock.setEnabled(True) self.actionViewAll.setEnabled(True) self.actionExport.setEnabled(True) def initDeviceFinder(self): self.device_finder = DeviceFinder() self.device_finder.foundDevice[str, SerialInterface].connect(self.gotNewDevice) self.device_finder.start() def gotNewDevice(self, port, iface): self.port = port self.listDevices.addItem(QtGui.QListWidgetItem(QtGui.QIcon('icons/device.png'), port)) self.ifaces.append(iface) self.statusBar().showMessage('Found %d device(s).' % self.listDevices.count()) def startSampling(self): self.iface_thread.start() def stopSampling(self): self.iface_thread.stop__() self.iface_thread.exit() def connectDevice(self): if not self.iface: self.iface = self.ifaces[self.listDevices.currentRow()] if self.iface: if not self.iface.isConnected(): self.iface = SerialInterface(self.port, self.baud) self.iface.connectToArduino() if not self.iface.serial_conn.isOpen(): self.iface.serial_conn.open() if self.iface.isConnected(): if self.iface_thread: del self.iface_thread self.iface_thread = SerialThread(self.iface) self.iface_thread.n_samples = 1000 self.iface_thread.gotSamples[tuple, int].connect(self.plotWindow.plotSamples) #self.iface_thread.deviceDisconnected.connect(self.disconnectFromCurrentDevice) self.startSampling() return True return False def refreshList(self): self.statusBar().showMessage('Searching...') for i in range(0, self.listDevices.count()): port = self.listDevices.item(i).text() self.device_finder.found.remove(port) self.listDevices.clear() self.ifaces = [] def connectFromList(self): self.actionConnect.setEnabled(False) self.actionDisconnect.setEnabled(True) self.actionRefresh.setEnabled(False) #self.connectDevice(self.listDevices.currentItem().text()) if self.connectDevice(): self.enableControls() else: QtGui.QMessageBox.critical(self, 'Error', 'Cannot connect to the device, refresh the list') def disconnectFromCurrentDevice(self): self.actionConnect.setEnabled(True) self.actionDisconnect.setEnabled(False) self.actionRefresh.setEnabled(True) self.disableControls() try: self.stopSampling() self.iface.disconnect() except: pass self.iface = None self.plotWindow.plot_item_a.clear() self.plotWindow.plot_item_p.clear() def exportData(self): self.plotWindow.scene().showExportDialog() def hold(self, checked): if checked: self.stopSampling() else: self.connectDevice() self.startSampling() def autoSet(self, checked): if checked: self.plotWindow.plot_item_a.enableAutoRange() self.plotWindow.plot_item_p.enableAutoRange() else: self.plotWindow.plot_item_a.disableAutoRange() self.plotWindow.plot_item_p.disableAutoRange() def quitApp(self): try: self.disconnectFromCurrentDevice() except: pass QtGui.QApplication.exit(0) def aboutApp(self): QtGui.QMessageBox.about(self, 'About', """<b>Spectrum Analyzer</b><br>Computer Peripherals Interface Project<br><b>By:</b><br>Sherif Adel Radwan<br>Mahmoud Sayed Zainhom<br>Abdelrahman Ghanem Abdelrady""") def closeEvent(self, event): if self.iface: self.iface.disconnect()
class Test(object): def setUp(self): # Create instance self.serial_interface = SerialInterface("test") # Start self.serial_interface.start() def tearDown(self): # Clear instance self.serial_interface.clear() def test_send_trigger_is_first_trigger_denied(self): """Check if first trigger is ignored""" time.sleep(1) ret_1, ret_2 = self.serial_interface.send_trigger(0) assert_false(ret_1) assert_equal(ret_2, 0) def test_send_trigger(self): """Check if trigger is sent to serial port""" # Wait for virtual serial port time.sleep(1) # Send trigger self.serial_interface.send_trigger(0) # Wait to trigger to be processed time.sleep(1) # Has the trigger been written to serial port? assert_equal(os.read(self.serial_interface.master, 1024), 'T\n') def test_run(self): """Check if thread functionality works correctly""" # Is thread running? assert_true(self.serial_interface.is_alive()) # Stop thread self.serial_interface.clear() # Wait for thread to shutdown time.sleep(1) # Is thread still running or has it shut down? assert_false(self.serial_interface.is_alive()) def test_clear(self): """Check if if connection to serial port is closed""" # Clear thread and close connection self.serial_interface.clear() assert_true(self.serial_interface.eventProgramEnd.is_set()) assert_false(self.serial_interface.serial_connection.isOpen())
from serial_interface import SerialInterface PORT_NAME = '/dev/panachrome' BAUD_RATE = 115200 # Set this variable to "threading", "eventlet" or "gevent" to test the # different async modes, or leave it set to None for the application to choose # the best option based on installed packages. async_mode = None app = Flask(__name__) app.config['SECRET_KEY'] = 'secret!' socketio = SocketIO(app, async_mode=async_mode) thread = None serial_port = SerialInterface() def serial_event(data): """ Data received form the serial port """ if data: socketio.emit('rx_data', {'data': data}, namespace='/test') def serial_listener(): """ Continuously poll the serial port, replies from the controller """
class BX305Driver(): def __init__(self, server_com_port, baudrate): # Setup serial interface. self._serial_interface = SerialInterface(server_com_port, baudrate, 50) self._serial_interface.set_read_callback(self._on_serial_read) # The byte parser analyses the byte string from the sensor # and divides it into individual sentences. self._byte_parser = ByteParser() self._current_sentence = bytearray() # If set, all raw data from serial port will be stored to this file. self._log_file = None # Locks #self._ack_lock = threading.Condition() self._wait_for_sentence_lock = threading.Condition() self._wait_for_sentence_type = None self._wait_for_sentence_data = None # Callbacks for NMEA sentences. self._GGA_cb = None self._RMC_cb = None self._GSV_cb = None self._GST_cb = None # Callbacks for ASCII sentences. self._BESTPOS_cb = None self._BESTVEL_cb = None self._TIME_cb = None self._PSRDOP_cb = None # Special callbacks. self._reset_cb = None # GSV information is sometimes split up into multiple sentences. # Need to gather all informations before calling callback. self._GSV_data = None # Total number of sentences until the GSV data we are currently # waiting for is complete self._received_GSV_sentences = 0 def __del__(self): self._driver.stop() # Open connection to sensor. If success, start gathering data. def connect(self): if(self._serial_interface.open_connection()): self._serial_interface.start() return True else: return False def disconnect(self): self._serial_interface.stop() self._serial_interface.close_connection() # Unlog all def unlogall(self): command = "unlogall\r\n" self._serial_interface.write_safe(command) # Reset/ Restart sensor def reset(self): command = "reset\r\n" self._serial_interface.write_safe(command) def saveconfig(self): command = "saveconfig\r\n" self._serial_interface.write_safe(command) # Repeatedly log def log_ontime(self, log_type, ontime, sensor_com = ""): # Clamp ontime ontime = max(0.05, min(ontime, 20)) command = "log " + sensor_com + " " + log_type + " ontime " + str(ontime) + "\r\n" self._serial_interface.write_safe(command) # TODO: wait for ACK #self._ack_lock.acquire() #self._ack_lock.wait(2) #self._ack_lock.release() # Log a single sentence once. Will wait for result def log_once(self, log_type, sensor_com = "" ): # Remember what we are waiting for, then clear old data #self._wait_for_sentence_type = log_type #self._wait_for_sentence_data = None # Send request command = "log " + sensor_com + " " + log_type + " once\r\n" self._serial_interface.write_safe(command) # Wait until result is available or 3 seconds have passed #self._wait_for_sentence_lock.acquire() #self._wait_for_sentence_lock.wait(3) #self._wait_for_sentence_lock.release() #return self._wait_for_sentence_data # Log whenever this sentence changed def log_onchanged(self, log_type , sensor_com = ""): command = "log " + sensor_com + " " + log_type + " onchanged\r\n" self._serial_interface.write_safe(command) # Callback setters for NMEA sentences def set_GGA_callback(self, GGA_callback): self._GGA_cb = GGA_callback def set_RMC_callback(self, RMC_callback): self._RMC_cb = RMC_callback def set_GSV_callback(self, GSV_callback): self._GSV_cb = GSV_callback def set_GST_callback(self, GST_callback): self._GST_cb = GST_callback # Callback setters for ASCII sentences def set_BESTPOS_callback(self, BESTPOS_callback): self._BESTPOS_cb = BESTPOS_callback def set_BESTVEL_callback(self, BESTVEL_callback): self._BESTVEL_cb = BESTVEL_callback def set_TIME_callback(self, TIME_callback): self._TIME_cb = TIME_callback def set_PSRDOP_callback(self, PSRDOP_callback): self._PSRDOP_cb = PSRDOP_callback # Callback setters for special callbacks def set_reset_done_callback(self, reset_done_callback): self._reset_cb = reset_done_callback def _restart_byte_parser(self): self._byte_parser.restart() self._current_sentence = bytearray() def _on_serial_read(self, data): for b in data: #print(chr(b)) # Update state machine self._byte_parser.update_state(b) self._current_sentence.append(b) if(self._byte_parser.parsing_done()): if (self._byte_parser.get_state() == ReadState.SUCCESS_BINARY): self._on_new_binary_data(self._current_sentence) self._restart_byte_parser() elif (self._byte_parser.get_state() == ReadState.SUCCESS_ASCII): self._on_new_ascii_data(self._current_sentence) self._restart_byte_parser() elif (self._byte_parser.get_state() == ReadState.SUCCESS_ACK): self._on_ack() self._restart_byte_parser() elif (self._byte_parser.get_state() == ReadState.ERROR): #print("ERROR parsing") #print(chr(b)) self._restart_byte_parser() elif (self._byte_parser.get_state() == ReadState.SUCCESS_RESET): self._on_reset() self._restart_byte_parser() # Save to log file, if enabled if(self._log_file is not None): self._log_file.write(data) def _on_new_ascii_data(self, data): if(parser.is_nmea_sentence(data)): self._handle_nmea_sentence(data) elif(parser.is_ascii_sentence(data)): self._handle_ascii_sentence(data) def _handle_nmea_sentence(self, sentence): nmea_type = parser.get_nmea_sentence_type(sentence) if(nmea_type == "GGA" and self._GGA_cb is not None): self._GGA_cb(parser.extract_GGA_data(sentence)) if(nmea_type == "RMC" and self._RMC_cb is not None): self._RMC_cb(parser.extract_RMC_data(sentence)) if(nmea_type == "GST" and self._GST_cb is not None): self._GST_cb(parser.extract_GST_data(sentence)) # GSV is a special case: Data is split up in multiple sentences. Need to wait until all # data is available, before calling callback function. if(nmea_type == "GSV" and self._GSV_cb is not None): data = parser.extract_GSV_data(sentence) total_msg = data.pop('num_total_msgs') this_msg = data.pop('msg_number') if(self._GSV_data is None): # Data consists of only one sentence. Call callback directly. if (total_msg == this_msg): self._GSV_cb(data) # Multiple sentences. Save this data to complete it later. else: self._GSV_data = data else: self._GSV_data['sat_infos'].extend(data['sat_infos']) if (total_msg == this_msg): self._GSV_cb(self._GSV_data) self._GSV_data = None def _handle_ascii_sentence(self, sentence): ascii_type = parser.get_ascii_sentence_type(sentence) if(ascii_type == "BESTPOSA" and self._BESTPOS_cb is not None): result = parser.extract_bestpos_data(sentence) if(result): self._BESTPOS_cb(result) if(ascii_type == "BESTVELA" and self._BESTVEL_cb is not None): self._BESTVEL_cb(parser.extract_bestvel_data(sentence)) if(ascii_type == "TIMEA" and self._TIME_cb is not None): self._TIME_cb(parser.extract_time_data(sentence)) if(ascii_type == "PSRDOPA" and self._PSRDOP_cb is not None): self._PSRDOP_cb(parser.extract_psrdop_data(sentence)) def _on_new_binary_data(self, data): if(self._binaryFile is not None): self._binaryFile.write(data) def _on_ack(self): #print("ACK arrived") #self._ack_lock.acquire() #self._ack_lock.notify() #self._ack_lock.release() pass def _on_reset(self): print("RESET received") if(self._reset_cb is not None): self._reset_cb() # Log to file def enable_file_log(self, filepath): try: self._log_file = open(filepath, 'w') except IOError as e: self._log_file = None print("Error opening record file.") # Disable log to file def disable_file_log(self): if(self._log_file is not None): self._log_file.close() self._log_file = None
class MainWindow(QtGui.QMainWindow): def __init__(self): QtGui.QMainWindow.__init__(self, None) uic.loadUi('mainwindow.ui', self) self.resize(700, 500) self.plotWindow = PlotWindow() self.stackedPlots.addWidget(self.plotWindow) self.stackedPlots.setCurrentIndex(0) self.actionRefresh.triggered[bool].connect(self.refreshList) self.actionConnect.triggered[bool].connect(self.connectFromList) self.actionDisconnect.triggered[bool].connect( self.disconnectFromCurrentDevice) self.actionLock.toggled[bool].connect(self.hold) self.actionViewAll.toggled[bool].connect(self.autoSet) self.actionExport.triggered[bool].connect(self.exportData) self.actionQuit.triggered[bool].connect(self.quitApp) self.actionAbout.triggered[bool].connect(self.aboutApp) self.listDevices.itemSelectionChanged.connect(self.deviceListChanged) self.actionViewAll.setChecked(True) self.autoSet(self.actionViewAll.isChecked()) self.ifaces = [] self.port = None self.baud = 115200 self.iface = None self.iface_thread = None self.initDeviceFinder() self.disableControls() self.deviceListChanged() self.statusBar().showMessage('Ready.') def deviceListChanged(self): if self.listDevices.count() > 0: self.actionConnect.setEnabled(True) self.enableControls() else: self.actionConnect.setEnabled(False) self.disableControls() def disableControls(self): self.plotWindow.setEnabled(False) self.actionDisconnect.setEnabled(False) self.actionLock.setEnabled(False) self.actionViewAll.setEnabled(False) self.actionExport.setEnabled(False) def enableControls(self): self.plotWindow.setEnabled(True) self.actionDisconnect.setEnabled(True) self.actionLock.setEnabled(True) self.actionViewAll.setEnabled(True) self.actionExport.setEnabled(True) def initDeviceFinder(self): self.device_finder = DeviceFinder() self.device_finder.foundDevice[str, SerialInterface].connect( self.gotNewDevice) self.device_finder.start() def gotNewDevice(self, port, iface): self.port = port self.listDevices.addItem( QtGui.QListWidgetItem(QtGui.QIcon('icons/device.png'), port)) self.ifaces.append(iface) self.statusBar().showMessage('Found %d device(s).' % self.listDevices.count()) def startSampling(self): self.iface_thread.start() def stopSampling(self): self.iface_thread.stop__() self.iface_thread.exit() def connectDevice(self): if not self.iface: self.iface = self.ifaces[self.listDevices.currentRow()] if self.iface: if not self.iface.isConnected(): self.iface = SerialInterface(self.port, self.baud) self.iface.connectToArduino() if not self.iface.serial_conn.isOpen(): self.iface.serial_conn.open() if self.iface.isConnected(): if self.iface_thread: del self.iface_thread self.iface_thread = SerialThread(self.iface) self.iface_thread.n_samples = 1000 self.iface_thread.gotSamples[tuple, int].connect( self.plotWindow.plotSamples) #self.iface_thread.deviceDisconnected.connect(self.disconnectFromCurrentDevice) self.startSampling() return True return False def refreshList(self): self.statusBar().showMessage('Searching...') for i in range(0, self.listDevices.count()): port = self.listDevices.item(i).text() self.device_finder.found.remove(port) self.listDevices.clear() self.ifaces = [] def connectFromList(self): self.actionConnect.setEnabled(False) self.actionDisconnect.setEnabled(True) self.actionRefresh.setEnabled(False) #self.connectDevice(self.listDevices.currentItem().text()) if self.connectDevice(): self.enableControls() else: QtGui.QMessageBox.critical( self, 'Error', 'Cannot connect to the device, refresh the list') def disconnectFromCurrentDevice(self): self.actionConnect.setEnabled(True) self.actionDisconnect.setEnabled(False) self.actionRefresh.setEnabled(True) self.disableControls() try: self.stopSampling() self.iface.disconnect() except: pass self.iface = None self.plotWindow.plot_item_a.clear() self.plotWindow.plot_item_p.clear() def exportData(self): self.plotWindow.scene().showExportDialog() def hold(self, checked): if checked: self.stopSampling() else: self.connectDevice() self.startSampling() def autoSet(self, checked): if checked: self.plotWindow.plot_item_a.enableAutoRange() self.plotWindow.plot_item_p.enableAutoRange() else: self.plotWindow.plot_item_a.disableAutoRange() self.plotWindow.plot_item_p.disableAutoRange() def quitApp(self): try: self.disconnectFromCurrentDevice() except: pass QtGui.QApplication.exit(0) def aboutApp(self): QtGui.QMessageBox.about( self, 'About', """<b>Spectrum Analyzer</b><br>Computer Peripherals Interface Project<br><b>By:</b><br>Sherif Adel Radwan<br>Mahmoud Sayed Zainhom<br>Abdelrahman Ghanem Abdelrady""" ) def closeEvent(self, event): if self.iface: self.iface.disconnect()
import serial import socketio import struct import eventlet from serial_interface import SerialInterface # If no params reply with G # TIME OUT SET TO NONE SO when reading, will only read once done. ser = serial.Serial('/dev/ttyACM0', 9600, timeout=None) sio = socketio.Server() app = socketio.WSGIApp(sio) thread = None PORT = 5000 serial_interface = SerialInterface(ser, sio) @sio.on('connect') def connect(sid, message): global thread global serial_interface print('connected') if thread == None: thread = sio.start_background_task(target=serial_interface.background_process) def set_params_to_send(sid, params): parameter_names = [ "mode", "fiO2", "peep", "inspiratoryPressure",
import sys import error #sds python libraries sys.path.append('..\libraries') from logger import _print, _print_bytes, APP, ERROR, WARNING, DEBUG from serial_interface import SerialInterface SERIAL_PREAMBLE = b'\xee' SERIAL_TRAILER = b'\x0a\x0d' g_serial = SerialInterface() class SerialPacket: """ Serial Packet Structure: Serial Preamble Notification Length Notification Data Trailer """ def __init__(self): self.bytes = None def set(self, _bytes): #calculate length of remaining bytes length = len(_bytes) length_hex = length.to_bytes(1, byteorder='little')