def __init__(self, parent=None): super(PyClockSetup, self).__init__() self.serial = QSerialPort(self) uic.loadUi('pyclocksetup.ui', self) self.show() self.timer = QtCore.QTimer() self.timer.timeout.connect(self.updateTime) self.timer.start(1000) self.serial = QSerialPort(self) self.cp.colorChanged.connect(self.changeColor) self.connectButton.clicked.connect(self.serialConnect) self.setClockButton.clicked.connect(self.setClock) self.blinkingDots.toggled.connect(self.setBlinkingDots) self.leadingZero.toggled.connect(self.setLeadingZero) self.autoBrightness.toggled.connect(self.setAutoBrightness) self.segmentTest.toggled.connect(self.setSegmentTest) self.brightnessSlider.valueChanged.connect(self.changeBrightness) self.colorLabel.setStyleSheet('QLabel {background-color: #ffffff; }') availablePorts = QSerialPortInfo.availablePorts() for port in availablePorts: self.serialPorts.addItem(port.portName())
def CreateItems(self): # Qt 串口类 self.com = QSerialPort() # Qt 定时器类 self.timer = QTimer(self) #初始化一个定时器 self.timer.timeout.connect(self.ShowTime) #计时结束调用operate()方法 self.timer.start(100) #设置计时间隔 100ms 并启动
def __init__(self, *args, **kwds): super(Com_port, self).__init__(kwds.pop('parent')) self.ser = QSerialPort(kwds.pop('port')) self.ser.open(QIODevice.ReadWrite) self.ser.setBaudRate(kwds.pop('baudrate')) self.ser.readyRead.connect(self.on_serial_read) print("Com port " + self.ser.portName() + ' ready.')
class Weigher(): def __init__(self, port_name=None, baud_rate=None, data_bits=None, stop_bits=None): # Read config config = read_config()[port_name] self.port_name = config['port_name'] self.baud_rate = config['baud_rate'] self.data_bits = config['data_bits'] self.stop_bits = config['stop_bits'] # Initial self.weigher = QSerialPort() # It is the subclass of the QIODevice class; self.weigher.setPortName(self.port_name) # passing name such as 'COM1' self.weigher.setBaudRate(int(self.baud_rate)) self.weigher.setDataBits(QSerialPort.DataBits(int(self.data_bits))) self.weigher.setStopBits(QSerialPort.StopBits(int(self.stop_bits))) # Logging module self.mylogging = MyLogging(logger_name='user') self.mylogger = self.mylogging.logger def read(self): if self.weigher.canReadLine(): ascii_data = self.weigher.readLine() data = ascii_data.decode('ascii') try: # The formate of weigher returns datas. weigher_data = float(data[1:-4]) * 1000 return weigher_data except BaseException as e: self.mylogger.error(e)
def __init__(self): super(MainWindow, self).__init__() self.ui = Ui_MainWindow() self.ui.setupUi(self) self.serial = QSerialPort(self) self.timer = QtCore.QElapsedTimer() self.graphInit() self.getAvaliablePorts() self.ui.pushButton_Get.clicked.connect(self.getOnce_slot) self.ui.pushButton_Start.clicked.connect(self.start_slot) self.ui.pushButton_Stop.clicked.connect(self.stop_slot) self.serial.readyRead.connect(self.serialRead_slot) self.data_isReady_signal.connect(self.plotUpdate) self.get_data_signal.connect(self.getOnce_slot) average = [] for i in range(1, 10): average.append(str(i)) for average_ in average: entry = QAction(average_, self) self.ui.menuAverage.addAction(entry) entry.triggered.connect(lambda Val, average_to_set=average_: self. average_set(average_to_set))
def slot_connect(self): self.serialport_name = self.qcb_ports.currentText() self.serialport = QSerialPort() self.serialport.setPortName(self.serialport_name) self.serialport.setBaudRate( self.baudrates[self.qcb_baudrates.currentText()]) self.serialport.setDataBits( self.databits[self.qcb_databits.currentText()]) self.serialport.setParity( self.paritybit[self.qcb_paritybit.currentText()]) self.serialport.setStopBits( self.stopbits[self.qcb_stopbits.currentText()]) self.serialport.setFlowControl(QSerialPort.NoFlowControl) # self.serialport.close() self.serialport.open(QIODevice.ReadWrite) if self.serialport.isOpen(): self.serialport.readyRead.connect(self.ready_read) self.qpb_connect_disconnect.setText("Disconnect") self.qpb_connect_disconnect.disconnect() self.qpb_connect_disconnect.clicked.connect(self.slot_disconnect) if self.fl_log: self.logfile = open(self.logfile_location, 'w') self.qcb_ports.setDisabled(True) self.qcb_baudrates.setDisabled(True) self.qcb_databits.setDisabled(True) self.qcb_paritybit.setDisabled(True) self.qcb_stopbits.setDisabled(True) self.qcb_flowcontrol.setDisabled(True) self.qpb_refresh.setDisabled(True) self.qpb_load_session.setDisabled(True)
def setupSerialPort(self): """ Процедура установки различных параметров для ком-порта """ self.serial = QSerialPort() self.serial.readyRead.connect(self.onDataRecv) try: settings = cfg.read() except Exception as e: msg = QMessageBox(self) msg.setIcon(QMessageBox.Critical) msg.setText("Ошибка при чтении настроек ком-порта") msg.setInformativeText(str(e)) msg.setWindowTitle("Ошибка") msg.setDetailedText(traceback.format_exc()) msg.exec_() return if len(cfg.VALID_VALUES['port']) == 0: self.setSerialStatus("COM-порты не найдены", False) return elif settings['port'] not in cfg.VALID_VALUES['port']: dialog = SerialPortConfigDialog(self) dialog.exec_() if dialog.okClicked: settings = dialog.settings else: self.setSerialStatus("COM-порт не настроен", False) return self.setSerialSettings(settings) self.startSerial()
def init(self): self.serianame = '' self.com = QSerialPort() self.cominfo = QSerialPortInfo() self.infos = self.cominfo.availablePorts() for info in self.infos: print("Name:", info.portName()) print("vendoridentifier:", info.vendorIdentifier()) # 串口信息认证 if info.vendorIdentifier() == 6790: self.serianame = info.portName() self.com.setPortName(self.serianame) self.com.setBaudRate(9600) # 打开串口 if self.com.open(QSerialPort.ReadWrite) == False: print("open fault") return # 设置定时函数 self.readtimer = QTimer() self.readtimer.timeout.connect(self.readData) # 读信号 self.readtimer.start(200) # 每200ms读一次数据
def __init__(self): super(SerialProtoParser, self).__init__() # Serial port self.__serialPort = QSerialPort() # Setup Serialport # We are using USB serial driver, so the baud rate doesn't matter self.__serialPort.setBaudRate(QSerialPort.Baud115200, QSerialPort.Input) self.destroyed.connect(self.close) # Get the list of all available serial ports portsList = QSerialPortInfo.availablePorts() # Only connect to Chibios port chibiOsPort = None for port in portsList: if ("ChibiOS" in port.description()): chibiOsPort = port if (chibiOsPort is None): print("Cannot find chibios based device") else: # Set the serial port self.__serialPort.setPort(chibiOsPort) self.__serialPort.setDataBits(QSerialPort.Data8) self.__serialPort.setFlowControl(QSerialPort.NoFlowControl) self.__serialPort.setParity(QSerialPort.NoParity) self.__serialPort.setStopBits(QSerialPort.OneStop) # Connect signals and slots self.__serialPort.readyRead.connect(self.__onSerialPortReadyRead) # Open the device self.__serialPort.open(QIODevice.ReadOnly)
def __init__(self, *args, **kwargs): super(Window, self).__init__(*args, **kwargs) self.setupUi(self) self._serial = QSerialPort(self) # 用于连接串口的对象 self._serial.readyRead.connect(self.onReadyRead) # 绑定数据读取信号 # 首先获取可用的串口列表 self.getAvailablePorts()
def connectSerial(self, port): #try: self.active_port = QSerialPort(port, baudRate=QSerialPort.Baud9600, readyRead=self.receive) if not self.active_port.isOpen( ): #Close serial port if it is already open if self.active_port.open( QtCore.QIODevice.ReadWrite): #Open serial connection self.active_port.readyRead.connect(self.receive) self.active_port.clear() #Clear buffer of any remaining data self.gui.status_dict["COM Port"] = self.getPortInfo( self.active_port)["Port"] return True else: if debug: print("Can't open port1") else: if debug: print("Can't open port2") #except: #Return False if unable to establish connection to serial port if debug: print("Failed to connect to COM port, with QSerialPort Error #" + str(self.active_port.error())) self.disconnectSerial() return False
def __init__(self, parent=None): super().__init__(parent) self.__data = QByteArray() self.__serial = QSerialPort() self.__timer = QTimer(self) for info in QSerialPortInfo.availablePorts(): if info.description() == "USB-SERIAL CH340": self.__serial = QSerialPort(info) print(self.__serial.portName()) break self.__serial.readyRead.connect(self.__read_data) self.__timer.timeout.connect(self.__timer_update_com) self.__temperature = 0 self.__humidity = 0 self.__co2 = 0 self.__tvoc = 0 self.__pm25 = 0 self.__pm10 = 0 self.__o2 = 0 if self.__serial.open(QIODevice.ReadWrite): print("open success") else: print("open fail") self.__auto_save_thread = AutoSave(self) self.__auto_save_thread.start()
def __init__(self): super(SerialPort, self).__init__() self.ports = [] self.serialData = '' self.commands = { 'CurveTemporal': '|', 'GainOffset': ':', 'Laser': '#', 'TimeAverage': '&', 'StopTemporal': '[', 'StopTechnical': '.', 'ControlPeris': '*', 'ControlImpulA': '!', 'ControlImpulB': '+', 'BackPeris': '<', 'StopPeris': '=', 'ForwardPeris': '>', 'TimePulsesPumps': '_', 'VolumePurge': 'a7', 'PurgeImpulA': '{', 'PurgeImpulB': '}', 'IAmAlive': '?', 'PowerDown': '/' } self.serialPort = QSerialPort()
def __init__(self): super().__init__() self.logger = logging.getLogger('controlpanel') l = QVBoxLayout(self) b = QPushButton("Gas") b.clicked.connect(self.do_go) l.addWidget(b) b2 = QPushButton("Bremsen") b2.clicked.connect(self.do_stop) l.addWidget(b2) self.motor_panel = MotorDataPanel() self.info_panel = InfoDataPanel() l.addWidget(self.info_panel) l.addWidget(self.motor_panel) self.protocol = Protocol() self.protocol.process_msg = self.process_msg self.msg_cntr = 0 # Construct port: self.port = QSerialPort(self) self.port.readyRead.connect(self.do_read_bytes) self.logger.debug('Created class') # open port: self.do_open() self.do_go()
def __init__(self, context, parent=None): super().__init__(parent) self.win = parent self.ctx = context self.cmbPort = self.win.findChild(QObject, 'cmbPort') self.cmbBaud = self.win.findChild(QObject, 'cmbBaud') self.cmbData = self.win.findChild(QObject, 'cmbData') self.cmbChek = self.win.findChild(QObject, 'cmbParity') self.cmbStop = self.win.findChild(QObject, 'cmbStop') self.txtMain = self.win.findChild(QObject, 'txtMain') self.txtSend = self.win.findChild(QObject, 'txtSend') self.btnOpen = self.win.findChild(QObject, 'btnOpen') self.btnSend = self.win.findChild(QObject, 'btnSend') self.chkHexShow = self.win.findChild(QObject, 'chkHexShow') self.chkWavShow = self.win.findChild(QObject, 'chkWavShow') self.chkHexSend = self.win.findChild(QObject, 'chkHexSend') self.chkTimSend = self.win.findChild(QObject, 'chkTimSend') self.chkExtTran = self.win.findChild(QObject, 'chkExtTran') self.initSetting() self.ser = QSerialPort(self) self.ser.readyRead.connect(self.on_ser_dataAvailable)
def __init__(self, port, theme='day', parent=None): super().__init__(parent) self.setFont(Font().load()) self.setAcceptRichText(False) self.setReadOnly(False) self.setUndoRedoEnabled(False) self.setContextMenuPolicy(Qt.CustomContextMenu) self.customContextMenuRequested.connect(self.context_menu) self.setObjectName('replpane') # open the serial port self.serial = QSerialPort(self) self.serial.setPortName(port) if self.serial.open(QIODevice.ReadWrite): self.serial.dataTerminalReady = True if not self.serial.isDataTerminalReady(): # Using pyserial as a 'hack' to open the port and set DTR # as QtSerial does not seem to work on some Windows :( # See issues #281 and #302 for details. self.serial.close() pyser = serial.Serial(port) # open serial port w/pyserial pyser.dtr = True pyser.close() self.serial.open(QIODevice.ReadWrite) self.serial.setBaudRate(115200) self.serial.readyRead.connect(self.on_serial_read) # clear the text self.clear() # Send a Control-C self.serial.write(b'\x03') else: raise IOError("Cannot connect to device on port {}".format(port)) self.set_theme(theme)
def __init__(self, port, baudrate=115200): super().__init__() self.serial = QSerialPort() self._port = port self._baudrate = baudrate self.serial.setPortName(port) self.serial.setBaudRate(baudrate)
def begin(self): """SLOT: begin Launches the serial read/write signal loop Expects: none Connects to: QThread.started """ path = glob.glob("/dev/tty.usbserial-*") self.serialPort = None try: path = path[0] except IndexError: self.displayRXMessage.emit("No serial connected") self.ready.emit() else: self.serialPort = QSerialPort(path) self.serialPort.setBaudRate(9600) self.buffer = bytearray() self.serialPort.readyRead.connect(self.readData) self.close.connect(self.serialPort.close) self.serialPort.open(QIODevice.ReadWrite) finally: self.lock = QMutex() self.broadcast.connect(self.writeData)
def __init__(self, baudRate, parent=None): super(self.__class__, self).__init__(parent) self.pollingTimer = QTimer() self.pollingTimer.timeout.connect(self.poll) self.ser = QSerialPort() self.ser.setBaudRate(baudRate) self.hasLogFile = False self.logFileName = ''
def get_ip(self): self.port = QSerialPort(self.cbxPort.currentData()) self.port.setBaudRate(115200) DeviceIP(self.port).exec_() if self.port.isOpen(): self.port.close()
def __init__(self): super(MainUi, self).__init__() uic.loadUi(res_path('MainWindow.ui'), self) self.serial = QSerialPort(self) self.timer = QTimer(self) self.timer.timeout.connect(self.updateTimer) self.setup() self.lastSerial = None
def __init__(self, *args, **kwargs): super(QtCore.QObject, self).__init__(*args, **kwargs) self.serial = QSerialPort() port = "COM14" self.serial.setPortName(port) if self.serial.open(QtCore.QIODevice.ReadWrite): self.serial.setDataTerminalReady(True) self.serial.setBaudRate(4800) self.serial.readyRead.connect(self.on_serial_read)
def portOpen(self): self.serial = QSerialPort() self.serial.setPortName(self.portNameBox.currentText()) self.serial.open(QIODevice.ReadWrite) self.serial.setBaudRate(int(self.baudRateBox.currentText())) self.serial.setDataBits(QSerialPort.Data8) self.serial.setParity(QSerialPort.NoParity) self.serial.setFlowControl(QSerialPort.NoFlowControl) self.serial.setStopBits(QSerialPort.OneStop) self.portGroupBox.setEnabled(False)
def __init__(self): super(SerialWidget, self).__init__() self.com = QSerialPort() self.sendCnt = 0 self.recvCnt = 0 self.serialStatus = False self.initUI() self.detectSerialStatus() self.signalSlot()
def __init__(self): super(RPMPlotter, self).__init__() # Setupui self.setupUi(self) # Create a serial port self.__serialPort = QSerialPort() # Setup Serialport # We are using USB serial driver, so the baud rate doesn't matter self.__serialPort.setBaudRate(QSerialPort.Baud115200, QSerialPort.Input) # Get the list of all available serial ports portsList = QSerialPortInfo.availablePorts() # Only connect to Chibios port chibiOsPort = None self.setWindowTitle("Experiment Data Collector") for port in portsList: if ("ChibiOS" in port.description()): chibiOsPort = port print(chibiOsPort.description()) # Check of the device is connected. if (chibiOsPort is None): # We didn't find anything statusString = "Cannot find Chibios based device." print(statusString) else: # Set the serial port self.__serialPort.setPort(chibiOsPort) self.__serialPort.setDataBits(QSerialPort.Data8) self.__serialPort.setFlowControl(QSerialPort.NoFlowControl) self.__serialPort.setParity(QSerialPort.NoParity) self.__serialPort.setStopBits(QSerialPort.OneStop) # Connect signals and slots self.__serialPort.readyRead.connect(self.__onSerialPortReadyRead) self.startButton.clicked.connect(self.onStartButtonClicked) self.lineEdit.returnPressed.connect(self.onReferenceValueChanged) # Open the device self.__serialPort.open(QIODevice.ReadWrite) # Initialize variables # We track the reference and draw it as a line. self.__referenceArray = [] # Timestamp in seconds self.__timeStampArray = [] # RPM value self.__rpmArray = [] # Voltage provided to the motor self.__voltageValue = [] ## Curves self.__rpmCurve = pg.PlotCurveItem() self.__rpmCurve.setPen(pg.mkPen(color=(3, 39, 28), width=1.2)) self.__referenceCurve = pg.PlotCurveItem() self.__referenceCurve.setPen( pg.mkPen(color=(214, 118, 17), width=1.2, style=Qt.DashDotLine)) self.graphicsView.addItem(self.__rpmCurve) self.graphicsView.addItem(self.__referenceCurve)
def run(self): serial = QSerialPort() serial.setPortName(self.portName) if not serial.open(QIODevice.ReadOnly): self.logger.error("can't open serial port") return while not self.quit: if serial.waitForReadyRead(self.waitTimeout): bytes = serial.readAll() while serial.waitForReadyRead(10): bytes += serial.readAll() tag = self.decode_gwiot(bytes) now = calendar.timegm(time.gmtime()) self.logger.debug("tag=%d, now=%d" % (tag, now)) if tag > 0: self.tagScan.emit(tag, self.hash_tag(tag), now, self.dump_pkt(bytes)) else: self.tagScanError.emit(tag, now, self.dump_pkt(bytes))
def initSerial(self, str_com): self.data_zigbee_list = [] # 初始化串口 self.ser_data = QSerialPort(STR_COM, baudRate=QSerialPort.Baud115200, readyRead=self.receive) self.ser_data.open(QIODevice.ReadWrite) if self.ser_data.isOpen(): print('串口开启成功!') else: print('串口打开失败……')
def __init__(self): super().__init__() self.com = QSerialPort() self.Layout() self.CreateSignalSolt() self.RefreshCom() self.encoding = 'utf-8' self.recvCount = 0 self.sendCount = 0
def __init__(self, parent=None): super(Serial, self).__init__(parent) self.setupUi(self) self.setWindowTitle("串口助手<V1.0> by-FXC") # 设置标题 self._num_send = 0 # 发送数据量 self._num_receive = 0 # 接收数据量 self._serial = QSerialPort(self) # 用于连接串口的对象 self._single_slot() # 连接信号与槽 self.get_available_ports() # 获取可用的串口列表 self.set_statusbar() # 设置状态栏 self.plainTextEdit_send.setPlainText("hello world!")
def __init__(self, *args, **kwargs): super(QtCore.QObject, self).__init__(*args, **kwargs) self.serial = QSerialPort() port = "/dev/ttyUSB0" self.serial.setPortName(port) if self.serial.open(QtCore.QIODevice.ReadWrite): self.serial.setDataTerminalReady(True) self.serial.setBaudRate(115200) self.serial.readyRead.connect(self.on_serial_read) else: print("Failed to open serial port")
def __init__(self, port, parent=None): super().__init__(parent) self.setAcceptRichText(False) self.setReadOnly(False) self.setLineWrapMode(QTextEdit.NoWrap) self.setObjectName('replpane') # open the serial port self.serial = QSerialPort(self) self.serial.setPortName(port) self.serial.setBaudRate(115200) print(self.serial.open(QIODevice.ReadWrite)) self.serial.readyRead.connect(self.on_serial_read) # clear the text self.clear()
def __init__(self, port, parent=None): super().__init__(parent) self.setAcceptRichText(False) self.setReadOnly(False) self.setLineWrapMode(QTextEdit.NoWrap) self.setObjectName('replpane') # open the serial port self.serial = QSerialPort(self) self.serial.setPortName(port) self.serial.setBaudRate(115200) if self.serial.open(QIODevice.ReadWrite): self.serial.readyRead.connect(self.on_serial_read) # clear the text self.clear() # Send a Control-C self.serial.write(b'\x03') else: raise IOError("Cannot connect to device on port {}".format(port))
def __init__(self, port, parent=None): super().__init__(parent) self.setAcceptRichText(False) self.setReadOnly(False) self.setLineWrapMode(QTextEdit.NoWrap) self.setObjectName("replpane") # A flag to indicate that we've sent some sort of escape # character e.g. \b self.escape_flag = False # open the serial port self.serial = QSerialPort(self) self.serial.setPortName(port) self.serial.setBaudRate(115200) print(self.serial.open(QIODevice.ReadWrite)) self.serial.readyRead.connect(self.on_serial_read) # clear the text self.clear()
def __init__(self, parent = None): super(SerialSimulate, self).__init__(parent) self.setObjectName('SerialSimulate') # self._currIndex = 0 self._currFrameId = 0 self._frameSize = 0 self._streamBuff = [] self._newBuff = [0] * 4096 self._pkgBuff = [0] * 100 self._serialSend = SerialSend() self._serialRecv = SerialRecv() self._serialConfig = SerialPortConfig() self._serialPort = QSerialPort(self) # self._serialPort.error.connect(self.onSerialPortError) self._serialPort.readyRead.connect(self.readData) # self._serialPort.setPortName('COM5') if self._serialPort.open(QIODevice.ReadWrite): self._serialPort.setBaudRate(QSerialPort.Baud115200) self._serialPort.setDataBits(QSerialPort.Data8) self._serialPort.setParity(QSerialPort.OddParity) self._serialPort.setStopBits(QSerialPort.OneStop) self.stateChanged.emit('Open') # self._serialRecv.lMBrakeP = SerialPortProxy.swapUint16(0) self._serialRecv.rMBrakeP = SerialPortProxy.swapUint16(0) self._serialRecv.lABrakeP = SerialPortProxy.swapUint16(5) self._serialRecv.rABrakeP = SerialPortProxy.swapUint16(5) self._serialRecv.lMRotateP = SerialPortProxy.swapUint16(0) self._serialRecv.rMRotateP = SerialPortProxy.swapUint16(0) self._serialRecv.lARotateP = SerialPortProxy.swapUint16(5) self._serialRecv.rARotateP = SerialPortProxy.swapUint16(5) self._serialRecv.lWheelSpd = self.convertToASCII(100) self._serialRecv.rWheelSpd = self.convertToASCII(100) # self._timerId = self.startTimer(100, Qt.PreciseTimer)
def connect(self): if self._serial is None: self._serial = QSerialPort() self._serial.readyRead.connect(self.serial_read_bytes) self._serial.setPortName(self.serial_port) self._serial.setBaudRate(self.serial_baudrate) try: # attempt to connect self._log('Connecting serial port {:s} ...'.format(self.serial_port)) self._serial.open(QIODevice.ReadWrite) # emit succesful connection signals self.serial_is_connected = True self.serial_connected.emit() self._log('Connected serial port!') except Exception as e: self._log_exception('Unable to open serial port', e)
def __init__(self, port, theme='day', parent=None): super().__init__(parent) self.setFont(Font().load()) self.setAcceptRichText(False) self.setReadOnly(False) self.setUndoRedoEnabled(False) self.setContextMenuPolicy(Qt.CustomContextMenu) self.customContextMenuRequested.connect(self.context_menu) self.setObjectName('replpane') # open the serial port self.serial = QSerialPort(self) self.serial.setPortName(port) if self.serial.open(QIODevice.ReadWrite): self.serial.setBaudRate(115200) self.serial.readyRead.connect(self.on_serial_read) # clear the text self.clear() # Send a Control-C self.serial.write(b'\x03') else: raise IOError("Cannot connect to device on port {}".format(port)) self.set_theme(theme)
def open_serial_link(self, port): """ Creates a new serial link instance. """ self.input_buffer = [] self.serial = QSerialPort() self.serial.setPortName(port) if self.serial.open(QIODevice.ReadWrite): self.serial.dataTerminalReady = True if not self.serial.isDataTerminalReady(): # Using pyserial as a 'hack' to open the port and set DTR # as QtSerial does not seem to work on some Windows :( # See issues #281 and #302 for details. self.serial.close() pyser = serial.Serial(port) # open serial port w/pyserial pyser.dtr = True pyser.close() self.serial.open(QIODevice.ReadWrite) self.serial.setBaudRate(115200) self.serial.readyRead.connect(self.on_serial_read) else: raise IOError("Cannot connect to device on port {}".format(port))
class REPLPane(QTextEdit): """ REPL = Read, Evaluate, Print, Loop. This widget represents a REPL client connected to a BBC micro:bit running MicroPython. The device MUST be flashed with MicroPython for this to work. """ def __init__(self, port, theme='day', parent=None): super().__init__(parent) self.setFont(Font().load()) self.setAcceptRichText(False) self.setReadOnly(False) self.setObjectName('replpane') # open the serial port self.serial = QSerialPort(self) self.serial.setPortName(port) if self.serial.open(QIODevice.ReadWrite): self.serial.setBaudRate(115200) self.serial.readyRead.connect(self.on_serial_read) # clear the text self.clear() # Send a Control-C self.serial.write(b'\x03') else: raise IOError("Cannot connect to device on port {}".format(port)) self.set_theme(theme) def set_theme(self, theme): """ Sets the theme / look for the REPL pane. """ if theme == 'day': self.setStyleSheet(DAY_STYLE) else: self.setStyleSheet(NIGHT_STYLE) def on_serial_read(self): """ Called when the application gets data from the connected device. """ self.process_bytes(bytes(self.serial.readAll())) def keyPressEvent(self, data): """ Called when the user types something in the REPL. Correctly encodes it and sends it to the connected device. """ key = data.key() msg = bytes(data.text(), 'utf8') if key == Qt.Key_Backspace: msg = b'\b' elif key == Qt.Key_Up: msg = b'\x1B[A' elif key == Qt.Key_Down: msg = b'\x1B[B' elif key == Qt.Key_Right: msg = b'\x1B[C' elif key == Qt.Key_Left: msg = b'\x1B[D' elif platform.system() == 'Darwin' and data.modifiers() == Qt.MetaModifier: # Handle the Control key. On OSX/macOS/Darwin (python calls this platform Darwin), this # is handled by Qt.MetaModifier. Other platforms (Linux, Windows) call this Qt.ControlModifier. # Go figure. See see http://doc.qt.io/qt-5/qt.html#KeyboardModifier-enum if Qt.Key_A <= key <= Qt.Key_Z: # The microbit treats an input of \x01 as Ctrl+A, etc. msg = bytes([1 + key - Qt.Key_A]) self.serial.write(msg) def process_bytes(self, bs): """ Given some incoming bytes of data, work out how to handle / display them in the REPL widget. """ tc = self.textCursor() # The text cursor must be on the last line of the document. If it isn't # then move it there. while tc.movePosition(QTextCursor.Down): pass for b in bs: if b == 8: # \b tc.movePosition(QTextCursor.Left) self.setTextCursor(tc) elif b == 13: # \r pass else: tc.deleteChar() self.setTextCursor(tc) self.insertPlainText(chr(b)) self.ensureCursorVisible() def clear(self): """ Clears the text of the REPL. """ self.setText('')
class SerialPortProxy(QObject): """ class SerialPortProxy """ stateChanged = QtCore.pyqtSignal(str) serialPortError = QtCore.pyqtSignal(QSerialPort.SerialPortError, str) displayRespond = QtCore.pyqtSignal(SerialRecv, QDateTime) def __init__(self, parent=None): super(SerialPortProxy, self).__init__(parent) self.setObjectName("SerialPortProxy") # self._currIndex = 0 self._currFrameId = 0 self._frameSize = 0 self._streamBuff = [] self._newBuff = [0] * 4096 self._pkgBuff = [0] * 100 self._serialRecv = SerialRecv() self._serialConfig = SerialPortConfig() self._serialPort = QSerialPort(self) # self._serialPort.error.connect(self.onSerialPortError) self._serialPort.readyRead.connect(self.readData) # self._serialSimulate = None # SerialSimulate(self) # read configuration settings = QSettings(self) # group - serialport properties settings.beginGroup("Settings/" + self.objectName() + "/SerialPort") self._serialConfig.port = settings.value("port", "COM1") infolist = settings.value("info", "115200-8-N-1").split("-") self._serialConfig.baudRate = int(infolist[0]) dataBits = int(infolist[1]) self._serialConfig.dataBits = ( QSerialPort.Data5 if dataBits == 5 else QSerialPort.Data6 if dataBits == 6 else QSerialPort.Data7 if dataBits == 7 else QSerialPort.Data8 if dataBits == 8 else QSerialPort.Data8 ) parity = infolist[2][0].upper() self._serialConfig.parity = ( QSerialPort.NoParity if parity == "N" else QSerialPort.EvenParity if parity == "E" else QSerialPort.OddParity if parity == "O" else QSerialPort.SpaceParity if parity == "S" else QSerialPort.MarkParity if parity == "M" else QSerialPort.NoParity ) stopBits = int(float(infolist[3]) * 10) self._serialConfig.stopBits = ( QSerialPort.OneStop if stopBits == 10 else QSerialPort.OneAndHalfStop if stopBits == 15 else QSerialPort.TwoStop if stopBits == 20 else QSerialPort.OneStop ) settings.endGroup() def config(self): return self._serialConfig def setConfig(self, info): self._serialConfig.port = info.port self._serialConfig.baudRate = info.baudRate self._serialConfig.dataBits = info.dataBits self._serialConfig.parity = info.parity self._serialConfig.stopBits = info.stopBits # settings = QSettings(self) settings.beginGroup("Settings/" + self.objectName() + "/SerialPort") settings.setValue("port", self._serialConfig.port) settings.setValue("info", self.__str__()) settings.endGroup() @QtCore.pyqtSlot(QSerialPort.SerialPortError, str) def onSerialPortError(self, error): print("SerialPort open failed!, %d" % error) self.serialPortError.emit( error, "No error" if error == QSerialPort.NoError else "Device not found" if error == QSerialPort.DeviceNotFoundError else "Permission error" if error == QSerialPort.PermissionError else "Open error" if error == QSerialPort.OpenError else "Parity error" if error == QSerialPort.ParityError else "Framing error" if error == QSerialPort.FramingError else "Break Condition error" if error == QSerialPort.BreakConditionError else "Write error" if error == QSerialPort.WriteError else "Read error" if error == QSerialPort.ReadError else "Resource error" if error == QSerialPort.ResourceError else "Unsupported operation" if error == QSerialPort.UnsupportedOperationError else "Unknown error" if error == QSerialPort.UnknownError else "Timeout" if error == QSerialPort.TimeoutError else "Not open" if error == QSerialPort.NotOpenError else "%d" % error, ) @QtCore.pyqtSlot() def start(self): if self._serialPort.isOpen(): self._serialPort.close() # config serialport properties self._serialPort.setPortName(self._serialConfig.port) if self._serialPort.open(QIODevice.ReadWrite): self._serialPort.setBaudRate(self._serialConfig.baudRate) self._serialPort.setDataBits(self._serialConfig.dataBits) self._serialPort.setParity(self._serialConfig.parity) self._serialPort.setStopBits(self._serialConfig.stopBits) self.stateChanged.emit("Open") @QtCore.pyqtSlot() def stop(self): if self._serialPort.isOpen(): self._serialPort.close() self.stateChanged.emit("Close") @QtCore.pyqtSlot() def save(self): self.setProperty("portState", self._serialPort.isOpen()) self.stop() # save state of simulator if self._serialSimulate: self._serialSimulate.save() @QtCore.pyqtSlot() def restore(self): self.start() if bool(self.property("portState")) else self.stop() # restore state of simulator if self._serialSimulate: self._serialSimulate.restore() @QtCore.pyqtSlot(SerialSend) def writeData(self, data): if not self._serialPort.isOpen(): # warning... return 0 return int(self._serialPort.write(data.pack())) @QtCore.pyqtSlot() def readData(self): self._streamBuff = self._serialPort.read(4096) self.unpack() return self._streamBuff.__len__() def unpack(self): for (i, value) in enumerate(self._streamBuff): if self._currIndex < self._serialRecv._offset_length: # 1.frame-header self._frameSize = 0 if value == self._serialRecv._headers[self._currIndex]: self._newBuff[self._currIndex] = value self._currIndex += 1 else: self._currIndex = 0 continue elif self._currIndex == self._serialRecv._offset_length: # 2.frame-length if value == self._serialRecv.length: pass else: self._currIndex = 0 continue self._frameSize = value self._newBuff[i] = value self._currIndex += 1 continue elif self._currIndex == self._serialRecv._offset_index: # 3.frame-index self._currFrameId = value self._newBuff[i] = value self._currIndex += 1 continue elif self._currIndex < self._frameSize: # 4.frame-data self._newBuff[i] = value self._currIndex += 1 if self._currIndex == self._frameSize: # receive a full frame successfully # 5.frame-sum s = 0 for index in range(0, self._serialRecv._offset_sum): s = (s + self._newBuff[index]) & 0xFF if self._newBuff[self._serialRecv._offset_sum] != s: self._currIndex = 0 # continue # invalid frame # 6.frame-tail if self._newBuff[self._serialRecv._offset_tail] != int(self._serialRecv.tail): self._currIndex = 0 # invalid frame continue # 7.save as... self._pkgBuff = self._newBuff[0 : self._frameSize] # 8.dispatch self.dispatch() # 9.reset self._currIndex = 0 def dispatch(self): # save as... self._serialRecv.unpack(bytes(self._pkgBuff)) # convert self._serialRecv.lMBrakeP = self.swapUint16(self._serialRecv.lMBrakeP) self._serialRecv.lABrakeP = self.swapUint16(self._serialRecv.lABrakeP) self._serialRecv.rMBrakeP = self.swapUint16(self._serialRecv.rMBrakeP) self._serialRecv.rABrakeP = self.swapUint16(self._serialRecv.rABrakeP) self._serialRecv.lMRotateP = self.swapUint16(self._serialRecv.lMRotateP) self._serialRecv.lARotateP = self.swapUint16(self._serialRecv.lARotateP) self._serialRecv.rMRotateP = self.swapUint16(self._serialRecv.rMRotateP) self._serialRecv.rARotateP = self.swapUint16(self._serialRecv.rARotateP) self._serialRecv.lWheelSpd = self.swapUint32(self._serialRecv.lWheelSpd) self._serialRecv.rWheelSpd = self.swapUint32(self._serialRecv.rWheelSpd) # emit self.displayRespond.emit(self._serialRecv, QDateTime.currentDateTime()) _crc16_table = bytes(256) @staticmethod def calcRCR16(data): cnta = 0 cntb = 0 crcval = 0 @staticmethod def serialPortSendSum(data): return 0 # TODO s = 0 for i in range(0, data._offset_sum): s = (s + data[i]) & 0xFF return s @staticmethod def serialPortRecvSum(data): return 0 # TODO s = 0 for i in range(0, data._offset_sum): s = (s + data[i]) & 0xFF return s @staticmethod def swapUint16(value): return value @staticmethod def swapUint32(value): return value @staticmethod def convertFromASCII(value): return value @staticmethod def convertToASCII(value): return value
class REPLPane(QTextEdit): """ REPL = Read, Evaluate, Print, Loop. This widget represents a REPL client connected to a BBC micro:bit running MicroPython. The device MUST be flashed with MicroPython for this to work. """ def __init__(self, port, theme='day', parent=None): super().__init__(parent) self.setFont(Font().load()) self.setAcceptRichText(False) self.setReadOnly(False) self.setUndoRedoEnabled(False) self.setContextMenuPolicy(Qt.CustomContextMenu) self.customContextMenuRequested.connect(self.context_menu) self.setObjectName('replpane') # open the serial port self.serial = QSerialPort(self) self.serial.setPortName(port) if self.serial.open(QIODevice.ReadWrite): self.serial.setBaudRate(115200) self.serial.readyRead.connect(self.on_serial_read) # clear the text self.clear() # Send a Control-C self.serial.write(b'\x03') else: raise IOError("Cannot connect to device on port {}".format(port)) self.set_theme(theme) def paste(self): """ Grabs clipboard contents then sends down the serial port. """ clipboard = QApplication.clipboard() if clipboard and clipboard.text(): self.serial.write(bytes(clipboard.text(), 'utf8')) def context_menu(self): """" Creates custom context menu with just copy and paste. """ menu = QMenu(self) if platform.system() == 'Darwin': copy_keys = QKeySequence(Qt.CTRL + Qt.Key_C) paste_keys = QKeySequence(Qt.CTRL + Qt.Key_V) else: copy_keys = QKeySequence(Qt.CTRL + Qt.SHIFT + Qt.Key_C) paste_keys = QKeySequence(Qt.CTRL + Qt.SHIFT + Qt.Key_V) menu.addAction("Copy", self.copy, copy_keys) menu.addAction("Paste", self.paste, paste_keys) menu.exec_(QCursor.pos()) def cursor_to_end(self): """ Moves the cursor to the very end of the available text. """ tc = self.textCursor() tc.movePosition(QTextCursor.End) self.setTextCursor(tc) def set_theme(self, theme): """ Sets the theme / look for the REPL pane. """ if theme == 'day': self.setStyleSheet(DAY_STYLE) else: self.setStyleSheet(NIGHT_STYLE) def on_serial_read(self): """ Called when the application gets data from the connected device. """ self.process_bytes(bytes(self.serial.readAll())) def keyPressEvent(self, data): """ Called when the user types something in the REPL. Correctly encodes it and sends it to the connected device. """ key = data.key() msg = bytes(data.text(), 'utf8') if key == Qt.Key_Backspace: msg = b'\b' elif key == Qt.Key_Up: msg = b'\x1B[A' elif key == Qt.Key_Down: msg = b'\x1B[B' elif key == Qt.Key_Right: msg = b'\x1B[C' elif key == Qt.Key_Left: msg = b'\x1B[D' elif key == Qt.Key_Home: msg = b'\x1B[H' elif key == Qt.Key_End: msg = b'\x1B[F' elif (platform.system() == 'Darwin' and data.modifiers() == Qt.MetaModifier) or \ (platform.system() != 'Darwin' and data.modifiers() == Qt.ControlModifier): # Handle the Control key. On OSX/macOS/Darwin (python calls this # platform Darwin), this is handled by Qt.MetaModifier. Other # platforms (Linux, Windows) call this Qt.ControlModifier. Go # figure. See http://doc.qt.io/qt-5/qt.html#KeyboardModifier-enum if Qt.Key_A <= key <= Qt.Key_Z: # The microbit treats an input of \x01 as Ctrl+A, etc. msg = bytes([1 + key - Qt.Key_A]) elif (data.modifiers() == Qt.ControlModifier | Qt.ShiftModifier) or \ (platform.system() == 'Darwin' and data.modifiers() == Qt.ControlModifier): # Command-key on Mac, Ctrl-Shift on Win/Lin if key == Qt.Key_C: self.copy() msg = b'' elif key == Qt.Key_V: self.paste() msg = b'' self.serial.write(msg) def process_bytes(self, data): """ Given some incoming bytes of data, work out how to handle / display them in the REPL widget. """ tc = self.textCursor() # The text cursor must be on the last line of the document. If it isn't # then move it there. while tc.movePosition(QTextCursor.Down): pass i = 0 while i < len(data): if data[i] == 8: # \b tc.movePosition(QTextCursor.Left) self.setTextCursor(tc) elif data[i] == 13: # \r pass elif data[i] == 27 and data[i + 1] == 91: # VT100 cursor: <Esc>[ i += 2 # move index to after the [ m = re.search(r'(?P<count>[\d]*)(?P<action>[ABCDK])', data[i:].decode('utf-8')) # move to (almost) after control seq (will ++ at end of loop) i += m.end() - 1 if m.group("count") == '': count = 1 else: count = int(m.group("count")) if m.group("action") == "A": # up tc.movePosition(QTextCursor.Up, n=count) self.setTextCursor(tc) elif m.group("action") == "B": # down tc.movePosition(QTextCursor.Down, n=count) self.setTextCursor(tc) elif m.group("action") == "C": # right tc.movePosition(QTextCursor.Right, n=count) self.setTextCursor(tc) elif m.group("action") == "D": # left tc.movePosition(QTextCursor.Left, n=count) self.setTextCursor(tc) elif m.group("action") == "K": # delete things if m.group("count") == "": # delete to end of line tc.movePosition(QTextCursor.EndOfLine, mode=QTextCursor.KeepAnchor) tc.removeSelectedText() self.setTextCursor(tc) elif data[i] == 10: # \n tc.movePosition(QTextCursor.End) self.setTextCursor(tc) self.insertPlainText(chr(data[i])) else: tc.deleteChar() self.setTextCursor(tc) self.insertPlainText(chr(data[i])) i += 1 self.ensureCursorVisible() def clear(self): """ Clears the text of the REPL. """ self.setText('')
class REPLPane(QTextEdit): """ REPL = Read, Evaluate, Print, Loop. This widget represents a REPL client connected to a BBC micro:bit. """ def __init__(self, port, parent=None): super().__init__(parent) self.setAcceptRichText(False) self.setReadOnly(False) self.setLineWrapMode(QTextEdit.NoWrap) self.setObjectName('replpane') # open the serial port self.serial = QSerialPort(self) self.serial.setPortName(port) self.serial.setBaudRate(115200) print(self.serial.open(QIODevice.ReadWrite)) self.serial.readyRead.connect(self.on_serial_read) self.serial_input_buffer = b'' # clear the text self.clear() def on_serial_read(self): self.process_bytes(bytes(self.serial.readAll())) def keyPressEvent(self, data): text = data.text() msg = bytes(text, 'utf8') key = data.key() if key == Qt.Key_Backspace: msg = b'\b' elif key == Qt.Key_Up: msg = b'\x1B[A' elif key == Qt.Key_Down: msg = b'\x1B[B' elif key == Qt.Key_Right: msg = b'\x1B[C' elif key == Qt.Key_Left: msg = b'\x1B[D' self.serial.write(msg) def process_bytes(self, bs): bs = self.serial_input_buffer + bs while len(bs): num_use = 0 if bs[0] == 8: # backspace self.delete() num_use = 1 elif bs[0] == 13: # \r # ignore num_use = 1 elif bs[0] == 27: # escape if bs.startswith(b'\x1b[K'): # kill to end of line num_use = 3 elif bs.startswith(b'\x1b[') and len(bs) >= 3 and chr(bs[2]).isdigit(): n = bs[2] - ord('0') cmd_idx = 3 if len(bs) >= 4 and chr(bs[3]).isdigit(): n = 10 * n + bs[3] - ord('0') cmd_idx = 4 if cmd_idx < len(bs): if bs[cmd_idx] == ord('D'): # backspace n chars for i in range(n): self.delete() num_use = cmd_idx + 1 if num_use == 0: # unknown or incomplete escape sequence print(bs) else: self.append(chr(bs[0])) num_use = 1 if num_use == 0: break bs = bs[num_use:] self.serial_input_buffer = bs def append(self, txt): tc = self.textCursor() tc.movePosition(QTextCursor.End) self.setTextCursor(tc) self.insertPlainText(txt) self.ensureCursorVisible() def delete(self): tc = self.textCursor() tc.deletePreviousChar() def clear(self): self.setText('') def kill(self): if self.serial.isOpen(): self.serial.close()
def open_serial_port(name): try: serial_port = QSerialPort() serial_port.setPortName(name) serial_port.setBaudRate(QSerialPort.Baud9600, QSerialPort.AllDirections) serial_port.setParity(QSerialPort.NoParity) serial_port.setStopBits(QSerialPort.OneStop) serial_port.setDataBits(QSerialPort.Data8) serial_port.setFlowControl(QSerialPort.NoFlowControl) serial_port.open(QSerialPort.ReadWrite) return serial_port except Exception as e: print("open_serial_port", e) return None
class REPLPane(QTextEdit): """ REPL = Read, Evaluate, Print, Loop. This widget represents a REPL client connected to a BBC micro:bit. """ def __init__(self, port, parent=None): super().__init__(parent) self.setAcceptRichText(False) self.setReadOnly(False) self.setLineWrapMode(QTextEdit.NoWrap) self.setObjectName('replpane') # open the serial port self.serial = QSerialPort(self) self.serial.setPortName(port) self.serial.setBaudRate(115200) print(self.serial.open(QIODevice.ReadWrite)) self.serial.readyRead.connect(self.on_serial_read) # clear the text self.clear() def on_serial_read(self): self.process_bytes(bytes(self.serial.readAll())) def keyPressEvent(self, data): key = data.key() msg = bytes(data.text(), 'utf8') if key == Qt.Key_Backspace: msg = b'\b' elif key == Qt.Key_Up: msg = b'\x1B[A' elif key == Qt.Key_Down: msg = b'\x1B[B' elif key == Qt.Key_Right: msg = b'\x1B[C' elif key == Qt.Key_Left: msg = b'\x1B[D' elif data.modifiers() == Qt.MetaModifier: # Handle the Control key. I would've expected us to have to test # for Qt.ControlModifier, but on (my!) OSX Qt.MetaModifier does # correspond to the Control key. I've read something that suggests # that it's different on other platforms. if Qt.Key_A <= key <= Qt.Key_Z: # The microbit treats an input of \x01 as Ctrl+A, etc. msg = bytes([1 + key - Qt.Key_A]) self.serial.write(msg) def process_bytes(self, bs): tc = self.textCursor() for b in bs: if b == 8: # \b tc.movePosition(QTextCursor.Left) self.setTextCursor(tc) elif b == 13: # \r pass else: tc.deleteChar() self.setTextCursor(tc) self.insertPlainText(chr(b)) self.ensureCursorVisible() def clear(self): self.setText('')
class KPSerialInterface(QtCore.QObject): subsys = 'SERIAL' msg_parser_period = 0.005 # S I G N A L S #=========================================================================== connected = pyqtSignal() disconnected = pyqtSignal() finished = pyqtSignal() rc_command = pyqtSignal(KPRemoteControlState) # C O N S T R U C T O R #=========================================================================== def __init__(self, serial_port="COM4", serial_baudrate=250000, **kwds): super(KPSerialInterface, self).__init__(**kwds) # thread variables self.terminate = False self._current_time = time.time() self._previous_time = self._current_time # serial interface self._serial = None self.is_connected = False self.port = serial_port self.baudrate = serial_baudrate self._rx_buffer = collections.deque(maxlen=512) # initialize control timers self._message_parser_timer = QTimer() self._message_parser_timer.timeout.connect(self.parse_rx_buffer) self._message_parser_timer.start(KPSerialInterface.msg_parser_period * 1000.0) # data variables self._rc_cmd = KPRemoteControlState() # M E T H O D S #=========================================================================== def connect(self): if self._serial is None: self._serial = QSerialPort() self._serial.readyRead.connect(self.serial_read_bytes) self._serial.setPortName(self.serial_port) self._serial.setBaudRate(self.serial_baudrate) try: # attempt to connect self._log('Connecting serial port {:s} ...'.format(self.serial_port)) self._serial.open(QIODevice.ReadWrite) # emit succesful connection signals self.serial_is_connected = True self.serial_connected.emit() self._log('Connected serial port!') except Exception as e: self._log_exception('Unable to open serial port', e) # P R I V A T E M E T H O D S #=========================================================================== def _parse_message(self, message): msg_bytes = '' for b in message: msg_bytes += hex(b) + " " #print("Message received! {:s}".format(msg_bytes)) message_type = message[0] if message_type == 0x40: button_state = message[1] message_bytes = bytearray(message) joystick_x = struct.unpack("H", message_bytes[2:4])[0] joystick_y = struct.unpack("H", message_bytes[4:6])[0] joystick_z = struct.unpack("H", message_bytes[6:8])[0] #print("State message: {:4s} {:4d} {:4d} {:4d}".format(hex(button_state), joystick_x, joystick_y, joystick_z)) # construct remote control command object #rc_cmd = KPRemoteControlState(button_state, joystick_x, joystick_y, joystick_z) self._rc_cmd.set_button_states(button_state) self._rc_cmd.joystick['x'] = joystick_x self._rc_cmd.joystick['y'] = joystick_y self._rc_cmd.joystick['z'] = joystick_z self.rc_command.emit(self._rc_cmd) # S L O T S #=========================================================================== @pyqtSlot() def process(self): while not self.terminate: # service Qt events QCoreApplication.processEvents() # thread termination self.disconnect() self._log('Serial interface thread terminating...') self.finished.emit() @pyqtSlot() def connect(self): if self._serial is None: self._serial = QSerialPort() self._serial.readyRead.connect(self.read_data) self._serial.setPortName(self.port) self._serial.setBaudRate(self.baudrate) try: # attempt to connect self._log('Connecting serial port {:s} ...'.format(self.port)) self._serial.open(QIODevice.ReadWrite) # emit succesful connection signals self.is_connected = True self.connected.emit() self._log('Connected serial port!') except Exception as e: self._log_exception('Unable to open serial port', e) @pyqtSlot() def read_data(self): rx_bytes = self._serial.readAll() #print("len = {:3d}".format(len(self._rx_buffer))) #print(rx_bytes.data()) for b in rx_bytes.data(): self._rx_buffer.append(b) ''' try: print(self._rx_buffer) except Exception as e: self._log_exception('EXCEPTION! {:s}'.format(str(e)), e) ''' @pyqtSlot() def parse_rx_buffer(self): msg_size = 0 if len(self._rx_buffer) >= 1: byte1 = self._rx_buffer[0] if byte1 != ord('$'): self._rx_buffer.popleft() return if len(self._rx_buffer) >= 2: byte2 = self._rx_buffer[1] if byte2 != ord('$'): self._rx_buffer.popleft() self._rx_buffer.popleft() return if len(self._rx_buffer) >= 3: msg_size = self._rx_buffer[2] if len(self._rx_buffer) >= (3 + msg_size): # pop the header self._rx_buffer.popleft() self._rx_buffer.popleft() self._rx_buffer.popleft() # pop the message message = [] for i in range(msg_size): message.append(self._rx_buffer.popleft()) self._parse_message(message) @pyqtSlot() def disconnect(self): if self._serial is not None: #self._serial.readyRead.disconnect(self) self._serial.close() self._rx_buffer.clear() self.is_connected = False self.disconnected.emit() self._log('Disconnected serial port') # H E L P E R F U N C T I O N S #=========================================================================== def _log(self, log_message, log_type='info', log_data=None): Logger.log(KPSerialInterface.subsys, log_message, log_type, log_data) def _log_warning(self, log_message, log_data=None): Logger.log_warning(KPSerialInterface.subsys, log_message, log_data) def _log_exception(self, log_message, log_exception): Logger.log_exception(KPSerialInterface.subsys, log_message, log_exception)
class ControlPanel(QWidget): """ This control panel steers the dr robot protocol. It opens the serial port, and handles the protocol. """ def __init__(self): super().__init__() self.logger = logging.getLogger('controlpanel') l = QVBoxLayout(self) b = QPushButton("Gas") b.clicked.connect(self.do_go) l.addWidget(b) b2 = QPushButton("Bremsen") b2.clicked.connect(self.do_stop) l.addWidget(b2) self.motor_panel = MotorDataPanel() self.info_panel = InfoDataPanel() l.addWidget(self.info_panel) l.addWidget(self.motor_panel) self.protocol = Protocol() self.protocol.process_msg = self.process_msg self.msg_cntr = 0 # Construct port: self.port = QSerialPort(self) self.port.readyRead.connect(self.do_read_bytes) self.logger.debug('Created class') # open port: self.do_open() self.do_go() def closeEvent(self, event): self.port.close() super().closeEvent(event) def do_open(self): self.logger.debug('Opening port') self.port.setPortName('/dev/ttyUSB0') self.logger.debug('Port name {}'.format(self.port.portName())) self.logger.debug('Baud rate: {}'.format(self.port.baudRate())) self.logger.debug('Data bits: {}'.format(self.port.dataBits())) res = self.port.open(QIODevice.ReadWrite) if not res: self.logger.error('Error opening port {}'.format(self.port.error())) if not self.port.setBaudRate(115200): self.logger.error('Error setting baudrate: {}'.format(self.port.error())) self.logger.debug('Port opened') self.logger.debug('Port name {}'.format(self.port.portName())) self.logger.debug('Baud rate: {}'.format(self.port.baudRate())) def do_read_bytes(self): data = self.port.read(100) # self.logger.debug('Read {} bytes'.format(data)) self.protocol.add_bytes(data) def process_msg(self, typ, data): """ Dissect the contents of the message. #define COMTYPE_MOTOR 40 """ self.msg_cntr += 1 self.info_panel.msgcnt = self.msg_cntr COMTYPE_SYSTEM = 0xFF COMTYPE_MOTOR_SENSOR = 0x7B COMTYPE_CUSTOM_SENSOR = 0x7C COMTYPE_STANDARD_SENSOR = 0x7D COMTYPE_SENSOR = 0x7F if typ == COMTYPE_MOTOR_SENSOR: # format: 6x angles, 6x current, pos, vel, pos, vel enc0, enc1, _, _, _, _, cur0, cur1, _, _, _, _, pos0, vel0, pos1, vel1, bitmask = struct.unpack('<HHH HHH HHH HHH H H H H B', data) self.motor_panel.pos0 = pos0 self.motor_panel.pos1 = pos1 self.motor_panel.enc0 = enc0 self.motor_panel.enc1 = enc1 self.motor_panel.vel0 = vel0 self.motor_panel.vel1 = vel1 elif typ == COMTYPE_SENSOR: #self.logger.warning('Sensor data') pass elif typ == COMTYPE_CUSTOM_SENSOR: #self.logger.warning('Custom sensor data') pass elif typ == COMTYPE_STANDARD_SENSOR: #self.logger.warning('Standard sensor data') pass else: self.logger.warning('Unknown packet type {}'.format(typ)) def send_msg(self, typ, data): msg = self.protocol.make_msg(typ, data) print(msg) def set_motor_velctrl_pid(self, channel, kp, ki, kd): """ const unsigned char POSITIONPID = 7; const unsigned char MOTORVELOCITYCTRL = 26; const unsigned char MOTORVELOCITYCTRLALL = 27; const unsigned char SERVOCTRL = 28; const unsigned char SERVOCTRLALL = 29; const unsigned char MOTORENABLE = 0x1e; const unsigned char MOTORFRICCOMP = 31; const unsigned char CUSTOMIO = 22; const unsigned char POWERCTRL = 22; """ MOTORPARAMETERSETTING = 7 VELOCITYPID = 8 KP_ID = 1 KD_ID = 2 KI_ID = 3 msg = struct.pack('<BB BH BH BH', VELOCITYPID, channel, KP_ID, kp, KD_ID, ki, KI_ID, ki) assert len(msg) == 11, str(msg) self.send_msg(MOTORPARAMETERSETTING, msg) def do_go(self): self.logger.debug('Connect!') self.set_motor_velctrl_pid(0, 1, 0, 1) def do_stop(self): self.logger.debug('Stop!')
#!/usr/bin/env python3 # -*- coding: utf-8 -*- from PyQt5.QtCore import QCoreApplication from PyQt5.QtSerialPort import QSerialPort, QSerialPortInfo from middleware_common import * from OldMiddleWare import parse_command import sys import time if __name__ == "__main__": a = QCoreApplication(sys.argv) serial_port = QSerialPort() serial_port.setPortName(sys.argv[1]) serial_port.setBaudRate(QSerialPort.Baud9600, QSerialPort.AllDirections) serial_port.setParity(QSerialPort.NoParity) serial_port.setStopBits(QSerialPort.OneStop) serial_port.setDataBits(QSerialPort.Data8) serial_port.setFlowControl(QSerialPort.NoFlowControl) serial_port.open(QSerialPort.ReadWrite) time.sleep(3) set_profile(serial_port, 1) # set_date_time(serial_port) set_wifi(serial_port) set_end_point(serial_port) time.sleep(3) while True: try: buffer = serial_port.read(100) if len(buffer) > 0: print(buffer, end='')
class Window(QMainWindow): """ Defines the look and characteristics of the application's main window. """ title = _("Mu {}").format(__version__) icon = "icon" timer = None usb_checker = None serial = None repl = None plotter = None _zoom_in = pyqtSignal(int) _zoom_out = pyqtSignal(int) close_serial = pyqtSignal() write_to_serial = pyqtSignal(bytes) data_received = pyqtSignal(bytes) def zoom_in(self): """ Handles zooming in. """ self._zoom_in.emit(2) def zoom_out(self): """ Handles zooming out. """ self._zoom_out.emit(2) def connect_zoom(self, widget): """ Connects a referenced widget to the zoom related signals. """ self._zoom_in.connect(widget.zoomIn) self._zoom_out.connect(widget.zoomOut) @property def current_tab(self): """ Returns the currently focussed tab. """ return self.tabs.currentWidget() def set_read_only(self, is_readonly): """ Set all tabs read-only. """ self.read_only_tabs = is_readonly for tab in self.widgets: tab.setReadOnly(is_readonly) def get_load_path(self, folder): """ Displays a dialog for selecting a file to load. Returns the selected path. Defaults to start in the referenced folder. """ path, _ = QFileDialog.getOpenFileName(self.widget, 'Open file', folder, '*.py *.PY *.hex') logger.debug('Getting load path: {}'.format(path)) return path def get_save_path(self, folder): """ Displays a dialog for selecting a file to save. Returns the selected path. Defaults to start in the referenced folder. """ path, _ = QFileDialog.getSaveFileName(self.widget, 'Save file', folder) logger.debug('Getting save path: {}'.format(path)) return path def get_microbit_path(self, folder): """ Displays a dialog for locating the location of the BBC micro:bit in the host computer's filesystem. Returns the selected path. Defaults to start in the referenced folder. """ path = QFileDialog.getExistingDirectory(self.widget, 'Locate BBC micro:bit', folder, QFileDialog.ShowDirsOnly) logger.debug('Getting micro:bit path: {}'.format(path)) return path def add_tab(self, path, text, api): """ Adds a tab with the referenced path and text to the editor. """ new_tab = EditorPane(path, text) new_tab.connect_margin(self.breakpoint_toggle) new_tab_index = self.tabs.addTab(new_tab, new_tab.label) new_tab.set_api(api) @new_tab.modificationChanged.connect def on_modified(): modified_tab_index = self.tabs.currentIndex() self.tabs.setTabText(modified_tab_index, new_tab.label) self.update_title(new_tab.label) self.tabs.setCurrentIndex(new_tab_index) self.connect_zoom(new_tab) self.set_theme(self.theme) new_tab.setFocus() if self.read_only_tabs: new_tab.setReadOnly(self.read_only_tabs) def focus_tab(self, tab): index = self.tabs.indexOf(tab) self.tabs.setCurrentIndex(index) tab.setFocus() @property def tab_count(self): """ Returns the number of active tabs. """ return self.tabs.count() @property def widgets(self): """ Returns a list of references to the widgets representing tabs in the editor. """ return [self.tabs.widget(i) for i in range(self.tab_count)] @property def modified(self): """ Returns a boolean indication if there are any modified tabs in the editor. """ for widget in self.widgets: if widget.isModified(): return True return False def on_serial_read(self): """ Called when the connected device is ready to send data via the serial connection. It reads all the available data, emits the data_received signal with the received bytes and, if appropriate, emits the tuple_received signal with the tuple created from the bytes received. """ data = bytes(self.serial.readAll()) # get all the available bytes. self.data_received.emit(data) def open_serial_link(self, port): """ Creates a new serial link instance. """ self.input_buffer = [] self.serial = QSerialPort() self.serial.setPortName(port) if self.serial.open(QIODevice.ReadWrite): self.serial.dataTerminalReady = True if not self.serial.isDataTerminalReady(): # Using pyserial as a 'hack' to open the port and set DTR # as QtSerial does not seem to work on some Windows :( # See issues #281 and #302 for details. self.serial.close() pyser = serial.Serial(port) # open serial port w/pyserial pyser.dtr = True pyser.close() self.serial.open(QIODevice.ReadWrite) self.serial.setBaudRate(115200) self.serial.readyRead.connect(self.on_serial_read) else: raise IOError("Cannot connect to device on port {}".format(port)) def close_serial_link(self): """ Close and clean up the currently open serial link. """ self.serial.close() self.serial = None def add_filesystem(self, home, file_manager): """ Adds the file system pane to the application. """ self.fs_pane = FileSystemPane(home) self.fs = QDockWidget(_('Filesystem on micro:bit')) self.fs.setWidget(self.fs_pane) self.fs.setFeatures(QDockWidget.DockWidgetMovable) self.fs.setAllowedAreas(Qt.BottomDockWidgetArea) self.addDockWidget(Qt.BottomDockWidgetArea, self.fs) self.fs_pane.setFocus() file_manager.on_list_files.connect(self.fs_pane.on_ls) self.fs_pane.list_files.connect(file_manager.ls) self.fs_pane.microbit_fs.put.connect(file_manager.put) self.fs_pane.microbit_fs.delete.connect(file_manager.delete) self.fs_pane.microbit_fs.list_files.connect(file_manager.ls) self.fs_pane.local_fs.get.connect(file_manager.get) self.fs_pane.local_fs.list_files.connect(file_manager.ls) file_manager.on_put_file.connect(self.fs_pane.microbit_fs.on_put) file_manager.on_delete_file.connect(self.fs_pane.microbit_fs.on_delete) file_manager.on_get_file.connect(self.fs_pane.local_fs.on_get) file_manager.on_list_fail.connect(self.fs_pane.on_ls_fail) file_manager.on_put_fail.connect(self.fs_pane.on_put_fail) file_manager.on_delete_fail.connect(self.fs_pane.on_delete_fail) file_manager.on_get_fail.connect(self.fs_pane.on_get_fail) self.connect_zoom(self.fs_pane) return self.fs_pane def add_micropython_repl(self, port, name): """ Adds a MicroPython based REPL pane to the application. """ if not self.serial: self.open_serial_link(port) # Send a Control-C / keyboard interrupt. self.serial.write(b'\x03') repl_pane = MicroPythonREPLPane(serial=self.serial, theme=self.theme) self.data_received.connect(repl_pane.process_bytes) self.add_repl(repl_pane, name) def add_micropython_plotter(self, port, name): """ Adds a plotter that reads data from a serial connection. """ if not self.serial: self.open_serial_link(port) plotter_pane = PlotterPane(theme=self.theme) self.data_received.connect(plotter_pane.process_bytes) self.add_plotter(plotter_pane, name) def add_jupyter_repl(self, kernel_manager, kernel_client): """ Adds a Jupyter based REPL pane to the application. """ kernel_manager.kernel.gui = 'qt4' kernel_client.start_channels() ipython_widget = JupyterREPLPane(theme=self.theme) ipython_widget.kernel_manager = kernel_manager ipython_widget.kernel_client = kernel_client self.add_repl(ipython_widget, _('Python3 (Jupyter)')) def add_repl(self, repl_pane, name): """ Adds the referenced REPL pane to the application. """ self.repl_pane = repl_pane self.repl = QDockWidget(_('{} REPL').format(name)) self.repl.setWidget(repl_pane) self.repl.setFeatures(QDockWidget.DockWidgetMovable) self.repl.setAllowedAreas(Qt.BottomDockWidgetArea | Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) self.addDockWidget(Qt.BottomDockWidgetArea, self.repl) self.connect_zoom(self.repl_pane) self.repl_pane.set_theme(self.theme) self.repl_pane.setFocus() def add_plotter(self, plotter_pane, name): """ Adds the referenced plotter pane to the application. """ self.plotter_pane = plotter_pane self.plotter = QDockWidget(_('{} Plotter').format(name)) self.plotter.setWidget(plotter_pane) self.plotter.setFeatures(QDockWidget.DockWidgetMovable) self.plotter.setAllowedAreas(Qt.BottomDockWidgetArea | Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) self.addDockWidget(Qt.BottomDockWidgetArea, self.plotter) self.plotter_pane.set_theme(self.theme) self.plotter_pane.setFocus() def add_python3_runner(self, script_name, working_directory, interactive=False, debugger=False, command_args=None, runner=None): """ Display console output for the referenced Python script. The script will be run within the workspace_path directory. If interactive is True (default is False) the Python process will run in interactive mode (dropping the user into the REPL when the script completes). If debugger is True (default is False) the script will be run within a debug runner session. The debugger overrides the interactive flag (you cannot run the debugger in interactive mode). If there is a list of command_args (the default is None) then these will be passed as further arguments into the command run in the new process. If runner is give, this is used as the command to start the Python process. """ self.process_runner = PythonProcessPane(self) self.runner = QDockWidget(_("Running: {}").format( os.path.basename(script_name))) self.runner.setWidget(self.process_runner) self.runner.setFeatures(QDockWidget.DockWidgetMovable) self.runner.setAllowedAreas(Qt.BottomDockWidgetArea | Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) self.addDockWidget(Qt.BottomDockWidgetArea, self.runner) self.process_runner.start_process(script_name, working_directory, interactive, debugger, command_args, runner) self.process_runner.setFocus() self.connect_zoom(self.process_runner) return self.process_runner def add_debug_inspector(self): """ Display a debug inspector to view the call stack. """ self.debug_inspector = DebugInspector() self.debug_model = QStandardItemModel() self.debug_inspector.setModel(self.debug_model) self.debug_inspector.setUniformRowHeights(True) self.inspector = QDockWidget(_('Debug Inspector')) self.inspector.setWidget(self.debug_inspector) self.inspector.setFeatures(QDockWidget.DockWidgetMovable) self.inspector.setAllowedAreas(Qt.BottomDockWidgetArea | Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) self.addDockWidget(Qt.RightDockWidgetArea, self.inspector) self.connect_zoom(self.debug_inspector) def update_debug_inspector(self, locals_dict): """ Given the contents of a dict representation of the locals in the current stack frame, update the debug inspector with the new values. """ excluded_names = ['__builtins__', '__debug_code__', '__debug_script__', ] names = sorted([x for x in locals_dict if x not in excluded_names]) self.debug_model.clear() self.debug_model.setHorizontalHeaderLabels([_('Name'), _('Value'), ]) for name in names: try: # DANGER! val = eval(locals_dict[name]) except Exception: val = None if isinstance(val, list): # Show a list consisting of rows of position/value list_item = QStandardItem(name) for i, i_val in enumerate(val): list_item.appendRow([ QStandardItem(str(i)), QStandardItem(repr(i_val)) ]) self.debug_model.appendRow([ list_item, QStandardItem(_('(A list of {} items.)').format(len(val))) ]) elif isinstance(val, dict): # Show a dict consisting of rows of key/value pairs. dict_item = QStandardItem(name) for k, k_val in val.items(): dict_item.appendRow([ QStandardItem(repr(k)), QStandardItem(repr(k_val)) ]) self.debug_model.appendRow([ dict_item, QStandardItem(_('(A dict of {} items.)').format(len(val))) ]) else: self.debug_model.appendRow([ QStandardItem(name), QStandardItem(locals_dict[name]), ]) def remove_filesystem(self): """ Removes the file system pane from the application. """ if hasattr(self, 'fs') and self.fs: self.fs_pane = None self.fs.setParent(None) self.fs.deleteLater() self.fs = None def remove_repl(self): """ Removes the REPL pane from the application. """ if self.repl: self.repl_pane = None self.repl.setParent(None) self.repl.deleteLater() self.repl = None if not self.plotter: self.serial = None def remove_plotter(self): """ Removes the plotter pane from the application. """ if self.plotter: self.plotter_pane = None self.plotter.setParent(None) self.plotter.deleteLater() self.plotter = None if not self.repl: self.serial = None def remove_python_runner(self): """ Removes the runner pane from the application. """ if hasattr(self, 'runner') and self.runner: self.process_runner = None self.runner.setParent(None) self.runner.deleteLater() self.runner = None def remove_debug_inspector(self): """ Removes the debug inspector pane from the application. """ if hasattr(self, 'inspector') and self.inspector: self.debug_inspector = None self.debug_model = None self.inspector.setParent(None) self.inspector.deleteLater() self.inspector = None def set_theme(self, theme): """ Sets the theme for the REPL and editor tabs. """ self.theme = theme if theme == 'contrast': self.setStyleSheet(CONTRAST_STYLE) new_theme = ContrastTheme new_icon = 'theme_day' elif theme == 'night': new_theme = NightTheme new_icon = 'theme_contrast' self.setStyleSheet(NIGHT_STYLE) else: self.setStyleSheet(DAY_STYLE) new_theme = DayTheme new_icon = 'theme' for widget in self.widgets: widget.set_theme(new_theme) self.button_bar.slots['theme'].setIcon(load_icon(new_icon)) if hasattr(self, 'repl') and self.repl: self.repl_pane.set_theme(theme) if hasattr(self, 'plotter') and self.plotter: self.plotter_pane.set_theme(theme) def show_logs(self, log, theme): """ Display the referenced content of the log. """ log_box = LogDisplay() log_box.setup(log, theme) log_box.exec() def show_message(self, message, information=None, icon=None): """ Displays a modal message to the user. If information is passed in this will be set as the additional informative text in the modal dialog. Since this mechanism will be used mainly for warning users that something is awry the default icon is set to "Warning". It's possible to override the icon to one of the following settings: NoIcon, Question, Information, Warning or Critical. """ message_box = QMessageBox(self) message_box.setText(message) message_box.setWindowTitle('Mu') if information: message_box.setInformativeText(information) if icon and hasattr(message_box, icon): message_box.setIcon(getattr(message_box, icon)) else: message_box.setIcon(message_box.Warning) logger.debug(message) logger.debug(information) message_box.exec() def show_confirmation(self, message, information=None, icon=None): """ Displays a modal message to the user to which they need to confirm or cancel. If information is passed in this will be set as the additional informative text in the modal dialog. Since this mechanism will be used mainly for warning users that something is awry the default icon is set to "Warning". It's possible to override the icon to one of the following settings: NoIcon, Question, Information, Warning or Critical. """ message_box = QMessageBox() message_box.setText(message) message_box.setWindowTitle(_('Mu')) if information: message_box.setInformativeText(information) if icon and hasattr(message_box, icon): message_box.setIcon(getattr(message_box, icon)) else: message_box.setIcon(message_box.Warning) message_box.setStandardButtons(message_box.Cancel | message_box.Ok) message_box.setDefaultButton(message_box.Cancel) logger.debug(message) logger.debug(information) return message_box.exec() def update_title(self, filename=None): """ Updates the title bar of the application. If a filename (representing the name of the file currently the focus of the editor) is supplied, append it to the end of the title. """ title = self.title if filename: title += ' - ' + filename self.setWindowTitle(title) def autosize_window(self): """ Makes the editor 80% of the width*height of the screen and centres it. """ screen = QDesktopWidget().screenGeometry() w = int(screen.width() * 0.8) h = int(screen.height() * 0.8) self.resize(w, h) size = self.geometry() self.move((screen.width() - size.width()) / 2, (screen.height() - size.height()) / 2) def reset_annotations(self): """ Resets the state of annotations on the current tab. """ self.current_tab.reset_annotations() def annotate_code(self, feedback, annotation_type): """ Given a list of annotations about the code in the current tab, add the annotations to the editor window so the user can make appropriate changes. """ self.current_tab.annotate_code(feedback, annotation_type) def show_annotations(self): """ Show the annotations added to the current tab. """ self.current_tab.show_annotations() def setup(self, breakpoint_toggle, theme): """ Sets up the window. Defines the various attributes of the window and defines how the user interface is laid out. """ self.theme = theme self.breakpoint_toggle = breakpoint_toggle # Give the window a default icon, title and minimum size. self.setWindowIcon(load_icon(self.icon)) self.update_title() self.read_only_tabs = False self.setMinimumSize(800, 400) self.widget = QWidget() widget_layout = QVBoxLayout() self.widget.setLayout(widget_layout) self.button_bar = ButtonBar(self.widget) self.tabs = FileTabs() self.tabs.setMovable(True) self.setCentralWidget(self.tabs) self.status_bar = StatusBar(parent=self) self.setStatusBar(self.status_bar) self.addToolBar(self.button_bar) self.show() self.autosize_window() def resizeEvent(self, resizeEvent): """ Respond to window getting too small for the button bar to fit well. """ size = resizeEvent.size() self.button_bar.set_responsive_mode(size.width(), size.height()) def select_mode(self, modes, current_mode, theme): """ Display the mode selector dialog and return the result. """ mode_select = ModeSelector() mode_select.setup(modes, current_mode, theme) mode_select.exec() try: return mode_select.get_mode() except Exception as ex: return None def change_mode(self, mode): """ Given a an object representing a mode, recreates the button bar with the expected functionality. """ self.button_bar.change_mode(mode) # Update the autocomplete / tooltip APIs for each tab to the new mode. api = mode.api() for widget in self.widgets: widget.set_api(api) def set_usb_checker(self, duration, callback): """ Sets up a timer that polls for USB changes via the "callback" every "duration" seconds. """ self.usb_checker = QTimer() self.usb_checker.timeout.connect(callback) self.usb_checker.start(duration * 1000) def set_timer(self, duration, callback): """ Set a repeating timer to call "callback" every "duration" seconds. """ self.timer = QTimer() self.timer.timeout.connect(callback) self.timer.start(duration * 1000) # Measured in milliseconds. def stop_timer(self): """ Stop the repeating timer. """ if self.timer: self.timer.stop() self.timer = None def connect_tab_rename(self, handler, shortcut): """ Connect the double-click event on a tab and the keyboard shortcut to the referenced handler (causing the Save As dialog). """ self.tabs.shortcut = QShortcut(QKeySequence(shortcut), self) self.tabs.shortcut.activated.connect(handler) self.tabs.tabBarDoubleClicked.connect(handler) def open_directory_from_os(self, path): """ Given the path to a directoy, open the OS's built in filesystem explorer for that path. Works with Windows, OSX and Linux. """ if sys.platform == 'win32': # Windows os.startfile(path) elif sys.platform == 'darwin': # OSX os.system('open "{}"'.format(path)) else: # Assume freedesktop.org on unix-y. os.system('xdg-open "{}"'.format(path))
class SerialSimulate(QObject): ''' class SerialSimulate ''' stateChanged = QtCore.pyqtSignal(str) serialPortError = QtCore.pyqtSignal(QSerialPort.SerialPortError, str) def __init__(self, parent = None): super(SerialSimulate, self).__init__(parent) self.setObjectName('SerialSimulate') # self._currIndex = 0 self._currFrameId = 0 self._frameSize = 0 self._streamBuff = [] self._newBuff = [0] * 4096 self._pkgBuff = [0] * 100 self._serialSend = SerialSend() self._serialRecv = SerialRecv() self._serialConfig = SerialPortConfig() self._serialPort = QSerialPort(self) # self._serialPort.error.connect(self.onSerialPortError) self._serialPort.readyRead.connect(self.readData) # self._serialPort.setPortName('COM5') if self._serialPort.open(QIODevice.ReadWrite): self._serialPort.setBaudRate(QSerialPort.Baud115200) self._serialPort.setDataBits(QSerialPort.Data8) self._serialPort.setParity(QSerialPort.OddParity) self._serialPort.setStopBits(QSerialPort.OneStop) self.stateChanged.emit('Open') # self._serialRecv.lMBrakeP = SerialPortProxy.swapUint16(0) self._serialRecv.rMBrakeP = SerialPortProxy.swapUint16(0) self._serialRecv.lABrakeP = SerialPortProxy.swapUint16(5) self._serialRecv.rABrakeP = SerialPortProxy.swapUint16(5) self._serialRecv.lMRotateP = SerialPortProxy.swapUint16(0) self._serialRecv.rMRotateP = SerialPortProxy.swapUint16(0) self._serialRecv.lARotateP = SerialPortProxy.swapUint16(5) self._serialRecv.rARotateP = SerialPortProxy.swapUint16(5) self._serialRecv.lWheelSpd = self.convertToASCII(100) self._serialRecv.rWheelSpd = self.convertToASCII(100) # self._timerId = self.startTimer(100, Qt.PreciseTimer) @QtCore.pyqtSlot(QSerialPort.SerialPortError, str) def onSerialPortError(self, error): print('SerialPort open failed!, %d' % error) self.serialPortError.emit(error, 'No error' if error == QSerialPort.NoError else 'Device not found' if error == QSerialPort.DeviceNotFoundError else 'Permission error' if error == QSerialPort.PermissionError else 'Open error' if error == QSerialPort.OpenError else 'Parity error' if error == QSerialPort.ParityError else 'Framing error' if error == QSerialPort.FramingError else 'Break Condition error' if error == QSerialPort.BreakConditionError else 'Write error' if error == QSerialPort.WriteError else 'Read error' if error == QSerialPort.ReadError else 'Resource error' if error == QSerialPort.ResourceError else 'Unsupported operation' if error == QSerialPort.UnsupportedOperationError else 'Unknown error' if error == QSerialPort.UnknownError else 'Timeout' if error == QSerialPort.TimeoutError else 'Not open' if error == QSerialPort.NotOpenError else '%d' % error) @QtCore.pyqtSlot() def start(self): if self._serialPort.isOpen(): self._serialPort.close() # config serialport properties self._serialPort.setPortName(self._serialConfig.port) if self._serialPort.open(QIODevice.ReadWrite): self._serialPort.setBaudRate(self._serialConfig.baudRate) self._serialPort.setDataBits(self._serialConfig.dataBits) self._serialPort.setParity(self._serialConfig.parity) self._serialPort.setStopBits(self._serialConfig.stopBits) self.stateChanged.emit('Open') @QtCore.pyqtSlot() def stop(self): if self._serialPort.isOpen(): self._serialPort.close() self.stateChanged.emit('Close') @QtCore.pyqtSlot() def save(self): self.setProperty('portState', self._serialPort.isOpen()) self.stop() @QtCore.pyqtSlot() def restore(self): self.start() if bool(self.property('portState')) else self.stop() @QtCore.pyqtSlot(SerialRecv) def writeData(self, data): if not self._serialPort.isOpen(): # warning... self.killTimer(self._timerId) return 0 return int(self._serialPort.write(data.pack())) @QtCore.pyqtSlot() def readData(self): self._streamBuff = self._serialPort.read(4096) self.unpack() return self._streamBuff.__len__() def unpack(self): for (i, value) in enumerate(self._streamBuff): if self._currIndex < self._serialSend._offset_length: # 1.frame-header self._frameSize = 0 if value == self._serialSend._headers[self._currIndex]: self._newBuff[self._currIndex] = value self._currIndex += 1 else: self._currIndex = 0 continue elif self._currIndex == self._serialSend._offset_length: # 2.frame-length if value == self._serialSend.length: pass else: self._currIndex = 0 continue self._frameSize = value self._newBuff[i] = value self._currIndex += 1 continue elif self._currIndex == self._serialSend._offset_index: # 3.frame-index self._currFrameId = value self._newBuff[i] = value self._currIndex += 1 continue elif self._currIndex < self._frameSize: # 4.frame-data self._newBuff[i] = value self._currIndex += 1 if self._currIndex == self._frameSize: # receive a full frame successfully # 5.frame-sum s = 0 for index in range(0, self._serialSend._offset_sum): s = (s + self._newBuff[index]) & 0xff if self._newBuff[self._serialSend._offset_sum] != s: self._currIndex = 0 # continue # invalid frame # 6.frame-tail if self._newBuff[self._serialSend._offset_tail] != int(self._serialSend.tail): self._currIndex = 0 # invalid frame continue # 7.save as... self._pkgBuff = self._newBuff[0:self._frameSize] # 8.dispatch self.dispatch() # 9.reset self._currIndex = 0 def dispatch(self): # save as... self._serialSend.unpack(bytes(self._pkgBuff)) # send self._serialRecv.lWheelSpd = self.convertToASCII(int(self._serialSend.lWheelSpd / 42.94967296)) self._serialRecv.rWheelSpd = self.convertToASCII(int(self._serialSend.rWheelSpd / 42.94967296)) self._serialRecv.sum = SerialPortProxy.serialPortRecvSum(self._serialRecv) self.writeData(self._serialRecv) def timerEvent(self, event): step = 1 if event.timerId() == self._timerId: self._serialRecv.index += 1 if self._serialSend.ctrlWord.lPowerSw: self._serialRecv.lMBrakeP = self.stepInc(self._serialRecv.lMBrakeP, step, 30) self._serialRecv.lABrakeP = self.stepInc(self._serialRecv.lABrakeP, step, 30) self._serialRecv.lMRotateP = self.stepInc(self._serialRecv.lMRotateP, step, 30) self._serialRecv.lARotateP = self.stepInc(self._serialRecv.lARotateP, step, 30) self._serialRecv.lWheelSpd = self.stepInc(self._serialRecv.lWheelSpd, step, 3000) if self._serialSend.ctrlWord.rPowerSw: self._serialRecv.rMBrakeP = self.stepInc(self._serialRecv.rMBrakeP, step, 30) self._serialRecv.rABrakeP = self.stepInc(self._serialRecv.rABrakeP, step, 30) self._serialRecv.rMRotateP = self.stepInc(self._serialRecv.rMRotateP, step, 30) self._serialRecv.rARotateP = self.stepInc(self._serialRecv.rARotateP, step, 30) self._serialRecv.rWheelSpd = self.stepInc(self._serialRecv.rWheelSpd, step, 3000) self._serialRecv.sum = SerialPortProxy.serialPortRecvSum(self._serialRecv) self.writeData(self._serialRecv) @staticmethod def stepWheelSpd(value, step, maxValue): value = SerialPortProxy.convertFromASCII(value) + step if value > maxValue: value = 0 return SerialSimulate.convertToASCII(value) @staticmethod def convertToASCII(value): return value @staticmethod def stepInc(value, step, maxValue): value = SerialPortProxy.swapUint16(value) + step # + random() % 50 if value > maxValue: value = 0 return SerialPortProxy.swapUint16(value)
def __init__(self, parent=None): super(SerialPortProxy, self).__init__(parent) self.setObjectName("SerialPortProxy") # self._currIndex = 0 self._currFrameId = 0 self._frameSize = 0 self._streamBuff = [] self._newBuff = [0] * 4096 self._pkgBuff = [0] * 100 self._serialRecv = SerialRecv() self._serialConfig = SerialPortConfig() self._serialPort = QSerialPort(self) # self._serialPort.error.connect(self.onSerialPortError) self._serialPort.readyRead.connect(self.readData) # self._serialSimulate = None # SerialSimulate(self) # read configuration settings = QSettings(self) # group - serialport properties settings.beginGroup("Settings/" + self.objectName() + "/SerialPort") self._serialConfig.port = settings.value("port", "COM1") infolist = settings.value("info", "115200-8-N-1").split("-") self._serialConfig.baudRate = int(infolist[0]) dataBits = int(infolist[1]) self._serialConfig.dataBits = ( QSerialPort.Data5 if dataBits == 5 else QSerialPort.Data6 if dataBits == 6 else QSerialPort.Data7 if dataBits == 7 else QSerialPort.Data8 if dataBits == 8 else QSerialPort.Data8 ) parity = infolist[2][0].upper() self._serialConfig.parity = ( QSerialPort.NoParity if parity == "N" else QSerialPort.EvenParity if parity == "E" else QSerialPort.OddParity if parity == "O" else QSerialPort.SpaceParity if parity == "S" else QSerialPort.MarkParity if parity == "M" else QSerialPort.NoParity ) stopBits = int(float(infolist[3]) * 10) self._serialConfig.stopBits = ( QSerialPort.OneStop if stopBits == 10 else QSerialPort.OneAndHalfStop if stopBits == 15 else QSerialPort.TwoStop if stopBits == 20 else QSerialPort.OneStop ) settings.endGroup()
class REPLPane(QTextEdit): """ REPL = Read, Evaluate, Print, Loop. This widget represents a REPL client connected to a BBC micro:bit. """ def __init__(self, port, parent=None): super().__init__(parent) self.setAcceptRichText(False) self.setReadOnly(False) self.setLineWrapMode(QTextEdit.NoWrap) self.setObjectName("replpane") # A flag to indicate that we've sent some sort of escape # character e.g. \b self.escape_flag = False # open the serial port self.serial = QSerialPort(self) self.serial.setPortName(port) self.serial.setBaudRate(115200) print(self.serial.open(QIODevice.ReadWrite)) self.serial.readyRead.connect(self.on_serial_read) # clear the text self.clear() def on_serial_read(self): self.append(self.serial.readAll()) def keyPressEvent(self, data): self.escape_flag = False text = data.text() msg = bytes(text, "utf8") key = data.key() if key == Qt.Key_Backspace: msg = "\b" self.delete() self.escape_flag = True elif key == Qt.Key_Up: msg = "\x1B[A" elif key == Qt.Key_Down: msg = "\x1B[B" self.serial.write(msg) def append(self, data): txt = str(data, "utf8") if self.escape_flag: return tc = self.textCursor() tc.movePosition(QTextCursor.End) self.setTextCursor(tc) self.insertPlainText(txt) self.ensureCursorVisible() def delete(self): tc = self.textCursor() block_text = tc.block().text() if not (block_text.startswith(">>> ") or block_text.startswith("... ")): return if block_text in [">>> ", "... "]: return tc.deletePreviousChar() def clear(self): self.setText("") def kill(self): if self.serial.isOpen(): self.serial.close()