class Comm(): def __init__(self, address, port): self.block = 0 self.port = port self.delimiter = bytes('x', 'utf-8') self.address = address self.block = bytearray() self.initialize(address, port) def initialize(self, address, port): self.socket = QTcpSocket() self.socket.connectToHost(self.address, self.port) def decode(self, data): return data.decode('utf-8').replace('\x00', '').rsplit() def read(self): self.size = self.socket.bytesAvailable() self.block += self.socket.read(self.size) def get_data(self): if (self.delimiter in self.block): data = self.block[0:self.block.index(self.delimiter)] data = list(map(int, self.decode(data))) self.block = self.block[self.block.index(self.delimiter) + 1:-1] return data def send(self, data): self.socket.write(bytearray(data, 'utf-8')) def disconnect(self): self.socket.close()
def exchangeData(self): if not checkIPAddress(ip_line_edit.text()): raise Exception("ERROR IP-address format") tcp_socket = QTcpSocket() tcp_socket.connectToHost(ip_line_edit.text(), 80, QIODevice.ReadWrite) self.update.emit( f"Connecting to {tcp_socket.peerAddress().toString()}:{tcp_socket.peerPort()}" ) if not tcp_socket.waitForConnected(5000): raise Exception(f"ERROR connecting to {ip_line_edit.text()}:80") tcp_socket.waitForReadyRead(5000) arduino_state: bytes = b"" while tcp_socket.bytesAvailable() > 0: arduino_state += tcp_socket.readAll().data() print(arduino_state) arduino_state = arduino_state.decode() if ("+" not in arduino_state): raise Exception(f"ERROR incomplete read") self.updateState(arduino_state) tcp_socket.write((self.getState() + "+\n").encode("utf-8")) tcp_socket.flush() if tcp_socket.bytesToWrite() > 0: raise Exception(f"ERROR incomplete write") tcp_socket.disconnectFromHost() tcp_socket.close()
def __init__(self, sock_type='TCP Client', ip='127.0.0.1', port=2007): '''打开网络设备,建立连接 ## sock_type: - 'TCP Client' - 'TCP Server' - 'UDP' ''' self.sock_type = sock_type # self.ip = ip self.port = port if sock_type == 'TCP Client': tcp_client = QTcpSocket() tcp_client.connectToHost(ip, port) self.sock = tcp_client elif sock_type == 'TCP Server': tcp_server = QTcpServer() tcp_server.listen(QHostAddress(ip), port) self.sock = tcp_server elif sock_type == 'UDP': udp = QUdpSocket() udp.bind(QHostAddress(ip), port) self.sock = udp else: print('Unkonw sock_type=%r' % sock_type)
def get_ip_mac_pinged(ip): """ Returns a list [ip,mac,pinged] """ pinged = True mac = None sock = QTcpSocket() sock.connectToHost(ip, 80) sock.close() #ARP if pinged == True: if platform_system() == "Windows": CREATE_NO_WINDOW = 0x08000000 arpexit = subprocess.check_output( ["arp", "-a", ip], creationflags=CREATE_NO_WINDOW) for s in arpexit.split(b" "): if len(s) == 17 and s.find(b"-") != -1: mac = s.decode().replace("-", ":").upper() else: arpexit = subprocess.check_output(["arp", ip]) for s in arpexit.decode('utf-8').split(" "): if len(s) == 17 and s.find(":") != -1: mac = s.upper() return (ip, mac, pinged)
class TcpClient(QWidget): recvDataReady = pyqtSignal(bytes) def __init__(self): super(TcpClient, self).__init__() self.tcpClient = QTcpSocket() self.initUI() # self.signalSlot() def initUI(self): mainLayout = QVBoxLayout() mainLayout.addWidget(self.paraUI()) self.setLayout(mainLayout) def paraUI(self): groupBox = QGroupBox('参数设置') # self.masterIP = QLineEdit('192.168.1.166') self.serverIP = QLineEdit('192.168.0.1') self.serverIP.setInputMask('000.000.000.000') self.serverIP.setToolTip('需要连接到Server的IP地址') self.serverPort = QLineEdit('2111') self.serverPort.setToolTip('需要连接到Server的端口') form = QFormLayout() form.addRow('Server IP地址:', self.serverIP) form.addRow('Server 端口号:', self.serverPort) self.linkRbtn = QRadioButton() mainLayout = QVBoxLayout() mainLayout.addLayout(form) mainLayout.addWidget(self.linkRbtn) mainLayout.addStretch(1) mainLayout.setAlignment(self.linkRbtn, Qt.AlignHCenter) groupBox.setLayout(mainLayout) return groupBox # # def signalSlot(self): # self.linkRbtn.clicked.connect(self.ctrlTcpStatus) # self.linkRbtn.clicked.connect(self.currentStatus) # self.tcpClient.connected.connect(self.hasConnected) # self.tcpClient.disconnected.connect(self.hasClosed) # self.tcpClient.readyRead.connect(self.processTcpClientDatagrams) @pyqtSlot() def ctrlTcpStatus(self): if self.linkRbtn.isChecked(): # self.tcpClient.connectToHost(self.serverIP.text(), int(self.serverPort.text())) self.tcpClient.connectToHost('192.168.0.1', 2111, QIODevice.ReadWrite) self.tcpClient.waitForConnected(1000) else: self.tcpClient.disconnectFromHost()
class TcpClient(QObject): finished = pyqtSignal() connected = pyqtSignal() connectionLost = pyqtSignal() interpretCmd = pyqtSignal(str) def __init__(self): super(TcpClient, self).__init__() self.__tcp_socket = None self.connectionLost.connect(self.finished) self.connectionLost.connect( lambda: print('## Disconnected from the robot ##')) @pyqtSlot() def start_client(self): print(f'## Connecting to robot at IP: {WIFI_IP}, PORT: {WIFI_PORT} ##') self.__tcp_socket = QTcpSocket() self.__tcp_socket.disconnected.connect(self.connectionLost) self.__tcp_socket.readyRead.connect(self.read_ready) self.__tcp_socket.connected.connect(self.connected) self.__tcp_socket.connectToHost(WIFI_IP, WIFI_PORT) if not self.__tcp_socket.waitForConnected(TIMEOUT_MSEC): print( f'## Timeout! {TIMEOUT_MSEC/1000}s has passed and it still hasn\'t connect ##' ) self.__tcp_socket.disconnectFromHost() self.finished.emit() else: print( f'## Connected to robot at IP: {WIFI_IP}, PORT: {WIFI_PORT} ##' ) def stop_client(self): if self.__tcp_socket is not None: self.__tcp_socket.disconnectFromHost() self.finished.emit() @pyqtSlot() def read_ready(self): try: data = self.__tcp_socket.readAll() self.interpretCmd.emit(str(data, "utf-8").strip()) except Exception as err: print(f'tcpClient::read_ready() error msg: {err}') @pyqtSlot(str) def send_message(self, payload): try: # Example message: 'FP|tr' # self.__tcp_socket.write(QByteArray().append(json.dumps({'target': 'ARD', 'payload': 'hi'}))) self.__tcp_socket.write(QByteArray().append(payload)) # self.__tcp_socket.flush() except Exception as err: print(f'tcpClient::send_message() error msg: {err}')
def connect(self, host, port): if self._server: raise RuntimeError( 'MeetingServer: Must call either listen, or connect, not both') from PyQt5.QtNetwork import QTcpSocket socket = QTcpSocket() def socket_error(error_type, self=self, socket=socket): self._socket_error(error_type, socket) socket.error.connect(socket_error) socket.connectToHost(host, port) self._add_connection(socket) self._session.logger.status('Waiting for scene data from meeting host')
class SocketTest(QObject): def __init__(self, parent=None): super(SocketTest, self).__init__(parent) def connect(self): self.socket = QTcpSocket(self) self.socket.connectToHost(IP, PORT) if self.socket.waitForConnected(3000): print('Connected') self.socket.waitForReadyRead(3000) print(self.socket.bytesAvailable(), self.socket.readAll()) else: print('Not Connected')
class TcpClient(QWidget, Ui_Form): def __init__(self): super(TcpClient, self).__init__() self.ui = Ui_Form() self.ui.setupUi(self) self.tcpSocket = QTcpSocket(self) self.ui.connectButton.clicked.connect(self.buttonConnect) self.tcpSocket.connected.connect(self.sucessConnect) self.ui.sendButton.clicked.connect(self.sendMessage) self.tcpSocket.readyRead.connect(self.showMessage) self.ui.closeButton.clicked.connect(self.closeConnect) def buttonConnect(self): ip = self.ui.IPLineEdit.text() port = self.ui.portLineEdit.text() self.tcpSocket.connectToHost(QHostAddress(ip), int(port)) def sucessConnect(self): self.ui.showText.setText("成功和服务器建立连接") def sendMessage(self): message = self.ui.sendText.toPlainText() # self.communication = QByteArray() # stream = QDataStream(self.communication, QIODevice.WriteOnly) # stream.writeQString(message) # self.tcpSocket.write(self.communication) # self.ui.sendText.clear() message = message.encode(encoding='utf-8') self.tcpSocket.write(message) self.ui.sendText.clear() def showMessage(self): # stream = QDataStream(self.tcpSocket) # stream.setVersion(QDataStream.Qt_5_10) # message = stream.readQString() # self.ui.showText.append(message) self.message = QByteArray() self.message = self.tcpSocket.readAll() self.message = str(self.message, encoding='utf-8') #找遍世界,终于找到可用的方法 print(self.message) self.ui.showText.append(self.message) def closeConnect(self): self.tcpSocket.disconnectFromHost() self.tcpSocket.close()
class MyClientThread(QThread): def __init__(self, ip, port): super(MyClientThread, self).__init__() self.ip = ip self.port = port def run(self): print("新连接进入") self.clientSocket = QTcpSocket() self.clientSocket.connectToHost(QHostAddress(self.ip), self.port) clientSocketList.append((self.clientSocket, self.ip, self.port)) self.clientSocket.connected.connect(lambda: print("连接成功")) self.clientSocket.readyRead.connect(lambda:self.handle_read(self.clientSocket),Qt.DirectConnection) self.clientSocket.disconnected.connect(self.dealDisconnected,Qt.DirectConnection) self.exec() def handle_read(self,socket): msg = socket.readAll() print(msg) self.handle_write() def handle_write(self): for socket, ip, port in clientSocketList: socket.write("郑兵".encode("utf-8")) def handle_runing_single(self, str): print(str) def dealDisconnected(self): print("断开连接") self.clientSocket.disconnectFromHost() self.clientSocket.close() self.clientSocket.deleteLater() def winClose(self): print("主窗口关闭了") for socket,ip,port in clientSocketList: print(socket) # self.clientSocket.disconnectFromHost() # self.clientSocket.close() # self.deleteLater() clientSocketList.clear()
class TcpClient(QObject): def __init__(self, socket=None): super(TcpClient, self).__init__() self.is_connected = False if socket is None: self.socket = QTcpSocket() else: self.socket = socket self.socket.error.connect(self.error) self.socket.connected.connect(self.connected) self.socket.disconnected.connect(self.disconnected) self.socket.readyRead.connect(self.readyRead) @pyqtSlot() def error(self): print self.socket.errorString() @pyqtSlot() def connected(self): self.is_connected = True print 'TcpClient connected' @pyqtSlot() def disconnected(self): self.is_connected = False print 'TcpClient disconnected' @pyqtSlot() def readyRead(self): data = self.socket.readAll() self.parse_data(data) def connectToHost(self, host, port): print 'Trying to connect to host', host, 'at port', port self.socket.connectToHost(host, port) def disconnectFromHost(self): self.socket.disconnectFromHost() def write(self, buf): self.socket.write(buf) def parse_data(self, data): # Placeholder function; override it with your own implementation print str(data).strip()
class Client(QObject): def __init__(self, parent=None): super().__init__(parent) self.log = logging.getLogger(__name__) self._socket_setup() def _socket_setup(self): self.socket = QTcpSocket(self) self.socket.setSocketOption(QTcpSocket.KeepAliveOption, 1) self.socket.connected.connect(self.on_connected) self.socket.disconnected.connect(self.on_disconnected) self.socket.readyRead.connect(self.on_readyRead) self.socket.error.connect(self.on_error) self.socket.stateChanged.connect(self.on_stateChanged) def connect(self, host=HOST, port=PORT): if not self.socket.isOpen(): self.log.info('connecting to {}:{}'.format(host, port)) self.socket.connectToHost(QHostAddress(host), port) def disconnect(self): self.log.info('disconnecting') self.socket.disconnectFromHost() def on_readyRead(self): data = bytes() while self.socket.bytesAvailable(): data += self.socket.read(1024) self.log.debug(data) def on_connected(self): self.log.info('connected') def on_disconnected(self): self.log.info('disconnected') def on_error(self, error): self.log.error('error {}: {}'.format(error, self.socket.errorString())) def on_stateChanged(self, state): states = ['Unconnected', 'HostLookup', 'Connecting', 'Connected', 'Bound', 'Closing', 'Listening'] self.log.debug('state changed to {}'.format(states[state]))
class TcpClient(): def __init__(self, line_edit_widget=None, text_widget=None): self.line_edit = line_edit_widget self.text_widget = text_widget self.socket = QTcpSocket() # client "is a" socket def connect_server(self): print('inside connect_server') print('Port is: ' + str(SERVER_PORT)) self.socket.connectToHost(SERVER_ADDRESS, SERVER_PORT) def write_data(self): data_byte_array = QByteArray() stream = QDataStream(data_byte_array, QIODevice.WriteOnly) stream.setVersion(QDataStream.Qt_5_9) stream.writeUInt32(0) if self.line_edit: print('inside write_data') stream.writeQString(self.line_edit.text()) self.socket.write(data_byte_array) data_byte_array = None if self.line_edit: self.line_edit.setText("") def read_data(self): stream = QDataStream(self.socket) stream.setVersion(QDataStream.Qt_5_9) while True: if self.socket.bytesAvailable() <= 0: break stream.readUInt32() text_from_server = stream.readQString() if self.text_widget: print('display_text') print(text_from_server) self.text_widget.append(text_from_server)
def send(message='ping 1234', port=PORT): ''' Sends a raw message Trick here is that PyQt5 does not do automatic str<->byte encoding, but pya does. Also something weird with the addresses ''' payload = message + '\r\n' psock = QTcpSocket() if not isGSI(): payload = payload.encode() psock.connectToHost(localhost, port) if psock.waitForConnected(): psock.write(payload) if psock.waitForReadyRead(3000): ret = psock.readLine() if not isGSI(): ret = bytes(ret).decode('utf-8') handle_query(ret) else: raise Exception('Not acknowledged') else: print('Connection Fail! (tried {}:{})'.format(localhost, port))
def run(self): self.mutex.lock() serverName = self.hostName serverPort = self.port self.mutex.unlock() while not self.quit: Timeout = 5 * 1000 socket = QTcpSocket() socket.connectToHost(serverName, serverPort) if not socket.waitForConnected(Timeout): self.error.emit(socket.error(), socket.errorString()) return while socket.bytesAvailable() < 2: if not socket.waitForReadyRead(Timeout): self.error.emit(socket.error(), socket.errorString()) return instr = QDataStream(socket) instr.setVersion(QDataStream.Qt_4_0) blockSize = instr.readUInt16() while socket.bytesAvailable() < blockSize: if not socket.waitForReadyRead(Timeout): self.error.emit(socket.error(), socket.errorString()) return self.mutex.lock() fortune = instr.readQString() self.newFortune.emit(fortune) self.cond.wait(self.mutex) serverName = self.hostName serverPort = self.port self.mutex.unlock()
def run(self): self.mutex.lock() serverName = self.hostName serverPort = self.port self.mutex.unlock() while not self.quit: Timeout = 5 * 1000 socket = QTcpSocket() socket.connectToHost(serverName, serverPort) if not socket.waitForConnected(Timeout): self.error.emit(socket.error(), socket.errorString()) return while socket.bytesAvailable() < 2: if not socket.waitForReadyRead(Timeout): self.error.emit(socket.error(), socket.errorString()) return instr = QDataStream(socket) instr.setVersion(QDataStream.Qt_4_0) blockSize = instr.readUInt16() while socket.bytesAvailable() < blockSize: if not socket.waitForReadyRead(Timeout): self.error.emit(socket.error(), socket.errorString()) return self.mutex.lock() fortune = instr.readQString() self.newFortune.emit(fortune) self.cond.wait(self.mutex) serverName = self.hostName serverPort = self.port self.mutex.unlock()
class Client(QWidget, Ui_Form): def __init__(self): super(Client, self).__init__() self.ui = Ui_Form() self.ui.setupUi(self) self.file = QFile() self.tcpsocket = QTcpSocket() self.ui.pushButton_Connect.clicked.connect(self.ConnectToServer) self.tcpsocket.connected.connect(self.SuccessConnect) self.tcpsocket.readyRead.connect(self.HandleReceive) def ConnectToServer(self): ip = self.ui.lineEdit_IPAddress.text() port = self.ui.lineEdit_PORT.text() self.tcpsocket.connectToHost(QHostAddress(ip), int(port)) def SuccessConnect(self): self.ui.textEdit.setText("成功和服务器建立连接") def HandleReceive(self): with open('../FileRecv/test.txt', 'wb') as f: buf = self.tcpsocket.readAll() f.write(buf)
class Messenger(Messenger_Window): RANDOM_MESSAGES = ('Hello', 'How are you?', 'Hi there!', 'I’m fine, and you?', 'Your problems – my problems.', 'Hello, I’m awesome. How can I help you?', 'What’s up?', 'I was so bored. Thank you for saving me!', 'I’ve been expecting you!') def __init__(self, host, port): super().__init__() self.tcpSocket = QTcpSocket() self.blockSize = 0 self.host = host self.port = port self.jim = None self.connected = False self.chat_list = [] self.online_users = [] self.active_chat = '' self.logon() # self.last_sent_message = '' def reset_connection(self): if self.connected: self.tcpSocket.disconnect() self.jim = None self.connected = False self.chat_list = [] self.online_users = [] self.active_chat = '' self.enable_server_buttons(False) self.enable_communication_buttons(False) self.setWindowTitle('My awesome client: disconnected') self.chat_label.setText('Disconnected') def debug(self): print('chat_list=' + ','.join(self.chat_list)) print('online_users=' + ','.join(self.online_users)) print('active_chat={}'.format(self.active_chat)) try: print('username={}'.format(self.jim.username)) except: print('username is none') print('connected={}'.format(self.connected)) def logon(self): if self.connected: self.tcpSocket.disconnect() username, ok = QInputDialog.getText(self, 'Logon to chat', 'Enter your name:', QLineEdit.Normal, 'Nastya') if ok: self.jim = JimClient(username) self.enable_server_buttons(True) self.enable_communication_buttons(False) self.setWindowTitle( 'My awesome client: connected as {}'.format(username)) self.tcpSocket.connectToHost(self.host, self.port, QIODevice.ReadWrite) # self.tcpSocket.waitForConnected() self.chat_label.setText('Please join chat...') self.tcpSocket.readyRead.connect(self.read_messages) self.tcpSocket.error.connect(self.display_error) # self.tcpSocket.write(self.jim.auth()) self.tcpSocket.write(self.jim.presence()) self.connected = True # self.tcpSocket.write(self.jim.request_chat_list()) self.chat_area.clear() else: self.reset_connection() def before_exit(self): print('Exiting!') if self.jim: msg = self.jim.quit() self.tcpSocket.write(msg) time.sleep(5) print('Exiting! Message length is {}, message={}'.format( len(msg), msg)) if self.connected: self.tcpSocket.disconnectFromHost() def dialog_join_chat(self): # print(self.chat_list) if self.connected: chat, ok = QInputDialog.getItem(self, 'Доступные чаты', 'Выберите чат', self.chat_list, 0, False) if ok and chat: self.chat_label.setText('Active Chat: ' + chat) msg = self.jim.join_chat(chat) self.tcpSocket.write(msg) self.chat_area.clear() self.enable_communication_buttons(True) self.active_chat = chat def dialog_contact_user(self): # print(self.chat_list) if self.connected: user, ok = QInputDialog.getItem(self, 'Пользователи онлайн', 'Выберите пользователя', self.online_users, 0, False) if ok and user: self.chat_label.setText('Dialog with ' + user) self.chat_area.clear() self.enable_communication_buttons(True) self.active_chat = user def random_message(self): message = self.RANDOM_MESSAGES[random.randint( 0, len(self.RANDOM_MESSAGES) - 1)] self.message_area.clear() self.message_area.setText(message) self.send() def read_messages(self): data = self.tcpSocket.readAll().data() if data: received_messages = self.jim.unpack(data) for msg in received_messages: server_resp = self.jim.parse_server_message(msg) if 'response' in server_resp: print('received server message {} "{}"'.format( server_resp['response'], server_resp['alert'])) if server_resp['response'] in (200, 201): # everything OK # self.chat_area.append(time.strftime("%Y-%m-%d %H:%M", time.localtime(server_resp['time']))) # self.chat_area.append('{}: {}'.format(self.jim.username, self.last_sent_message)) pass elif server_resp['response'] == 203: # a user is online if not server_resp['username'] in self.online_users: self.online_users.append(server_resp['username']) elif server_resp[ 'response'] == 204: # a user has joined chat if self.active_chat == server_resp['chat']: # redColor = QColor(255, 0, 0) # blackColor = QColor(0, 0, 0) # tmpFont = QFont('Arial', pointSize=10, weight=400) # self.chat_area.setTextColor(redColor) # self.chat_area.setFont(tmpFont) self.chat_area.append( time.strftime( "%Y-%m-%d %H:%M", time.localtime(server_resp['time']))) self.chat_area.append( '{} has joined this chat'.format( server_resp['username'])) # self.chat_area.setFont(self.font) # self.chat_area.setTextColor(blackColor) elif server_resp['response'] == 215: # received chat list self.chat_list = server_resp['chat_list'].split(',') elif server_resp['response'] == 216: # received users list self.online_users = server_resp['user_list'].split(',') elif server_resp['response'] >= 400: # received an error self.chat_area.append( time.strftime("%Y-%m-%d %H:%M", time.localtime(server_resp['time']))) self.chat_area.append(server_resp['alert']) elif 'message' in server_resp: # received a message if self.chat_area.toPlainText( ) == 'В чат пока ничего не написали': self.chat_area.clear() # display if it is a history message if 'archive' in server_resp: self.display_message(server_resp) # if message to current chat or dialog then display it elif (server_resp['from'] == self.active_chat and server_resp['to'] == self.jim.username) or \ (self.active_chat == server_resp['to']) : self.display_message(server_resp) print('received message {}'.format(server_resp)) else: print('something wrong in read_messages {}'.format(msg)) def display_message(self, server_resp): self.chat_area.append( time.strftime("%Y-%m-%d %H:%M", time.localtime(server_resp['time']))) self.chat_area.append('{}: {}'.format(server_resp['from'], server_resp['message'])) def display_error(self): self.chat_area.append(time.strftime("%Y-%m-%d %H:%M", time.localtime())) self.chat_area.append('Connection error') self.reset_connection() def send(self): # message_html = self.message_area.toHtml() message_txt = self.message_area.toPlainText() msg_len = len(message_txt) if msg_len > 512: self.errorMessageDialog.showMessage( 'Warning: Message {} bytes too long, max 512'.format(msg_len)) elif not message_txt: pass else: message_json_packed = self.jim.message(self.active_chat, message_txt) self.tcpSocket.write(message_json_packed) if self.active_chat != self.jim.username and self.active_chat in self.online_users: self.display_message({ 'from': self.jim.username, 'message': message_txt, 'time': time.time() }) self.message_area.clear() self.message_area.setFocus()
class IrcWidget(QWidget, Ui_IrcWidget): """ Class implementing the IRC window. @signal autoConnected() emitted after an automatic connection was initiated """ autoConnected = pyqtSignal() ServerDisconnected = 1 ServerConnected = 2 ServerConnecting = 3 def __init__(self, parent=None): """ Constructor @param parent reference to the parent widget (QWidget) """ super(IrcWidget, self).__init__(parent) self.setupUi(self) from .IrcNetworkManager import IrcNetworkManager self.__ircNetworkManager = IrcNetworkManager(self) self.__leaveButton = QToolButton(self) self.__leaveButton.setIcon( UI.PixmapCache.getIcon("ircCloseChannel.png")) self.__leaveButton.setToolTip( self.tr("Press to leave the current channel")) self.__leaveButton.clicked.connect(self.__leaveChannel) self.__leaveButton.setEnabled(False) self.channelsWidget.setCornerWidget( self.__leaveButton, Qt.BottomRightCorner) self.channelsWidget.setTabsClosable(False) if not isMacPlatform(): self.channelsWidget.setTabPosition(QTabWidget.South) height = self.height() self.splitter.setSizes([height * 0.6, height * 0.4]) self.__channelList = [] self.__channelTypePrefixes = "" self.__userName = "" self.__identityName = "" self.__quitMessage = "" self.__nickIndex = -1 self.__nickName = "" self.__server = None self.__registering = False self.__connectionState = IrcWidget.ServerDisconnected self.__sslErrorLock = False self.__buffer = "" self.__userPrefix = {} self.__socket = None if SSL_AVAILABLE: self.__sslErrorHandler = E5SslErrorHandler(self) else: self.__sslErrorHandler = None self.__patterns = [ # :[email protected] PRIVMSG bar_ :some long message (re.compile(r":([^!]+)!([^ ]+)\sPRIVMSG\s([^ ]+)\s:(.*)"), self.__query), # :foo.bar.net COMMAND some message (re.compile(r""":([^ ]+)\s+([A-Z]+)\s+(.+)"""), self.__handleNamedMessage), # :foo.bar.net 123 * :info (re.compile(r""":([^ ]+)\s+(\d{3})\s+(.+)"""), self.__handleNumericMessage), # PING :ping message (re.compile(r"""PING\s+:(.*)"""), self.__ping), ] self.__prefixRe = re.compile(r""".*\sPREFIX=\((.*)\)([^ ]+).*""") self.__chanTypesRe = re.compile(r""".*\sCHANTYPES=([^ ]+).*""") ircPic = UI.PixmapCache.getPixmap("irc128.png") self.__emptyLabel = QLabel() self.__emptyLabel.setPixmap(ircPic) self.__emptyLabel.setAlignment(Qt.AlignVCenter | Qt.AlignHCenter) self.channelsWidget.addTab(self.__emptyLabel, "") # all initialized, do connections now self.__ircNetworkManager.dataChanged.connect(self.__networkDataChanged) self.networkWidget.initialize(self.__ircNetworkManager) self.networkWidget.connectNetwork.connect(self.__connectNetwork) self.networkWidget.editNetwork.connect(self.__editNetwork) self.networkWidget.joinChannel.connect(self.joinChannel) self.networkWidget.nickChanged.connect(self.__changeNick) self.networkWidget.sendData.connect(self.__send) self.networkWidget.away.connect(self.__away) self.networkWidget.autoConnected.connect(self.autoConnected) def shutdown(self): """ Public method to shut down the widget. @return flag indicating successful shutdown (boolean) """ if self.__server: if Preferences.getIrc("AskOnShutdown"): ok = E5MessageBox.yesNo( self, self.tr("Disconnect from Server"), self.tr( """<p>Do you really want to disconnect from""" """ <b>{0}</b>?</p><p>All channels will be closed.""" """</p>""").format(self.__server.getName())) else: ok = True if ok: self.__connectNetwork("", False, True) else: ok = True if ok: self.__ircNetworkManager.close() return ok def autoConnect(self): """ Public method to initiate the IRC auto connection. """ self.networkWidget.autoConnect() def __connectNetwork(self, name, connect, silent): """ Private slot to connect to or disconnect from the given network. @param name name of the network to connect to (string) @param connect flag indicating to connect (boolean) @param silent flag indicating a silent connect/disconnect (boolean) """ if connect: network = self.__ircNetworkManager.getNetwork(name) if network: self.__server = network.getServer() self.__identityName = network.getIdentityName() identity = self.__ircNetworkManager.getIdentity( self.__identityName) if identity: self.__userName = identity.getIdent() self.__quitMessage = identity.getQuitMessage() if self.__server: useSSL = self.__server.useSSL() if useSSL and not SSL_AVAILABLE: E5MessageBox.critical( self, self.tr("SSL Connection"), self.tr( """An encrypted connection to the IRC""" """ network was requested but SSL is not""" """ available. Please change the server""" """ configuration.""")) return if useSSL: # create SSL socket self.__socket = QSslSocket(self) self.__socket.encrypted.connect( self.__hostConnected) self.__socket.sslErrors.connect( self.__sslErrors) else: # create TCP socket self.__socket = QTcpSocket(self) self.__socket.connected.connect( self.__hostConnected) self.__socket.hostFound.connect( self.__hostFound) self.__socket.disconnected.connect( self.__hostDisconnected) self.__socket.readyRead.connect( self.__readyRead) self.__socket.error.connect( self.__tcpError) self.__connectionState = IrcWidget.ServerConnecting if useSSL: self.networkWidget.addServerMessage( self.tr("Info"), self.tr("Looking for server {0} (port {1})" " using an SSL encrypted connection" "...").format(self.__server.getName(), self.__server.getPort())) self.__socket.connectToHostEncrypted( self.__server.getName(), self.__server.getPort() ) else: self.networkWidget.addServerMessage( self.tr("Info"), self.tr( "Looking for server {0} (port {1})...") .format( self.__server.getName(), self.__server.getPort())) self.__socket.connectToHost( self.__server.getName(), self.__server.getPort()) else: if silent: ok = True else: ok = E5MessageBox.yesNo( self, self.tr("Disconnect from Server"), self.tr("""<p>Do you really want to disconnect from""" """ <b>{0}</b>?</p><p>All channels will be""" """ closed.</p>""") .format(self.__server.getName())) if ok: if self.__server is not None: self.networkWidget.addServerMessage( self.tr("Info"), self.tr("Disconnecting from server {0}...").format( self.__server.getName())) elif name: self.networkWidget.addServerMessage( self.tr("Info"), self.tr("Disconnecting from network {0}...").format( name)) else: self.networkWidget.addServerMessage( self.tr("Info"), self.tr("Disconnecting from server.")) self.__closeAllChannels() self.__send("QUIT :" + self.__quitMessage) if self.__socket: self.__socket.flush() self.__socket.close() if self.__socket: # socket is still existing self.__socket.deleteLater() self.__socket = None self.__userName = "" self.__identityName = "" self.__quitMessage = "" def __editNetwork(self, name): """ Private slot to edit the network configuration. @param name name of the network to edit (string) """ from .IrcNetworkListDialog import IrcNetworkListDialog dlg = IrcNetworkListDialog(self.__ircNetworkManager, self) dlg.exec_() def __networkDataChanged(self): """ Private slot handling changes of the network and identity definitions. """ identity = self.__ircNetworkManager.getIdentity(self.__identityName) if identity: partMsg = identity.getPartMessage() for channel in self.__channelList: channel.setPartMessage(partMsg) def joinChannel(self, name, key=""): """ Public slot to join a channel. @param name name of the channel (string) @param key key of the channel (string) """ # step 1: check, if this channel is already joined for channel in self.__channelList: if channel.name() == name: return from .IrcChannelWidget import IrcChannelWidget channel = IrcChannelWidget(self) channel.setName(name) channel.setUserName(self.__nickName) identity = self.__ircNetworkManager.getIdentity(self.__identityName) if identity: channel.setPartMessage(identity.getPartMessage()) channel.setUserPrivilegePrefix(self.__userPrefix) channel.initAutoWho() channel.sendData.connect(self.__send) channel.sendCtcpRequest.connect(self.__sendCtcpRequest) channel.sendCtcpReply.connect(self.__sendCtcpReply) channel.channelClosed.connect(self.__closeChannel) channel.openPrivateChat.connect(self.__openPrivate) channel.awayCommand.connect(self.networkWidget.handleAwayCommand) channel.leaveChannels.connect(self.__leaveChannels) channel.leaveAllChannels.connect(self.__leaveAllChannels) self.channelsWidget.addTab(channel, name) self.__channelList.append(channel) self.channelsWidget.setCurrentWidget(channel) joinCommand = ["JOIN", name] if key: joinCommand.append(key) self.__send(" ".join(joinCommand)) self.__send("MODE " + name) emptyIndex = self.channelsWidget.indexOf(self.__emptyLabel) if emptyIndex > -1: self.channelsWidget.removeTab(emptyIndex) self.__leaveButton.setEnabled(True) self.channelsWidget.setTabsClosable(True) def __query(self, match): """ Private method to handle a new private connection. @param match reference to the match object @return flag indicating, if the message was handled (boolean) """ # group(1) sender user name # group(2) sender user@host # group(3) target nick # group(4) message if match.group(4).startswith("\x01"): return self.__handleCtcp(match) self.__openPrivate(match.group(1)) # the above call sets the new channel as the current widget channel = self.channelsWidget.currentWidget() channel.addMessage(match.group(1), match.group(4)) channel.setPrivateInfo( "{0} - {1}".format(match.group(1), match.group(2))) return True @pyqtSlot(str) def __openPrivate(self, name): """ Private slot to open a private chat with the given user. @param name name of the user (string) """ from .IrcChannelWidget import IrcChannelWidget channel = IrcChannelWidget(self) channel.setName(self.__nickName) channel.setUserName(self.__nickName) identity = self.__ircNetworkManager.getIdentity(self.__identityName) if identity: channel.setPartMessage(identity.getPartMessage()) channel.setUserPrivilegePrefix(self.__userPrefix) channel.setPrivate(True, name) channel.addUsers([name, self.__nickName]) channel.sendData.connect(self.__send) channel.sendCtcpRequest.connect(self.__sendCtcpRequest) channel.sendCtcpReply.connect(self.__sendCtcpReply) channel.channelClosed.connect(self.__closeChannel) channel.awayCommand.connect(self.networkWidget.handleAwayCommand) channel.leaveChannels.connect(self.__leaveChannels) channel.leaveAllChannels.connect(self.__leaveAllChannels) self.channelsWidget.addTab(channel, name) self.__channelList.append(channel) self.channelsWidget.setCurrentWidget(channel) @pyqtSlot() def __leaveChannel(self): """ Private slot to leave a channel and close the associated tab. """ channel = self.channelsWidget.currentWidget() channel.requestLeave() @pyqtSlot(list) def __leaveChannels(self, channelNames): """ Private slot to leave a list of channels and close their associated tabs. @param channelNames list of channels to leave @type list of str """ for channelName in channelNames: for channel in self.__channelList: if channel.name() == channelName: channel.leaveChannel() @pyqtSlot() def __leaveAllChannels(self): """ Private slot to leave all channels and close their tabs. """ while self.__channelList: channel = self.__channelList[0] channel.leaveChannel() def __closeAllChannels(self): """ Private method to close all channels. """ while self.__channelList: channel = self.__channelList.pop() self.channelsWidget.removeTab(self.channelsWidget.indexOf(channel)) channel.deleteLater() channel = None self.channelsWidget.addTab(self.__emptyLabel, "") self.__emptyLabel.show() self.__leaveButton.setEnabled(False) self.channelsWidget.setTabsClosable(False) def __closeChannel(self, name): """ Private slot handling the closing of a channel. @param name name of the closed channel (string) """ for channel in self.__channelList: if channel.name() == name: self.channelsWidget.removeTab( self.channelsWidget.indexOf(channel)) self.__channelList.remove(channel) channel.deleteLater() if self.channelsWidget.count() == 0: self.channelsWidget.addTab(self.__emptyLabel, "") self.__emptyLabel.show() self.__leaveButton.setEnabled(False) self.channelsWidget.setTabsClosable(False) @pyqtSlot(int) def on_channelsWidget_tabCloseRequested(self, index): """ Private slot to close a channel by pressing the close button of the channels widget. @param index index of the tab to be closed (integer) """ channel = self.channelsWidget.widget(index) channel.requestLeave() def __send(self, data): """ Private slot to send data to the IRC server. @param data data to be sent (string) """ if self.__socket: self.__socket.write( QByteArray("{0}\r\n".format(data).encode("utf-8"))) def __sendCtcpRequest(self, receiver, request, arguments): """ Private slot to send a CTCP request. @param receiver nick name of the receiver @type str @param request CTCP request to be sent @type str @param arguments arguments to be sent @type str """ request = request.upper() if request == "PING": arguments = "Eric IRC {0}".format( QDateTime.currentMSecsSinceEpoch()) self.__send("PRIVMSG {0} :\x01{1} {2}\x01".format( receiver, request, arguments)) def __sendCtcpReply(self, receiver, text): """ Private slot to send a CTCP reply. @param receiver nick name of the receiver @type str @param text text to be sent @type str """ self.__send("NOTICE {0} :\x01{1}\x01".format(receiver, text)) def __hostFound(self): """ Private slot to indicate the host was found. """ self.networkWidget.addServerMessage( self.tr("Info"), self.tr("Server found,connecting...")) def __hostConnected(self): """ Private slot to log in to the server after the connection was established. """ self.networkWidget.addServerMessage( self.tr("Info"), self.tr("Connected,logging in...")) self.networkWidget.setConnected(True) self.__registering = True serverPassword = self.__server.getPassword() if serverPassword: self.__send("PASS " + serverPassword) identity = self.__ircNetworkManager.getIdentity( self.__identityName) nick = self.networkWidget.getNickname() if not nick and identity: self.__nickIndex = 0 try: nick = identity.getNickNames()[self.__nickIndex] except IndexError: nick = "" if not nick: nick = self.__userName self.__nickName = nick self.networkWidget.setNickName(nick) if identity: realName = identity.getRealName() if not realName: realName = "eric IDE chat" self.__send("NICK " + nick) self.__send("USER " + self.__userName + " 0 * :" + realName) def __hostDisconnected(self): """ Private slot to indicate the host was disconnected. """ if self.networkWidget.isConnected(): self.__closeAllChannels() self.networkWidget.addServerMessage( self.tr("Info"), self.tr("Server disconnected.")) self.networkWidget.setRegistered(False) self.networkWidget.setConnected(False) self.__server = None self.__nickName = "" self.__nickIndex = -1 self.__channelTypePrefixes = "" if self.__socket: self.__socket.deleteLater() self.__socket = None self.__connectionState = IrcWidget.ServerDisconnected self.__sslErrorLock = False def __readyRead(self): """ Private slot to read data from the socket. """ if self.__socket: self.__buffer += str( self.__socket.readAll(), Preferences.getSystem("IOEncoding"), 'replace') if self.__buffer.endswith("\r\n"): for line in self.__buffer.splitlines(): line = line.strip() if line: logging.debug("<IRC> %s", line) handled = False # step 1: give channels a chance to handle the message for channel in self.__channelList: handled = channel.handleMessage(line) if handled: break else: # step 2: try to process the message ourselves for patternRe, patternFunc in self.__patterns: match = patternRe.match(line) if match is not None: if patternFunc(match): break else: # Oops, the message wasn't handled self.networkWidget.addErrorMessage( self.tr("Message Error"), self.tr( "Unknown message received from server:" "<br/>{0}").format(line)) self.__updateUsersCount() self.__buffer = "" def __handleCtcpReply(self, match): """ Private method to handle a server message containing a CTCP reply. @param match reference to the match object """ if "!" in match.group(1): sender = match.group(1).split("!", 1)[0] try: ctcpCommand = match.group(3).split(":", 1)[1] except IndexError: ctcpCommand = match.group(3) ctcpCommand = ctcpCommand[1:].split("\x01", 1)[0] if " " in ctcpCommand: ctcpReply, ctcpArg = ctcpCommand.split(" ", 1) else: ctcpReply, ctcpArg = ctcpCommand, "" ctcpReply = ctcpReply.upper() if ctcpReply == "PING" and ctcpArg.startswith("Eric IRC "): # it is a response to a ping request pingDateTime = int(ctcpArg.split()[-1]) latency = QDateTime.currentMSecsSinceEpoch() - pingDateTime self.networkWidget.addServerMessage( self.tr("CTCP"), self.tr( "Received CTCP-PING response from {0} with latency" " of {1} ms.").format(sender, latency)) else: self.networkWidget.addServerMessage( self.tr("CTCP"), self.tr( "Received unknown CTCP-{0} response from {1}.") .format(ctcpReply, sender)) def __handleNamedMessage(self, match): """ Private method to handle a server message containing a message name. @param match reference to the match object @return flag indicating, if the message was handled (boolean) """ name = match.group(2) if name == "NOTICE": try: msg = match.group(3).split(":", 1)[1] except IndexError: msg = match.group(3) if msg.startswith("\x01"): self.__handleCtcpReply(match) return True if "!" in match.group(1): name = match.group(1).split("!", 1)[0] msg = "-{0}- {1}".format(name, msg) self.networkWidget.addServerMessage(self.tr("Notice"), msg) return True elif name == "MODE": self.__registering = False if ":" in match.group(3): # :foo MODE foo :+i name, modes = match.group(3).split(" :") sourceNick = match.group(1) if not self.isChannelName(name): if name == self.__nickName: if sourceNick == self.__nickName: msg = self.tr( "You have set your personal modes to" " <b>[{0}]</b>.").format(modes) else: msg = self.tr( "{0} has changed your personal modes to" " <b>[{1}]</b>.").format(sourceNick, modes) self.networkWidget.addServerMessage( self.tr("Mode"), msg, filterMsg=False) return True elif name == "PART": nick = match.group(1).split("!", 1)[0] if nick == self.__nickName: channel = match.group(3).split(None, 1)[0] self.networkWidget.addMessage( self.tr("You have left channel {0}.").format(channel)) return True elif name == "QUIT": # don't do anything with it here return True elif name == "NICK": # :[email protected] NICK :newnick oldNick = match.group(1).split("!", 1)[0] newNick = match.group(3).split(":", 1)[1] if oldNick == self.__nickName: self.networkWidget.addMessage( self.tr("You are now known as {0}.").format(newNick)) self.__nickName = newNick self.networkWidget.setNickName(newNick) else: self.networkWidget.addMessage( self.tr("User {0} is now known as {1}.").format( oldNick, newNick)) return True elif name == "PONG": nick = match.group(3).split(":", 1)[1] self.networkWidget.addMessage( self.tr("Received PONG from {0}").format(nick)) return True elif name == "ERROR": self.networkWidget.addErrorMessage( self.tr("Server Error"), match.group(3).split(":", 1)[1]) return True return False def __handleNumericMessage(self, match): """ Private method to handle a server message containing a numeric code. @param match reference to the match object @return flag indicating, if the message was handled (boolean) """ code = int(match.group(2)) if code < 400: return self.__handleServerReply( code, match.group(1), match.group(3)) else: return self.__handleServerError( code, match.group(1), match.group(3)) def __handleServerError(self, code, server, message): """ Private slot to handle a server error reply. @param code numerical code sent by the server (integer) @param server name of the server (string) @param message message sent by the server (string) @return flag indicating, if the message was handled (boolean) """ if code == 433: if self.__registering: self.__handleNickInUseLogin() else: self.__handleNickInUse() else: self.networkWidget.addServerMessage(self.tr("Error"), message) return True def __handleServerReply(self, code, server, message): """ Private slot to handle a server reply. @param code numerical code sent by the server (integer) @param server name of the server (string) @param message message sent by the server (string) @return flag indicating, if the message was handled (boolean) """ # determine message type if code in [1, 2, 3, 4]: msgType = self.tr("Welcome") elif code == 5: msgType = self.tr("Support") elif code in [250, 251, 252, 253, 254, 255, 265, 266]: msgType = self.tr("User") elif code in [372, 375, 376]: msgType = self.tr("MOTD") elif code in [305, 306]: msgType = self.tr("Away") else: msgType = self.tr("Info ({0})").format(code) # special treatment for some messages if code == 375: message = self.tr("Message of the day") elif code == 376: message = self.tr("End of message of the day") elif code == 4: parts = message.strip().split() message = self.tr( "Server {0} (Version {1}), User-Modes: {2}," " Channel-Modes: {3}" ).format(parts[1], parts[2], parts[3], parts[4]) elif code == 265: parts = message.strip().split() message = self.tr( "Current users on {0}: {1}, max. {2}").format( server, parts[1], parts[2]) elif code == 266: parts = message.strip().split() message = self.tr( "Current users on the network: {0}, max. {1}").format( parts[1], parts[2]) elif code == 305: message = self.tr("You are no longer marked as being away.") elif code == 306: message = self.tr("You have been marked as being away.") else: first, message = message.split(None, 1) if message.startswith(":"): message = message[1:] else: message = message.replace(":", "", 1) self.networkWidget.addServerMessage(msgType, message) if code == 1: # register with services after the welcome message self.__connectionState = IrcWidget.ServerConnected self.__registerWithServices() self.networkWidget.setRegistered(True) QTimer.singleShot(1000, self.__autoJoinChannels) elif code == 5: # extract the user privilege prefixes # ... PREFIX=(ov)@+ ... m = self.__prefixRe.match(message) if m: self.__setUserPrivilegePrefix(m.group(1), m.group(2)) # extract the channel type prefixes # ... CHANTYPES=# ... m = self.__chanTypesRe.match(message) if m: self.__setChannelTypePrefixes(m.group(1)) return True def __registerWithServices(self): """ Private method to register to services. """ identity = self.__ircNetworkManager.getIdentity(self.__identityName) if identity: service = identity.getServiceName() password = identity.getPassword() if service and password: self.__send("PRIVMSG " + service + " :identify " + password) def __autoJoinChannels(self): """ Private slot to join channels automatically once a server got connected. """ for channel in self.networkWidget.getNetworkChannels(): if channel.autoJoin(): name = channel.getName() key = channel.getKey() self.joinChannel(name, key) def __tcpError(self, error): """ Private slot to handle errors reported by the TCP socket. @param error error code reported by the socket (QAbstractSocket.SocketError) """ if error == QAbstractSocket.RemoteHostClosedError: # ignore this one, it's a disconnect if self.__sslErrorLock: self.networkWidget.addErrorMessage( self.tr("SSL Error"), self.tr( """Connection to server {0} (port {1}) lost while""" """ waiting for user response to an SSL error.""") .format(self.__server.getName(), self.__server.getPort())) self.__connectionState = IrcWidget.ServerDisconnected elif error == QAbstractSocket.HostNotFoundError: self.networkWidget.addErrorMessage( self.tr("Socket Error"), self.tr( "The host was not found. Please check the host name" " and port settings.")) elif error == QAbstractSocket.ConnectionRefusedError: self.networkWidget.addErrorMessage( self.tr("Socket Error"), self.tr( "The connection was refused by the peer. Please check the" " host name and port settings.")) elif error == QAbstractSocket.SslHandshakeFailedError: self.networkWidget.addErrorMessage( self.tr("Socket Error"), self.tr("The SSL handshake failed.")) else: if self.__socket: self.networkWidget.addErrorMessage( self.tr("Socket Error"), self.tr( "The following network error occurred:<br/>{0}") .format(self.__socket.errorString())) else: self.networkWidget.addErrorMessage( self.tr("Socket Error"), self.tr("A network error occurred.")) def __sslErrors(self, errors): """ Private slot to handle SSL errors. @param errors list of SSL errors (list of QSslError) """ ignored, defaultChanged = self.__sslErrorHandler.sslErrors( errors, self.__server.getName(), self.__server.getPort()) if ignored == E5SslErrorHandler.NotIgnored: self.networkWidget.addErrorMessage( self.tr("SSL Error"), self.tr( """Could not connect to {0} (port {1}) using an SSL""" """ encrypted connection. Either the server does not""" """ support SSL (did you use the correct port?) or""" """ you rejected the certificate.""") .format(self.__server.getName(), self.__server.getPort())) self.__socket.close() else: if defaultChanged: self.__socket.setSslConfiguration( QSslConfiguration.defaultConfiguration()) if ignored == E5SslErrorHandler.UserIgnored: self.networkWidget.addErrorMessage( self.tr("SSL Error"), self.tr( """The SSL certificate for the server {0} (port {1})""" """ failed the authenticity check. SSL errors""" """ were accepted by you.""") .format(self.__server.getName(), self.__server.getPort())) if self.__connectionState == IrcWidget.ServerConnecting: self.__socket.ignoreSslErrors() def __setUserPrivilegePrefix(self, prefix1, prefix2): """ Private method to set the user privilege prefix. @param prefix1 first part of the prefix (string) @param prefix2 indictors the first part gets mapped to (string) """ # PREFIX=(ov)@+ # o = @ -> @ircbot , channel operator # v = + -> +userName , voice operator for i in range(len(prefix1)): self.__userPrefix["+" + prefix1[i]] = prefix2[i] self.__userPrefix["-" + prefix1[i]] = "" def __ping(self, match): """ Private method to handle a PING message. @param match reference to the match object @return flag indicating, if the message was handled (boolean) """ self.__send("PONG " + match.group(1)) return True def __handleCtcp(self, match): """ Private method to handle a CTCP command. @param match reference to the match object @return flag indicating, if the message was handled (boolean) """ # group(1) sender user name # group(2) sender user@host # group(3) target nick # group(4) message if match.group(4).startswith("\x01"): ctcpCommand = match.group(4)[1:].split("\x01", 1)[0] if " " in ctcpCommand: ctcpRequest, ctcpArg = ctcpCommand.split(" ", 1) else: ctcpRequest, ctcpArg = ctcpCommand, "" ctcpRequest = ctcpRequest.lower() if ctcpRequest == "version": if Version.startswith("@@"): vers = "" else: vers = " " + Version msg = "Eric IRC client{0}, {1}".format(vers, Copyright) self.networkWidget.addServerMessage( self.tr("CTCP"), self.tr("Received Version request from {0}.").format( match.group(1))) self.__sendCtcpReply(match.group(1), "VERSION " + msg) elif ctcpRequest == "ping": self.networkWidget.addServerMessage( self.tr("CTCP"), self.tr( "Received CTCP-PING request from {0}," " sending answer.").format(match.group(1))) self.__sendCtcpReply( match.group(1), "PING {0}".format(ctcpArg)) elif ctcpRequest == "clientinfo": self.networkWidget.addServerMessage( self.tr("CTCP"), self.tr( "Received CTCP-CLIENTINFO request from {0}," " sending answer.").format(match.group(1))) self.__sendCtcpReply( match.group(1), "CLIENTINFO CLIENTINFO PING VERSION") else: self.networkWidget.addServerMessage( self.tr("CTCP"), self.tr( "Received unknown CTCP-{0} request from {1}.") .format(ctcpRequest, match.group(1))) return True return False def __updateUsersCount(self): """ Private method to update the users count on the channel tabs. """ for channel in self.__channelList: index = self.channelsWidget.indexOf(channel) self.channelsWidget.setTabText( index, self.tr("{0} ({1})", "channel name, users count").format( channel.name(), channel.getUsersCount())) def __handleNickInUseLogin(self): """ Private method to handle a 443 server error at login. """ self.__nickIndex += 1 try: identity = self.__ircNetworkManager.getIdentity( self.__identityName) if identity: nick = identity.getNickNames()[self.__nickIndex] self.__nickName = nick else: self.__connectNetwork("", False, True) self.__nickName = "" self.__nickIndex = -1 return except IndexError: self.networkWidget.addServerMessage( self.tr("Critical"), self.tr( "No nickname acceptable to the server configured" " for <b>{0}</b>. Disconnecting...") .format(self.__userName), filterMsg=False) self.__connectNetwork("", False, True) self.__nickName = "" self.__nickIndex = -1 return self.networkWidget.setNickName(nick) self.__send("NICK " + nick) def __handleNickInUse(self): """ Private method to handle a 443 server error. """ self.networkWidget.addServerMessage( self.tr("Critical"), self.tr("The given nickname is already in use.")) def __changeNick(self, nick): """ Private slot to use a new nick name. @param nick nick name to use (str) """ if nick and nick != self.__nickName: self.__send("NICK " + nick) def __setChannelTypePrefixes(self, prefixes): """ Private method to set the channel type prefixes. @param prefixes channel prefix characters (string) """ self.__channelTypePrefixes = prefixes def isChannelName(self, name): """ Public method to check, if the given name is a channel name. @param name name to check (string) @return flag indicating a channel name (boolean) """ if not name: return False if self.__channelTypePrefixes: return name[0] in self.__channelTypePrefixes else: return name[0] in "#&" def __away(self, isAway): """ Private slot handling the change of the away state. @param isAway flag indicating the current away state (boolean) """ if isAway and self.__identityName: identity = self.__ircNetworkManager.getIdentity( self.__identityName) if identity and identity.rememberAwayPosition(): for channel in self.__channelList: channel.setMarkerLine()
class SocketTest(QObject): def __init__(self, parent=None): super(SocketTest, self).__init__(parent) def init_socket(self): self.socket = QTcpSocket(self) def connected(): logger.info('connected , local port:{}'.format(self.socket.localPort())) # self.socket.write('f**k u'.encode(encoding='utf8')) def disconnect(): logger.info('disconnected') self.socket.connectToHost(IP, PORT) @pyqtSlot(QAbstractSocket.SocketError) def error(err): dict = { 0: 'QAbstractSocket::ConnectionRefusedError', 1: 'QAbstractSocket::RemoteHostClosedError', 2: 'QAbstractSocket::HostNotFoundError', 3: 'QAbstractSocket::SocketAccessError', 4: 'QAbstractSocket::SocketResourceError', 5: 'QAbstractSocket::SocketTimeoutError', 6: 'QAbstractSocket::DatagramTooLargeError', 7: 'QAbstractSocket::NetworkError', 8: 'QAbstractSocket::AddressInUseError', 9: 'QAbstractSocket::SocketAddressNotAvailableError', 10: 'QAbstractSocket::UnsupportedSocketOperationError', 12: 'QAbstractSocket::ProxyAuthenticationRequiredError', 13: 'QAbstractSocket::SslHandshakeFailedError', 11: 'QAbstractSocket::UnfinishedSocketOperationError', 14: 'QAbstractSocket::ProxyConnectionRefusedError', 15: 'QAbstractSocket::ProxyConnectionClosedError', 16: 'QAbstractSocket::ProxyConnectionTimeoutError', 17: 'QAbstractSocket::ProxyNotFoundError', 18: 'QAbstractSocket::ProxyProtocolError', 19: 'QAbstractSocket::OperationError', 20: 'QAbstractSocket::SslInternalError', 21: 'QAbstractSocket::SslInvalidUserDataError', 22: 'QAbstractSocket::TemporaryError', -1: 'QAbstractSocket::UnknownSocketError' } logger.info(dict[err]) @pyqtSlot(QAbstractSocket.SocketState) def _state_changed(state): # http://doc.qt.io/qt-5/qabstractsocket.html#SocketState-enum dict = { 0: 'QAbstractSocket::UnconnectedState', 1: 'QAbstractSocket::HostLookupState', 2: 'QAbstractSocket::ConnectingState', 3: 'QAbstractSocket::ConnectedState', 4: 'QAbstractSocket::BoundState', 6: 'QAbstractSocket::ClosingState', 5: 'QAbstractSocket::ListeningState' } logger.info(dict[state]) def ready_ready(): logger.info('ready read', end=': ') #logger.info(self.socket.readAll(q)) self.socket.close() @pyqtSlot(int) def bytes_written(bytes): logger.info('{} bytes send'.format(bytes)) #self.socket.connected.connect(connected) #self.socket.disconnected.connect(disconnect) self.socket.stateChanged.connect(_state_changed) self.socket.error.connect(error) # self.socket.readyRead.connect(ready_ready) # self.socket.bytesWritten.connect(bytes_written) self.socket.connectToHost(IP, PORT)
class TcpClient(QWidget): def __init__(self): super().__init__() self.isOnline = False self.port = 8888 self.serverIP = QHostAddress('127.0.0.1') self.initUI() def initUI(self): self.ui = ui_tcpClient.Ui_Form() self.ui.setupUi(self) self.ui.sendBtn.setEnabled(False) self.ui.portLineEdit.setText(str(self.port)) self.ui.serverIPLineEdit.setText(self.serverIP.toString()) self.ui.enterBtn.clicked.connect(self.slotEnterOrLeave) self.ui.sendBtn.clicked.connect(self.slotSend) self.ui.sendLineEdit.returnPressed.connect(self.slotSend) self.show() def slotEnterOrLeave(self): if not self.isOnline: if not self.validate(): return self.enterRoom() else: self.leaveRoom() def validate(self): if self.ui.userNameLineEdit.text() == '': QMessageBox().information(self, 'ERROR', 'User Name Error!') return False self.userName = self.ui.userNameLineEdit.text() if not self.serverIP.setAddress( self.ui.serverIPLineEdit.text()): # 判断给定的IP是否能够被正确解析 QMessageBox().information(self, 'ERROR', 'Server IP Error!') return False if not (0 <= int(self.ui.portLineEdit.text()) <= 65535): QMessageBox().information(self, 'ERROR', 'Server Port Error!') return False self.port = int(self.ui.portLineEdit.text()) return True def enterRoom(self): self.tcpSocket = QTcpSocket(self) self.tcpSocket.connectToHost(self.serverIP, self.port) self.tcpSocket.connected.connect(self.slotConnected) self.tcpSocket.readyRead.connect(self.slotDataReceived) self.tcpSocket.disconnected.connect(self.slotDisconnected) self.tcpSocket.error.connect(self.slotErrorOccured) def leaveRoom(self): sendData = '[-] ' + self.userName + ': Leave Chat Room' self.tcpSocket.write(bytes(sendData, encoding='utf-8')) self.tcpSocket.disconnectFromHost() def slotSend(self): if self.ui.sendLineEdit.text() == '': return sendData = self.userName + ': ' + self.ui.sendLineEdit.text() self.tcpSocket.write(bytes(sendData, encoding='utf-8')) self.ui.sendLineEdit.clear() def slotConnected(self): self.ui.sendBtn.setEnabled(True) self.ui.userNameLineEdit.setEnabled(False) self.ui.serverIPLineEdit.setEnabled(False) self.ui.portLineEdit.setEnabled(False) self.ui.enterBtn.setText('Leave Chat Room') self.isOnline = True sendData = '[+] ' + self.userName + ': Enter Chat Room' self.tcpSocket.write(bytes(sendData, encoding='utf-8')) def slotDataReceived(self): recvData = '' while self.tcpSocket.bytesAvailable() > 0: recvData = self.tcpSocket.read(self.tcpSocket.bytesAvailable()) self.ui.contentListWidget.addItem(str(recvData, encoding='utf-8')) self.ui.contentListWidget.scrollToBottom() # 滚动到最后一行 def slotDisconnected(self): self.ui.sendBtn.setEnabled(False) self.ui.userNameLineEdit.setEnabled(True) self.ui.serverIPLineEdit.setEnabled(True) self.ui.portLineEdit.setEnabled(True) self.ui.enterBtn.setText('Enter Chat Room') self.isOnline = False def closeEvent(self, event): if self.isOnline: msg = 'Are you sure to leave the chat room ?' reply = QMessageBox().warning(self, 'Quit', msg, QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if reply == QMessageBox.Yes: self.leaveRoom() event.accept() else: event.ignore() else: event.accept() def slotErrorOccured(self, socketError): if socketError == 0: msg = '[*] ConnectionRefusedError: The connection was refused by the peer (or timed out).' self.ui.contentListWidget.addItem(msg) elif socketError == 1: msg = '[*] RemoteHostClosedError: The remote host closed the connection.' self.ui.contentListWidget.addItem(msg)
class VNA(QMainWindow, Ui_VNA): max_size = 16383 formatter = matplotlib.ticker.FuncFormatter(lambda x, pos: '%1.1fM' % (x * 1e-6) if abs(x) >= 1e6 else '%1.1fk' % (x * 1e-3) if abs(x) >= 1e3 else '%1.1f' % x if abs(x) >= 1e0 else '%1.1fm' % (x * 1e+3) if abs(x) >= 1e-3 else '%1.1fu' % (x * 1e+6) if abs(x) >= 1e-6 else '%1.1f' % x) def __init__(self): super(VNA, self).__init__() self.setupUi(self) # IP address validator rx = QRegExp('^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$') self.addrValue.setValidator(QRegExpValidator(rx, self.addrValue)) # state variable self.idle = True # sweep parameters self.sweep_start = 100 self.sweep_stop = 60000 self.sweep_size = 600 self.xaxis, self.sweep_step = np.linspace(self.sweep_start, self.sweep_stop, self.sweep_size, retstep = True) self.xaxis *= 1000 # buffer and offset for the incoming samples self.buffer = bytearray(32 * VNA.max_size) self.offset = 0 self.data = np.frombuffer(self.buffer, np.complex64) self.adc1 = np.zeros(VNA.max_size, np.complex64) self.adc2 = np.zeros(VNA.max_size, np.complex64) self.dac1 = np.zeros(VNA.max_size, np.complex64) self.open = np.zeros(VNA.max_size, np.complex64) self.short = np.zeros(VNA.max_size, np.complex64) self.load = np.zeros(VNA.max_size, np.complex64) self.dut = np.zeros(VNA.max_size, np.complex64) self.mode = 'dut' # create figure self.figure = Figure() self.figure.set_facecolor('none') self.canvas = FigureCanvas(self.figure) self.plotLayout.addWidget(self.canvas) # create navigation toolbar self.toolbar = NavigationToolbar(self.canvas, self.plotWidget, False) # remove subplots action actions = self.toolbar.actions() self.toolbar.removeAction(actions[7]) self.plotLayout.addWidget(self.toolbar) # create TCP socket self.socket = QTcpSocket(self) self.socket.connected.connect(self.connected) self.socket.readyRead.connect(self.read_data) self.socket.error.connect(self.display_error) # connect signals from buttons and boxes self.sweepFrame.setEnabled(False) self.dutSweep.setEnabled(False) self.connectButton.clicked.connect(self.start) self.writeButton.clicked.connect(self.write_cfg) self.readButton.clicked.connect(self.read_cfg) self.openSweep.clicked.connect(self.sweep_open) self.shortSweep.clicked.connect(self.sweep_short) self.loadSweep.clicked.connect(self.sweep_load) self.dutSweep.clicked.connect(self.sweep_dut) self.s1pButton.clicked.connect(self.write_s1p) self.startValue.valueChanged.connect(self.set_start) self.stopValue.valueChanged.connect(self.set_stop) self.sizeValue.valueChanged.connect(self.set_size) self.openPlot.clicked.connect(self.plot_open) self.shortPlot.clicked.connect(self.plot_short) self.loadPlot.clicked.connect(self.plot_load) self.dutPlot.clicked.connect(self.plot_dut) self.smithPlot.clicked.connect(self.plot_smith) self.impPlot.clicked.connect(self.plot_imp) self.rcPlot.clicked.connect(self.plot_rc) self.swrPlot.clicked.connect(self.plot_swr) self.rlPlot.clicked.connect(self.plot_rl) # create timer self.startTimer = QTimer(self) self.startTimer.timeout.connect(self.timeout) def start(self): if self.idle: self.connectButton.setEnabled(False) self.socket.connectToHost(self.addrValue.text(), 1001) self.startTimer.start(5000) else: self.stop() def stop(self): self.idle = True self.socket.abort() self.offset = 0 self.connectButton.setText('Connect') self.connectButton.setEnabled(True) self.sweepFrame.setEnabled(False) self.selectFrame.setEnabled(True) self.dutSweep.setEnabled(False) def timeout(self): self.display_error('timeout') def connected(self): self.startTimer.stop() self.idle = False self.set_start(self.startValue.value()) self.set_stop(self.stopValue.value()) self.set_size(self.sizeValue.value()) self.connectButton.setText('Disconnect') self.connectButton.setEnabled(True) self.sweepFrame.setEnabled(True) self.dutSweep.setEnabled(True) def read_data(self): size = self.socket.bytesAvailable() if self.offset + size < 32 * self.sweep_size: self.buffer[self.offset:self.offset + size] = self.socket.read(size) self.offset += size else: self.buffer[self.offset:32 * self.sweep_size] = self.socket.read(32 * self.sweep_size - self.offset) self.offset = 0 self.adc1 = self.data[0::4] self.adc2 = self.data[1::4] self.dac1 = self.data[2::4] getattr(self, self.mode)[0:self.sweep_size] = self.adc1[0:self.sweep_size] / self.dac1[0:self.sweep_size] self.sweepFrame.setEnabled(True) self.selectFrame.setEnabled(True) getattr(self, 'plot_%s' % self.mode)() def display_error(self, socketError): self.startTimer.stop() if socketError == 'timeout': QMessageBox.information(self, 'VNA', 'Error: connection timeout.') else: QMessageBox.information(self, 'VNA', 'Error: %s.' % self.socket.errorString()) self.stop() def set_start(self, value): self.sweep_start = value self.xaxis, self.sweep_step = np.linspace(self.sweep_start, self.sweep_stop, self.sweep_size, retstep = True) self.xaxis *= 1000 if self.idle: return self.socket.write(struct.pack('<I', 0<<28 | int(value * 1000))) def set_stop(self, value): self.sweep_stop = value self.xaxis, self.sweep_step = np.linspace(self.sweep_start, self.sweep_stop, self.sweep_size, retstep = True) self.xaxis *= 1000 if self.idle: return self.socket.write(struct.pack('<I', 1<<28 | int(value * 1000))) def set_size(self, value): self.sweep_size = value self.xaxis, self.sweep_step = np.linspace(self.sweep_start, self.sweep_stop, self.sweep_size, retstep = True) self.xaxis *= 1000 if self.idle: return self.socket.write(struct.pack('<I', 2<<28 | int(value))) def sweep(self): if self.idle: return self.sweepFrame.setEnabled(False) self.selectFrame.setEnabled(False) self.socket.write(struct.pack('<I', 3<<28)) def sweep_open(self): self.mode = 'open' self.sweep() def sweep_short(self): self.mode = 'short' self.sweep() def sweep_load(self): self.mode = 'load' self.sweep() def sweep_dut(self): self.mode = 'dut' self.sweep() def impedance(self): return 50.0 * (self.open[0:self.sweep_size] - self.load[0:self.sweep_size]) * (self.dut[0:self.sweep_size] - self.short[0:self.sweep_size]) / ((self.load[0:self.sweep_size] - self.short[0:self.sweep_size]) * (self.open[0:self.sweep_size] - self.dut[0:self.sweep_size])) def gamma(self): z = self.impedance() return (z - 50.0)/(z + 50.0) def plot_magphase(self, data): matplotlib.rcdefaults() self.figure.clf() self.figure.subplots_adjust(top = 0.98, right = 0.88) axes1 = self.figure.add_subplot(111) axes1.cla() axes1.xaxis.set_major_formatter(VNA.formatter) axes1.yaxis.set_major_formatter(VNA.formatter) axes1.tick_params('y', color = 'blue', labelcolor = 'blue') axes1.yaxis.label.set_color('blue') axes1.plot(self.xaxis, np.absolute(data), color = 'blue') axes2 = axes1.twinx() axes2.spines['left'].set_color('blue') axes2.spines['right'].set_color('red') axes1.set_xlabel('Hz') axes1.set_ylabel('Magnitude') axes2.set_ylabel('Phase angle') axes2.tick_params('y', color = 'red', labelcolor = 'red') axes2.yaxis.label.set_color('red') axes2.plot(self.xaxis, np.angle(data, deg = True), color = 'red') self.canvas.draw() def plot_open(self): self.plot_magphase(self.open[0:self.sweep_size]) def plot_short(self): self.plot_magphase(self.short[0:self.sweep_size]) def plot_load(self): self.plot_magphase(self.load[0:self.sweep_size]) def plot_dut(self): self.plot_magphase(self.dut[0:self.sweep_size]) def plot_smith(self): matplotlib.rcdefaults() self.figure.clf() self.figure.subplots_adjust(top = 0.90, right = 0.90) axes = self.figure.add_subplot(111, projection = 'smith', axes_radius = 0.55, axes_scale = 50.0) axes.cla() axes.plot(self.impedance()) self.canvas.draw() def plot_imp(self): self.plot_magphase(self.impedance()) def plot_rc(self): self.plot_magphase(self.gamma()) def plot_swr(self): matplotlib.rcdefaults() self.figure.clf() self.figure.subplots_adjust(top = 0.98, right = 0.88) axes1 = self.figure.add_subplot(111) axes1.cla() axes1.xaxis.set_major_formatter(VNA.formatter) axes1.yaxis.set_major_formatter(VNA.formatter) axes1.set_xlabel('Hz') axes1.set_ylabel('SWR') magnitude = np.absolute(self.gamma()) swr = np.maximum(1.0, np.minimum(100.0, (1.0 + magnitude) / np.maximum(1.0e-20, 1.0 - magnitude))) axes1.plot(self.xaxis, swr, color = 'blue') self.canvas.draw() def plot_rl(self): matplotlib.rcdefaults() self.figure.clf() self.figure.subplots_adjust(top = 0.98, right = 0.88) axes1 = self.figure.add_subplot(111) axes1.cla() axes1.xaxis.set_major_formatter(VNA.formatter) axes1.set_xlabel('Hz') axes1.set_ylabel('Return loss, dB') magnitude = np.absolute(self.gamma()) axes1.plot(self.xaxis, 20.0 * np.log10(magnitude), color = 'blue') self.canvas.draw() def write_cfg(self): name = QFileDialog.getSaveFileName(self, 'Write configuration settings', '.', '*.ini') settings = QSettings(name[0], QSettings.IniFormat) self.write_cfg_settings(settings) def read_cfg(self): name = QFileDialog.getOpenFileName(self, 'Read configuration settings', '.', '*.ini') settings = QSettings(name[0], QSettings.IniFormat) self.read_cfg_settings(settings) def write_cfg_settings(self, settings): settings.setValue('start', self.startValue.value()) settings.setValue('stop', self.stopValue.value()) size = self.sizeValue.value() settings.setValue('size', size) for i in range(0, size): settings.setValue('open_real_%d' % i, float(self.open.real[i])) settings.setValue('open_imag_%d' % i, float(self.open.imag[i])) for i in range(0, size): settings.setValue('short_real_%d' % i, float(self.short.real[i])) settings.setValue('short_imag_%d' % i, float(self.short.imag[i])) for i in range(0, size): settings.setValue('load_real_%d' % i, float(self.load.real[i])) settings.setValue('load_imag_%d' % i, float(self.load.imag[i])) for i in range(0, size): settings.setValue('dut_real_%d' % i, float(self.dut.real[i])) settings.setValue('dut_imag_%d' % i, float(self.dut.imag[i])) def read_cfg_settings(self, settings): self.startValue.setValue(settings.value('start', 100, type = int)) self.stopValue.setValue(settings.value('stop', 60000, type = int)) size = settings.value('size', 600, type = int) self.sizeValue.setValue(size) for i in range(0, size): real = settings.value('open_real_%d' % i, 0.0, type = float) imag = settings.value('open_imag_%d' % i, 0.0, type = float) self.open[i] = real + 1.0j * imag for i in range(0, size): real = settings.value('short_real_%d' % i, 0.0, type = float) imag = settings.value('short_imag_%d' % i, 0.0, type = float) self.short[i] = real + 1.0j * imag for i in range(0, size): real = settings.value('load_real_%d' % i, 0.0, type = float) imag = settings.value('load_imag_%d' % i, 0.0, type = float) self.load[i] = real + 1.0j * imag for i in range(0, size): real = settings.value('dut_real_%d' % i, 0.0, type = float) imag = settings.value('dut_imag_%d' % i, 0.0, type = float) self.dut[i] = real + 1.0j * imag def write_s1p(self): name = QFileDialog.getSaveFileName(self, 'Write s1p file', '.', '*.s1p') fh = open(name[0], 'w') gamma = self.gamma() size = self.sizeValue.value() fh.write('# GHz S MA R 50\n') for i in range(0, size): fh.write('0.0%.8d %8.6f %7.2f\n' % (self.xaxis[i], np.absolute(gamma[i]), np.angle(gamma[i], deg = True))) fh.close()
class MKSOutputDevice(NetworkedPrinterOutputDevice): def __init__(self, instance_id: str, address: str, properties: dict, **kwargs) -> None: super().__init__(device_id=instance_id, address=address, properties=properties, **kwargs) self._address = address self._port = 8080 self._key = instance_id self._properties = properties self._target_bed_temperature = 0 self._num_extruders = 1 self._hotend_temperatures = [0] * self._num_extruders self._target_hotend_temperatures = [0] * self._num_extruders self._monitor_view_qml_path = os.path.join( os.path.dirname(os.path.abspath(__file__)), "MonitorItem4x.qml") # self._monitor_view_qml_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "MonitorItem.qml") self.setPriority( 3 ) # Make sure the output device gets selected above local file output and Octoprint XD self._active_machine = CuraApplication.getInstance().getMachineManager( ).activeMachine self.setName(instance_id) self.setShortDescription( i18n_catalog.i18nc("@action:button", "Print over TFT")) self.setDescription( i18n_catalog.i18nc("@properties:tooltip", "Print over TFT")) self.setIconName("print") self.setConnectionText( i18n_catalog.i18nc("@info:status", "Connected to TFT on {0}").format(self._key)) Application.getInstance().globalContainerStackChanged.connect( self._onGlobalContainerChanged) self._socket = None self._gl = None self._command_queue = Queue() self._isPrinting = False self._isPause = False self._isSending = False self._gcode = None self._isConnect = False self._printing_filename = "" self._printing_progress = 0 self._printing_time = 0 self._start_time = 0 self._pause_time = 0 self.last_update_time = 0 self.angle = 10 self._connection_state_before_timeout = None self._sdFileList = False self.sdFiles = [] self._mdialog = None self._mfilename = None self._uploadpath = '' self._settings_reply = None self._printer_reply = None self._job_reply = None self._command_reply = None self._screenShot = None self._image_reply = None self._stream_buffer = b"" self._stream_buffer_start_index = -1 self._post_reply = None self._post_multi_part = None self._post_part = None self._last_file_name = None self._last_file_path = None self._progress_message = None self._error_message = None self._connection_message = None self.__additional_components_view = None self._update_timer = QTimer() self._update_timer.setInterval( 2000) # TODO; Add preference for update interval self._update_timer.setSingleShot(False) self._update_timer.timeout.connect(self._update) self._manager = QNetworkAccessManager() self._manager.finished.connect(self._onRequestFinished) self._preheat_timer = QTimer() self._preheat_timer.setSingleShot(True) self._preheat_timer.timeout.connect(self.cancelPreheatBed) self._exception_message = None self._output_controller = GenericOutputController(self) self._number_of_extruders = 1 self._camera_url = "" # Application.getInstance().getOutputDeviceManager().outputDevicesChanged.connect(self._onOutputDevicesChanged) CuraApplication.getInstance().getCuraSceneController( ).activeBuildPlateChanged.connect(self.CreateMKSController) def _onOutputDevicesChanged(self): Logger.log("d", "MKS _onOutputDevicesChanged") def connect(self): if self._socket is not None: self._socket.close() self._socket = QTcpSocket() self._socket.connectToHost(self._address, self._port) global_container_stack = CuraApplication.getInstance( ).getGlobalContainerStack() self.setShortDescription( i18n_catalog.i18nc( "@action:button", "Print over " + global_container_stack.getName())) self.setDescription( i18n_catalog.i18nc( "@properties:tooltip", "Print over " + global_container_stack.getName())) Logger.log("d", "MKS socket connecting ") # self._socket.waitForConnected(2000) self.setConnectionState( cast(ConnectionState, UnifiedConnectionState.Connecting)) self._setAcceptsCommands(True) self._socket.readyRead.connect(self.on_read) self._update_timer.start() def getProperties(self): return self._properties @pyqtSlot(str, result=str) def getProperty(self, key): key = key.encode("utf-8") if key in self._properties: return self._properties.get(key, b"").decode("utf-8") else: return "" @pyqtSlot(result=str) def getKey(self): return self._key @pyqtProperty(str, constant=True) def address(self): return self._properties.get(b"address", b"").decode("utf-8") @pyqtProperty(str, constant=True) def name(self): return self._properties.get(b"name", b"").decode("utf-8") @pyqtProperty(str, constant=True) def firmwareVersion(self): return self._properties.get(b"firmware_version", b"").decode("utf-8") @pyqtProperty(str, constant=True) def ipAddress(self): return self._address @pyqtSlot(float, float) def preheatBed(self, temperature, duration): self._setTargetBedTemperature(temperature) if duration > 0: self._preheat_timer.setInterval(duration * 1000) self._preheat_timer.start() else: self._preheat_timer.stop() @pyqtSlot() def cancelPreheatBed(self): self._setTargetBedTemperature(0) self._preheat_timer.stop() @pyqtSlot() def printtest(self): self.sendCommand("M104 S0\r\n M140 S0\r\n M106 S255") @pyqtSlot() def printer_state(self): if len(self._printers) <= 0: return "offline" return self.printers[0].state @pyqtSlot() def selectfile(self): if self._last_file_name: return True else: return False @pyqtSlot(str) def deleteSDFiles(self, filename): # filename = "几何图.gcode" self._sendCommand("M30 1:/" + filename) self.sdFiles.remove(filename) self._sendCommand("M20") @pyqtSlot(str) def printSDFiles(self, filename): self._sendCommand("M23 " + filename) self._sendCommand("M24") @pyqtSlot() def selectFileToUplload(self): preferences = Application.getInstance().getPreferences() preferences.addPreference("mkswifi/autoprint", "True") preferences.addPreference("mkswifi/savepath", "") filename, _ = QFileDialog.getOpenFileName( None, "choose file", preferences.getValue("mkswifi/savepath"), "Gcode(*.gcode;*.g;*.goc)") preferences.setValue("mkswifi/savepath", filename) self._uploadpath = filename if ".g" in filename.lower(): # Logger.log("d", "selectfile:"+filename) if filename in self.sdFiles: if self._mdialog: self._mdialog.close() self._mdialog = QDialog() self._mdialog.setWindowTitle("The " + filename[filename.rfind("/") + 1:] + " file already exists.") dialogvbox = QVBoxLayout() dialoghbox = QHBoxLayout() yesbtn = QPushButton("yes") nobtn = QPushButton("no") yesbtn.clicked.connect(lambda: self.renameupload(filename)) nobtn.clicked.connect(self.closeMDialog) content = QLabel( "The " + filename[filename.rfind("/") + 1:] + " file already exists. Do you want to rename and upload it?" ) self._mfilename = QLineEdit() self._mfilename.setText(filename[filename.rfind("/") + 1:]) dialoghbox.addWidget(yesbtn) dialoghbox.addWidget(nobtn) dialogvbox.addWidget(content) dialogvbox.addWidget(self._mfilename) dialogvbox.addLayout(dialoghbox) self._mdialog.setLayout(dialogvbox) self._mdialog.exec_() return if len(filename[filename.rfind("/") + 1:]) >= 30: if self._mdialog: self._mdialog.close() self._mdialog = QDialog() self._mdialog.setWindowTitle( "File name is too long to upload, please rename it.") dialogvbox = QVBoxLayout() dialoghbox = QHBoxLayout() yesbtn = QPushButton("yes") nobtn = QPushButton("no") yesbtn.clicked.connect(lambda: self.renameupload(filename)) nobtn.clicked.connect(self.closeMDialog) content = QLabel( "File name is too long to upload, please rename it.") self._mfilename = QLineEdit() self._mfilename.setText(filename[filename.rfind("/") + 1:]) dialoghbox.addWidget(yesbtn) dialoghbox.addWidget(nobtn) dialogvbox.addWidget(content) dialogvbox.addWidget(self._mfilename) dialogvbox.addLayout(dialoghbox) self._mdialog.setLayout(dialogvbox) self._mdialog.exec_() return if self.isBusy(): if self._exception_message: self._exception_message.hide() self._exception_message = Message( i18n_catalog.i18nc( "@info:status", "File cannot be transferred during printing.")) self._exception_message.show() return self.uploadfunc(filename) def closeMDialog(self): if self._mdialog: self._mdialog.close() def renameupload(self, filename): if self._mfilename and ".g" in self._mfilename.text().lower(): filename = filename[:filename. rfind("/")] + "/" + self._mfilename.text() if self._mfilename.text() in self.sdFiles: if self._mdialog: self._mdialog.close() self._mdialog = QDialog() self._mdialog.setWindowTitle("The " + filename[filename.rfind("/") + 1:] + " file already exists.") dialogvbox = QVBoxLayout() dialoghbox = QHBoxLayout() yesbtn = QPushButton("yes") nobtn = QPushButton("no") yesbtn.clicked.connect(lambda: self.renameupload(filename)) nobtn.clicked.connect(self.closeMDialog) content = QLabel( "The " + filename[filename.rfind("/") + 1:] + " file already exists. Do you want to rename and upload it?" ) self._mfilename = QLineEdit() self._mfilename.setText(filename[filename.rfind("/") + 1:]) dialoghbox.addWidget(yesbtn) dialoghbox.addWidget(nobtn) dialogvbox.addWidget(content) dialogvbox.addWidget(self._mfilename) dialogvbox.addLayout(dialoghbox) self._mdialog.setLayout(dialogvbox) self._mdialog.exec_() return if len(filename[filename.rfind("/") + 1:]) >= 30: if self._mdialog: self._mdialog.close() self._mdialog = QDialog() self._mdialog.setWindowTitle( "File name is too long to upload, please rename it.") dialogvbox = QVBoxLayout() dialoghbox = QHBoxLayout() yesbtn = QPushButton("yes") nobtn = QPushButton("no") yesbtn.clicked.connect(lambda: self.renameupload(filename)) nobtn.clicked.connect(self.closeMDialog) content = QLabel( "File name is too long to upload, please rename it.") self._mfilename = QLineEdit() self._mfilename.setText(filename[filename.rfind("/") + 1:]) dialoghbox.addWidget(yesbtn) dialoghbox.addWidget(nobtn) dialogvbox.addWidget(content) dialogvbox.addWidget(self._mfilename) dialogvbox.addLayout(dialoghbox) self._mdialog.setLayout(dialogvbox) self._mdialog.exec_() return if self.isBusy(): if self._exception_message: self._exception_message.hide() self._exception_message = Message( i18n_catalog.i18nc( "@info:status", "File cannot be transferred during printing.")) self._exception_message.show() return self._mdialog.close() self.uploadfunc(filename) def uploadfunc(self, filename): preferences = Application.getInstance().getPreferences() preferences.addPreference("mkswifi/autoprint", "True") preferences.addPreference("mkswifi/savepath", "") self._update_timer.stop() self._isSending = True self._preheat_timer.stop() single_string_file_data = "" try: f = open(self._uploadpath, "r") single_string_file_data = f.read() file_name = filename[filename.rfind("/") + 1:] self._last_file_name = file_name self._progress_message = Message( i18n_catalog.i18nc("@info:status", "Sending data to printer"), 0, False, -1, i18n_catalog.i18nc("@info:title", "Sending Data"), option_text=i18n_catalog.i18nc("@label", "Print jobs"), option_state=preferences.getValue("mkswifi/autoprint")) self._progress_message.addAction( "Cancel", i18n_catalog.i18nc("@action:button", "Cancel"), None, "") self._progress_message.actionTriggered.connect( self._cancelSendGcode) self._progress_message.optionToggled.connect( self._onOptionStateChanged) self._progress_message.show() self._post_multi_part = QHttpMultiPart(QHttpMultiPart.FormDataType) self._post_part = QHttpPart() self._post_part.setHeader( QNetworkRequest.ContentDispositionHeader, "form-data; name=\"file\"; filename=\"%s\"" % file_name) self._post_part.setBody(single_string_file_data.encode()) self._post_multi_part.append(self._post_part) post_request = QNetworkRequest( QUrl("http://%s/upload?X-Filename=%s" % (self._address, file_name))) post_request.setRawHeader(b'Content-Type', b'application/octet-stream') post_request.setRawHeader(b'Connection', b'keep-alive') self._post_reply = self._manager.post(post_request, self._post_multi_part) self._post_reply.uploadProgress.connect(self._onUploadProgress) self._post_reply.sslErrors.connect(self._onUploadError) self._gcode = None except IOError as e: Logger.log( "e", "An exception occurred in network connection: %s" % str(e)) self._progress_message.hide() self._error_message = Message( i18n_catalog.i18nc("@info:status", "Send file to printer failed.")) self._error_message.show() self._update_timer.start() except Exception as e: self._update_timer.start() self._progress_message.hide() Logger.log( "e", "An exception occurred in network connection: %s" % str(e)) @pyqtProperty("QVariantList") def getSDFiles(self): self._sendCommand("M20") return list(self.sdFiles) def _setTargetBedTemperature(self, temperature): if not self._updateTargetBedTemperature(temperature): return self._sendCommand(["M140 S%s" % temperature]) @pyqtSlot(str) def sendCommand(self, cmd): self._sendCommand(cmd) def _sendCommand(self, cmd): # Logger.log("d", "_sendCommand %s" % str(cmd)) if self._socket and self._socket.state() == 2 or self._socket.state( ) == 3: if isinstance(cmd, str): self._command_queue.put(cmd + "\r\n") elif isinstance(cmd, list): for eachCommand in cmd: self._command_queue.put(eachCommand + "\r\n") def disconnect(self): # self._updateJobState("") self._isConnect = False self.setConnectionState( cast(ConnectionState, UnifiedConnectionState.Closed)) if self._socket is not None: self._socket.readyRead.disconnect(self.on_read) self._socket.close() if self._progress_message: self._progress_message.hide() if self._error_message: self._error_message.hide() self._update_timer.stop() def isConnected(self): return self._isConnect def isBusy(self): return self._isPrinting or self._isPause def requestWrite(self, node, file_name=None, filter_by_machine=False, file_handler=None, **kwargs): self.writeStarted.emit(self) self._update_timer.stop() self._isSending = True # imagebuff = self._gl.glReadPixels(0, 0, 800, 800, self._gl.GL_RGB, # self._gl.GL_UNSIGNED_BYTE) active_build_plate = CuraApplication.getInstance( ).getMultiBuildPlateModel().activeBuildPlate scene = CuraApplication.getInstance().getController().getScene() gcode_dict = getattr(scene, "gcode_dict", None) if not gcode_dict: return self._gcode = gcode_dict.get(active_build_plate, None) # Logger.log("d", "mks ready for print") self.startPrint() def startPrint(self): global_container_stack = CuraApplication.getInstance( ).getGlobalContainerStack() if not global_container_stack: return if self._error_message: self._error_message.hide() self._error_message = None if self._progress_message: self._progress_message.hide() self._progress_message = None if self.isBusy(): self._error_message = Message( i18n_catalog.i18nc("@info:status", "Sending data to printer"), 0, False, -1, i18n_catalog.i18nc("@info:title", "Sending Data")) self._error_message.show() return job_name = Application.getInstance().getPrintInformation( ).jobName.strip() if job_name is "": job_name = "untitled_print" job_name = "cura_file" filename = "%s.gcode" % job_name if filename in self.sdFiles: if self._mdialog: self._mdialog.close() self._mdialog = QDialog() self._mdialog.setWindowTitle("The " + filename[filename.rfind("/") + 1:] + " file already exists.") dialogvbox = QVBoxLayout() dialoghbox = QHBoxLayout() yesbtn = QPushButton("yes") nobtn = QPushButton("no") yesbtn.clicked.connect(self.recheckfilename) nobtn.clicked.connect(self.closeMDialog) content = QLabel( "The " + filename[filename.rfind("/") + 1:] + " file already exists. Do you want to rename and upload it?") self._mfilename = QLineEdit() self._mfilename.setText(filename[filename.rfind("/") + 1:]) dialoghbox.addWidget(yesbtn) dialoghbox.addWidget(nobtn) dialogvbox.addWidget(content) dialogvbox.addWidget(self._mfilename) dialogvbox.addLayout(dialoghbox) self._mdialog.setLayout(dialogvbox) self._mdialog.exec_() return if len(filename[filename.rfind("/") + 1:]) >= 30: if self._mdialog: self._mdialog.close() self._mdialog = QDialog() self._mdialog.setWindowTitle( "File name is too long to upload, please rename it.") dialogvbox = QVBoxLayout() dialoghbox = QHBoxLayout() yesbtn = QPushButton("yes") nobtn = QPushButton("no") yesbtn.clicked.connect(self.recheckfilename) nobtn.clicked.connect(self.closeMDialog) content = QLabel( "File name is too long to upload, please rename it.") self._mfilename = QLineEdit() self._mfilename.setText(filename[filename.rfind("/") + 1:]) dialoghbox.addWidget(yesbtn) dialoghbox.addWidget(nobtn) dialogvbox.addWidget(content) dialogvbox.addWidget(self._mfilename) dialogvbox.addLayout(dialoghbox) self._mdialog.setLayout(dialogvbox) self._mdialog.exec_() return self._startPrint(filename) def recheckfilename(self): if self._mfilename and ".g" in self._mfilename.text().lower(): filename = self._mfilename.text() if filename in self.sdFiles: if self._mdialog: self._mdialog.close() self._mdialog = QDialog() self._mdialog.setWindowTitle("The " + filename[filename.rfind("/") + 1:] + " file already exists.") dialogvbox = QVBoxLayout() dialoghbox = QHBoxLayout() yesbtn = QPushButton("yes") nobtn = QPushButton("no") yesbtn.clicked.connect(self.recheckfilename) nobtn.clicked.connect(self.closeMDialog) content = QLabel( "The " + filename[filename.rfind("/") + 1:] + " file already exists. Do you want to rename and upload it?" ) self._mfilename = QLineEdit() self._mfilename.setText(filename[filename.rfind("/") + 1:]) dialoghbox.addWidget(yesbtn) dialoghbox.addWidget(nobtn) dialogvbox.addWidget(content) dialogvbox.addWidget(self._mfilename) dialogvbox.addLayout(dialoghbox) self._mdialog.setLayout(dialogvbox) self._mdialog.exec_() return if len(filename[filename.rfind("/") + 1:]) >= 30: if self._mdialog: self._mdialog.close() self._mdialog = QDialog() self._mdialog.setWindowTitle( "File name is too long to upload, please rename it.") dialogvbox = QVBoxLayout() dialoghbox = QHBoxLayout() yesbtn = QPushButton("yes") nobtn = QPushButton("no") yesbtn.clicked.connect(self.recheckfilename) nobtn.clicked.connect(self.closeMDialog) content = QLabel( "File name is too long to upload, please rename it.") self._mfilename = QLineEdit() self._mfilename.setText(filename[filename.rfind("/") + 1:]) dialoghbox.addWidget(yesbtn) dialoghbox.addWidget(nobtn) dialogvbox.addWidget(content) dialogvbox.addWidget(self._mfilename) dialogvbox.addLayout(dialoghbox) self._mdialog.setLayout(dialogvbox) self._mdialog.exec_() return if self.isBusy(): if self._exception_message: self._exception_message.hide() self._exception_message = Message( i18n_catalog.i18nc( "@info:status", "File cannot be transferred during printing.")) self._exception_message.show() return self._mdialog.close() self._startPrint(filename) def _messageBoxCallback(self, button): def delayedCallback(): if button == QMessageBox.Yes: self.startPrint() else: CuraApplication.getInstance().getController().setActiveStage( "PrepareStage") def _startPrint(self, file_name="cura_file.gcode"): self._preheat_timer.stop() self._screenShot = utils.take_screenshot() try: preferences = Application.getInstance().getPreferences() preferences.addPreference("mkswifi/autoprint", "True") preferences.addPreference("mkswifi/savepath", "") # CuraApplication.getInstance().showPrintMonitor.emit(True) self._progress_message = Message( i18n_catalog.i18nc("@info:status", "Sending data to printer"), 0, False, -1, i18n_catalog.i18nc("@info:title", "Sending Data"), option_text=i18n_catalog.i18nc("@label", "Print jobs"), option_state=preferences.getValue("mkswifi/autoprint")) self._progress_message.addAction( "Cancel", i18n_catalog.i18nc("@action:button", "Cancel"), None, "") self._progress_message.actionTriggered.connect( self._cancelSendGcode) self._progress_message.optionToggled.connect( self._onOptionStateChanged) self._progress_message.show() # job_name = Application.getInstance().getPrintInformation().jobName.strip() # if job_name is "": # job_name = "untitled_print" # job_name = "cura_file" # file_name = "%s.gcode" % job_name self._last_file_name = file_name Logger.log( "d", "mks: " + file_name + Application.getInstance(). getPrintInformation().jobName.strip()) single_string_file_data = "" if self._screenShot: single_string_file_data += utils.add_screenshot( self._screenShot, 50, 50, ";simage:") single_string_file_data += utils.add_screenshot( self._screenShot, 200, 200, ";;gimage:") single_string_file_data += "\r" last_process_events = time.time() for line in self._gcode: single_string_file_data += line if time.time() > last_process_events + 0.05: QCoreApplication.processEvents() last_process_events = time.time() self._post_multi_part = QHttpMultiPart(QHttpMultiPart.FormDataType) self._post_part = QHttpPart() # self._post_part.setHeader(QNetworkRequest.ContentTypeHeader, b'application/octet-stream') self._post_part.setHeader( QNetworkRequest.ContentDispositionHeader, "form-data; name=\"file\"; filename=\"%s\"" % file_name) self._post_part.setBody(single_string_file_data.encode()) self._post_multi_part.append(self._post_part) post_request = QNetworkRequest( QUrl("http://%s/upload?X-Filename=%s" % (self._address, file_name))) post_request.setRawHeader(b'Content-Type', b'application/octet-stream') post_request.setRawHeader(b'Connection', b'keep-alive') self._post_reply = self._manager.post(post_request, self._post_multi_part) self._post_reply.uploadProgress.connect(self._onUploadProgress) self._post_reply.sslErrors.connect(self._onUploadError) # Logger.log("d", "http://%s:80/upload?X-Filename=%s" % (self._address, file_name)) self._gcode = None except IOError as e: Logger.log( "e", "An exception occurred in network connection: %s" % str(e)) self._progress_message.hide() self._error_message = Message( i18n_catalog.i18nc("@info:status", "Send file to printer failed.")) self._error_message.show() self._update_timer.start() except Exception as e: self._update_timer.start() self._progress_message.hide() Logger.log( "e", "An exception occurred in network connection: %s" % str(e)) def _printFile(self): self._sendCommand("M23 " + self._last_file_name) self._sendCommand("M24") def _onUploadProgress(self, bytes_sent, bytes_total): if bytes_total > 0: new_progress = bytes_sent / bytes_total * 100 # Treat upload progress as response. Uploading can take more than 10 seconds, so if we don't, we can get # timeout responses if this happens. self._last_response_time = time.time() if new_progress > self._progress_message.getProgress(): self._progress_message.show( ) # Ensure that the message is visible. self._progress_message.setProgress(bytes_sent / bytes_total * 100) else: self._progress_message.setProgress(0) self._progress_message.hide() def _onUploadError(self, reply, sslerror): Logger.log("d", "Upload Error") def _setHeadPosition(self, x, y, z, speed): self._sendCommand("G0 X%s Y%s Z%s F%s" % (x, y, z, speed)) def _setHeadX(self, x, speed): self._sendCommand("G0 X%s F%s" % (x, speed)) def _setHeadY(self, y, speed): self._sendCommand("G0 Y%s F%s" % (y, speed)) def _setHeadZ(self, z, speed): self._sendCommand("G0 Z%s F%s" % (z, speed)) def _homeHead(self): self._sendCommand("G28 X Y") def _homeBed(self): self._sendCommand("G28 Z") def _moveHead(self, x, y, z, speed): self._sendCommand( ["G91", "G0 X%s Y%s Z%s F%s" % (x, y, z, speed), "G90"]) def _update(self): if self._socket is not None and (self._socket.state() == 2 or self._socket.state() == 3): _send_data = "M105\r\nM997\r\n" if self.isBusy(): _send_data += "M994\r\nM992\r\nM27\r\n" while self._command_queue.qsize() > 0: _queue_data = self._command_queue.get() if "M23" in _queue_data: self._socket.writeData(_queue_data.encode()) continue if "M24" in _queue_data: self._socket.writeData(_queue_data.encode()) continue _send_data += _queue_data # Logger.log("d", "_send_data: \r\n%s" % _send_data) self._socket.writeData(_send_data.encode()) self._socket.flush() # self._socket.waitForReadyRead() else: Logger.log("d", "MKS wifi reconnecting") self.disconnect() self.connect() def _setJobState(self, job_state): if job_state == "abort": command = "M26" elif job_state == "print": if self._isPause: command = "M25" else: command = "M24" elif job_state == "pause": command = "M25" if command: self._sendCommand(command) @pyqtSlot() def cancelPrint(self): self._sendCommand("M26") @pyqtSlot() def pausePrint(self): if self.printers[0].state == "paused": self._sendCommand("M24") else: self._sendCommand("M25") @pyqtSlot() def resumePrint(self): self._sendCommand("M25") def on_read(self): if not self._socket: self.disconnect() return try: if not self._isConnect: self._isConnect = True if self._connection_state != UnifiedConnectionState.Connected: self._sendCommand("M20") self.setConnectionState( cast(ConnectionState, UnifiedConnectionState.Connected)) self.setConnectionText( i18n_catalog.i18nc("@info:status", "TFT Connect succeed")) # ss = str(self._socket.readLine().data(), encoding=sys.getfilesystemencoding()) # while self._socket.canReadLine(): # ss = str(self._socket.readLine().data(), encoding=sys.getfilesystemencoding()) # ss_list = ss.split("\r\n") if not self._printers: self._createPrinterList() printer = self.printers[0] while self._socket.canReadLine(): s = str(self._socket.readLine().data(), encoding=sys.getfilesystemencoding()) # Logger.log("d", "mks recv: "+s) s = s.replace("\r", "").replace("\n", "") # if time.time() - self.last_update_time > 10 or time.time() - self.last_update_time<-10: # Logger.log("d", "mks time:"+str(self.last_update_time)+str(time.time())) # self._sendCommand("M20") # self.last_update_time = time.time() if "T" in s and "B" in s and "T0" in s: t0_temp = s[s.find("T0:") + len("T0:"):s.find("T1:")] t1_temp = s[s.find("T1:") + len("T1:"):s.find("@:")] bed_temp = s[s.find("B:") + len("B:"):s.find("T0:")] t0_nowtemp = float(t0_temp[0:t0_temp.find("/")]) t0_targettemp = float(t0_temp[t0_temp.find("/") + 1:len(t0_temp)]) t1_nowtemp = float(t1_temp[0:t1_temp.find("/")]) t1_targettemp = float(t1_temp[t1_temp.find("/") + 1:len(t1_temp)]) bed_nowtemp = float(bed_temp[0:bed_temp.find("/")]) bed_targettemp = float(bed_temp[bed_temp.find("/") + 1:len(bed_temp)]) # cura 3.4 new api printer.updateBedTemperature(bed_nowtemp) printer.updateTargetBedTemperature(bed_targettemp) extruder = printer.extruders[0] extruder.updateTargetHotendTemperature(t0_targettemp) extruder.updateHotendTemperature(t0_nowtemp) # self._number_of_extruders = 1 # extruder = printer.extruders[1] # extruder.updateHotendTemperature(t1_nowtemp) # extruder.updateTargetHotendTemperature(t1_targettemp) # only on lower 3.4 # self._setBedTemperature(bed_nowtemp) # self._updateTargetBedTemperature(bed_targettemp) # if self._num_extruders > 1: # self._setHotendTemperature(1, t1_nowtemp) # self._updateTargetHotendTemperature(1, t1_targettemp) # self._setHotendTemperature(0, t0_nowtemp) # self._updateTargetHotendTemperature(0, t0_targettemp) continue if printer.activePrintJob is None: print_job = PrintJobOutputModel( output_controller=self._output_controller) printer.updateActivePrintJob(print_job) else: print_job = printer.activePrintJob if s.startswith("M997"): job_state = "offline" if "IDLE" in s: self._isPrinting = False self._isPause = False job_state = 'idle' elif "PRINTING" in s: self._isPrinting = True self._isPause = False job_state = 'printing' elif "PAUSE" in s: self._isPrinting = False self._isPause = True job_state = 'paused' print_job.updateState(job_state) printer.updateState(job_state) # self._updateJobState(job_state) continue # print_job.updateState('idle') # printer.updateState('idle') if s.startswith("M994"): if self.isBusy() and s.rfind("/") != -1: self._printing_filename = s[s.rfind("/") + 1:s.rfind(";")] else: self._printing_filename = "" print_job.updateName(self._printing_filename) # self.setJobName(self._printing_filename) continue if s.startswith("M992"): if self.isBusy(): tm = s[s.find("M992") + len("M992"):len(s)].replace( " ", "") mms = tm.split(":") self._printing_time = int(mms[0]) * 3600 + int( mms[1]) * 60 + int(mms[2]) else: self._printing_time = 0 # Logger.log("d", self._printing_time) print_job.updateTimeElapsed(self._printing_time) # self.setTimeElapsed(self._printing_time) # print_job.updateTimeTotal(self._printing_time) # self.setTimeTotal(self._printing_time) continue if s.startswith("M27"): if self.isBusy(): self._printing_progress = float( s[s.find("M27") + len("M27"):len(s)].replace( " ", "")) totaltime = self._printing_time / self._printing_progress * 100 else: self._printing_progress = 0 totaltime = self._printing_time * 100 # Logger.log("d", self._printing_time) # Logger.log("d", totaltime) # self.setProgress(self._printing_progress) print_job.updateTimeTotal(self._printing_time) print_job.updateTimeElapsed(self._printing_time * 2 - totaltime) continue if 'Begin file list' in s: self._sdFileList = True self.sdFiles = [] self.last_update_time = time.time() continue if 'End file list' in s: self._sdFileList = False continue if self._sdFileList: s = s.replace("\n", "").replace("\r", "") if s.lower().endswith("gcode") or s.lower().endswith( "gco") or s.lower.endswith("g"): self.sdFiles.append(s) continue except Exception as e: print(e) def _updateTargetBedTemperature(self, temperature): if self._target_bed_temperature == temperature: return False self._target_bed_temperature = temperature self.targetBedTemperatureChanged.emit() return True def _updateTargetHotendTemperature(self, index, temperature): if self._target_hotend_temperatures[index] == temperature: return False self._target_hotend_temperatures[index] = temperature self.targetHotendTemperaturesChanged.emit() return True def _createPrinterList(self): printer = PrinterOutputModel( output_controller=self._output_controller, number_of_extruders=self._number_of_extruders) printer.updateName(self.name) self._printers = [printer] self.printersChanged.emit() def _onRequestFinished(self, reply): http_status_code = reply.attribute( QNetworkRequest.HttpStatusCodeAttribute) self._isSending = True self._update_timer.start() self._sendCommand("M20") preferences = Application.getInstance().getPreferences() preferences.addPreference("mkswifi/autoprint", "True") # preferences.addPreference("mkswifi/savepath", "") # preferences.setValue("mkswifi/autoprint", str(self._progress_message.getOptionState())) if preferences.getValue("mkswifi/autoprint"): self._printFile() if not http_status_code: return def _onOptionStateChanged(self, optstate): preferences = Application.getInstance().getPreferences() preferences.setValue("mkswifi/autoprint", str(optstate)) def _cancelSendGcode(self, message_id, action_id): self._update_timer.start() self._isSending = False self._progress_message.hide() self._post_reply.abort() def CreateMKSController(self): Logger.log("d", "Creating additional ui components for mkscontroller.") # self.__additional_components_view = CuraApplication.getInstance().createQmlComponent(self._monitor_view_qml_path, {"mkscontroller": self}) self.__additional_components_view = Application.getInstance( ).createQmlComponent(self._monitor_view_qml_path, {"manager": self}) # trlist = CuraApplication.getInstance()._additional_components # for comp in trlist: Logger.log("w", "create mkscontroller ") if not self.__additional_components_view: Logger.log("w", "Could not create ui components for tft35.") return def _onGlobalContainerChanged(self) -> None: self._global_container_stack = Application.getInstance( ).getGlobalContainerStack() definitions = self._global_container_stack.definition.findDefinitions( key="cooling") Logger.log("d", definitions[0].label)
class MainWindow(QtWidgets.QMainWindow): def __init__(self, args): super().__init__() self.socket = QTcpSocket() self.socket.connectToHost('localhost', args.port) self.socket.readyRead.connect(self.readFromEmotool) self.setAttribute(QtCore.Qt.WA_DeleteOnClose) self.setWindowTitle("EmoTool - {}".format(version())) self.main_widget = QtWidgets.QTabWidget(self) plot_tab = QtWidgets.QWidget(self.main_widget) self.main_widget.addTab(plot_tab, "plot") l = QtWidgets.QVBoxLayout(plot_tab) self.plot_widget = plot_widget = pg.PlotWidget() l.addWidget(plot_widget) self.plot_widget = plot_widget # TODO - make a menu action, not open by default c = pg.console.ConsoleWidget(namespace=globals(), text="test console") self.main_widget.addTab(c, "debug") self.main_widget.setFocus() self.setCentralWidget(self.main_widget) self.statusBar().showMessage("Starting", 2000) self.ticks = defaultdict(list) self.vals = defaultdict(list) self.data_items = defaultdict(pg.PlotDataItem) self.incoming = b'' self.next_message_size = None @coalesce_meth(10) # Limit refreshes, they can be costly def log_variables(self, msgs): """ Show points on log window. both @ticks and @vars are arrays :param msgs: [(ticks_scalar, [(name, value)])] :return: """ new_ticks, new_vals = to_dicts(msgs) # TODO - better logic. Right now just shows last second, no zoom in possible. Plus second[ticks] is fixed last_tick = msgs[-1][0] cutoff_tick = last_tick - 8000 for name in set(self.ticks.keys()) | set(new_ticks.keys()): if name not in self.data_items: item = self.data_items[name] self.plot_widget.addItem(item) else: item = self.data_items[name] ticks = self.ticks[name] vals = self.vals[name] i_cutoff = bisect_left(ticks, cutoff_tick) del ticks[:i_cutoff] del vals[:i_cutoff] ticks.extend(new_ticks[name]) vals.extend(new_vals[name]) item.setData(ticks, vals) first_tick = min([ticks[0] for ticks in self.ticks.values()]) self.plot_widget.setXRange(first_tick, last_tick) def readFromEmotool(self): """ This is a temporary measure - instead of the better solution: serial2tcp process <-> app We have serial2tcp process <-> emotool <-> app Just to avoid rewriting the emotool parts to drop asyncio support so they can be reused for app and emotool. Quick transport costs calculation (copy cost): 20000 msg/second msg size < 100 bytes < 2 MB /second """ self.incoming += self.socket.readAll() N = len(self.incoming) i = 0 messages = [] while i < N: if self.next_message_size is None: if N - i < SIZEOF_UINT32: break self.next_message_size, = unpack('<i', self.incoming[i : i + SIZEOF_UINT32]) i += SIZEOF_UINT32 if self.next_message_size > N - i: break data = self.incoming[i : i + self.next_message_size] i += self.next_message_size messages.extend(loads(data)) self.next_message_size = None self.incoming = self.incoming[i:] if len(messages) > 0: self.log_variables(messages) def fileQuit(self): self.close() def closeEvent(self, ce): self.fileQuit()
class VNA(QMainWindow, Ui_VNA): max_size = 16384 def __init__(self): super(VNA, self).__init__() self.setupUi(self) # IP address validator rx = QRegExp('^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$') self.addrValue.setValidator(QRegExpValidator(rx, self.addrValue)) # state variables self.idle = True self.reading = False # sweep parameters self.sweep_start = 100 self.sweep_stop = 60000 self.sweep_size = 600 self.xaxis, self.sweep_step = np.linspace(self.sweep_start, self.sweep_stop, self.sweep_size, retstep = True) self.xaxis *= 1000 # buffer and offset for the incoming samples self.buffer = bytearray(24 * VNA.max_size) self.offset = 0 self.data = np.frombuffer(self.buffer, np.complex64) self.adc1 = np.zeros(VNA.max_size, np.complex64) self.adc2 = np.zeros(VNA.max_size, np.complex64) self.dac1 = np.zeros(VNA.max_size, np.complex64) self.open = np.zeros(VNA.max_size, np.complex64) self.short = np.zeros(VNA.max_size, np.complex64) self.load = np.zeros(VNA.max_size, np.complex64) self.dut = np.zeros(VNA.max_size, np.complex64) self.mode = 'dut' # create figure self.figure = Figure() self.figure.set_facecolor('none') self.canvas = FigureCanvas(self.figure) self.plotLayout.addWidget(self.canvas) # create navigation toolbar self.toolbar = NavigationToolbar(self.canvas, self.plotWidget, False) # initialize cursor self.cursor = None # remove subplots action actions = self.toolbar.actions() self.toolbar.removeAction(actions[7]) self.plotLayout.addWidget(self.toolbar) # create TCP socket self.socket = QTcpSocket(self) self.socket.connected.connect(self.connected) self.socket.readyRead.connect(self.read_data) self.socket.error.connect(self.display_error) # connect signals from buttons and boxes self.sweepFrame.setEnabled(False) self.dutSweep.setEnabled(False) self.connectButton.clicked.connect(self.start) self.writeButton.clicked.connect(self.write_cfg) self.readButton.clicked.connect(self.read_cfg) self.openSweep.clicked.connect(self.sweep_open) self.shortSweep.clicked.connect(self.sweep_short) self.loadSweep.clicked.connect(self.sweep_load) self.dutSweep.clicked.connect(self.sweep_dut) self.csvButton.clicked.connect(self.write_csv) self.s1pButton.clicked.connect(self.write_s1p) self.s2pButton.clicked.connect(self.write_s2p) self.startValue.valueChanged.connect(self.set_start) self.stopValue.valueChanged.connect(self.set_stop) self.sizeValue.valueChanged.connect(self.set_size) self.rateValue.addItems(['500', '100', '50', '10', '5', '1']) self.rateValue.lineEdit().setReadOnly(True) self.rateValue.lineEdit().setAlignment(Qt.AlignRight) for i in range(0, self.rateValue.count()): self.rateValue.setItemData(i, Qt.AlignRight, Qt.TextAlignmentRole) self.rateValue.currentIndexChanged.connect(self.set_rate) self.corrValue.valueChanged.connect(self.set_corr) self.levelValue.valueChanged.connect(self.set_level) self.openPlot.clicked.connect(self.plot_open) self.shortPlot.clicked.connect(self.plot_short) self.loadPlot.clicked.connect(self.plot_load) self.dutPlot.clicked.connect(self.plot_dut) self.smithPlot.clicked.connect(self.plot_smith) self.impPlot.clicked.connect(self.plot_imp) self.rcPlot.clicked.connect(self.plot_rc) self.swrPlot.clicked.connect(self.plot_swr) self.rlPlot.clicked.connect(self.plot_rl) self.gainPlot.clicked.connect(self.plot_gain) # create timer self.startTimer = QTimer(self) self.startTimer.timeout.connect(self.timeout) def start(self): if self.idle: self.connectButton.setEnabled(False) self.socket.connectToHost(self.addrValue.text(), 1001) self.startTimer.start(5000) else: self.stop() def stop(self): self.idle = True self.socket.abort() self.connectButton.setText('Connect') self.connectButton.setEnabled(True) self.sweepFrame.setEnabled(False) self.selectFrame.setEnabled(True) self.dutSweep.setEnabled(False) def timeout(self): self.display_error('timeout') def connected(self): self.startTimer.stop() self.idle = False self.set_start(self.startValue.value()) self.set_stop(self.stopValue.value()) self.set_size(self.sizeValue.value()) self.set_rate(self.rateValue.currentIndex()) self.set_corr(self.corrValue.value()) self.set_level(self.levelValue.value()) self.connectButton.setText('Disconnect') self.connectButton.setEnabled(True) self.sweepFrame.setEnabled(True) self.dutSweep.setEnabled(True) def read_data(self): if not self.reading: self.socket.readAll() return size = self.socket.bytesAvailable() self.progress.setValue((self.offset + size) / 24) limit = 24 * (self.sweep_size + 1) if self.offset + size < limit: self.buffer[self.offset:self.offset + size] = self.socket.read(size) self.offset += size else: self.buffer[self.offset:limit] = self.socket.read(limit - self.offset) self.adc1 = self.data[0::3] self.adc2 = self.data[1::3] self.dac1 = self.data[2::3] getattr(self, self.mode)[0:self.sweep_size] = self.adc1[1:self.sweep_size + 1] / self.dac1[1:self.sweep_size + 1] getattr(self, 'plot_%s' % self.mode)() self.reading = False self.sweepFrame.setEnabled(True) self.selectFrame.setEnabled(True) def display_error(self, socketError): self.startTimer.stop() if socketError == 'timeout': QMessageBox.information(self, 'VNA', 'Error: connection timeout.') else: QMessageBox.information(self, 'VNA', 'Error: %s.' % self.socket.errorString()) self.stop() def set_start(self, value): self.sweep_start = value self.xaxis, self.sweep_step = np.linspace(self.sweep_start, self.sweep_stop, self.sweep_size, retstep = True) self.xaxis *= 1000 if self.idle: return self.socket.write(struct.pack('<I', 0<<28 | int(value * 1000))) def set_stop(self, value): self.sweep_stop = value self.xaxis, self.sweep_step = np.linspace(self.sweep_start, self.sweep_stop, self.sweep_size, retstep = True) self.xaxis *= 1000 if self.idle: return self.socket.write(struct.pack('<I', 1<<28 | int(value * 1000))) def set_size(self, value): self.sweep_size = value self.xaxis, self.sweep_step = np.linspace(self.sweep_start, self.sweep_stop, self.sweep_size, retstep = True) self.xaxis *= 1000 if self.idle: return self.socket.write(struct.pack('<I', 2<<28 | int(value))) def set_rate(self, value): if self.idle: return rate = [1, 5, 10, 50, 100, 500][value] self.socket.write(struct.pack('<I', 3<<28 | int(rate))) def set_corr(self, value): if self.idle: return self.socket.write(struct.pack('<I', 4<<28 | int(value))) def set_level(self, value): if self.idle: return self.socket.write(struct.pack('<I', 5<<28 | int(32767 * np.power(10.0, value / 20.0)))) def sweep(self): if self.idle: return self.sweepFrame.setEnabled(False) self.selectFrame.setEnabled(False) self.socket.write(struct.pack('<I', 6<<28)) self.offset = 0 self.reading = True self.progress = QProgressDialog('Sweep status', 'Cancel', 0, self.sweep_size + 1) self.progress.setModal(True) self.progress.setMinimumDuration(1000) self.progress.canceled.connect(self.cancel) def cancel(self): self.offset = 0 self.reading = False self.socket.write(struct.pack('<I', 7<<28)) self.sweepFrame.setEnabled(True) self.selectFrame.setEnabled(True) def sweep_open(self): self.mode = 'open' self.sweep() def sweep_short(self): self.mode = 'short' self.sweep() def sweep_load(self): self.mode = 'load' self.sweep() def sweep_dut(self): self.mode = 'dut' self.sweep() def gain(self): size = self.sweep_size return self.dut[0:size]/self.short[0:size] def impedance(self): size = self.sweep_size return 50.0 * (self.open[0:size] - self.load[0:size]) * (self.dut[0:size] - self.short[0:size]) / ((self.load[0:size] - self.short[0:size]) * (self.open[0:size] - self.dut[0:size])) def gamma(self): z = self.impedance() return (z - 50.0)/(z + 50.0) def plot_gain(self): if self.cursor is not None: self.cursor.hide().disable() matplotlib.rcdefaults() self.figure.clf() self.figure.subplots_adjust(left = 0.12, bottom = 0.12, right = 0.88, top = 0.98) axes1 = self.figure.add_subplot(111) axes1.cla() axes1.xaxis.set_major_formatter(FuncFormatter(metric_prefix)) axes1.yaxis.set_major_formatter(FuncFormatter(metric_prefix)) axes1.tick_params('y', color = 'blue', labelcolor = 'blue') axes1.yaxis.label.set_color('blue') gain = self.gain() axes1.plot(self.xaxis, 20.0 * np.log10(np.absolute(gain)), color = 'blue', label = 'Gain') axes2 = axes1.twinx() axes2.spines['left'].set_color('blue') axes2.spines['right'].set_color('red') axes1.set_xlabel('Hz') axes1.set_ylabel('Gain, dB') axes2.set_ylabel('Phase angle') axes2.tick_params('y', color = 'red', labelcolor = 'red') axes2.yaxis.label.set_color('red') axes2.plot(self.xaxis, np.angle(gain, deg = True), color = 'red', label = 'Phase angle') self.cursor = datacursor(axes = self.figure.get_axes(), formatter = LabelFormatter(), display = 'multiple') self.canvas.draw() def plot_magphase(self, data): if self.cursor is not None: self.cursor.hide().disable() matplotlib.rcdefaults() self.figure.clf() self.figure.subplots_adjust(left = 0.12, bottom = 0.12, right = 0.88, top = 0.98) axes1 = self.figure.add_subplot(111) axes1.cla() axes1.xaxis.set_major_formatter(FuncFormatter(metric_prefix)) axes1.yaxis.set_major_formatter(FuncFormatter(metric_prefix)) axes1.tick_params('y', color = 'blue', labelcolor = 'blue') axes1.yaxis.label.set_color('blue') axes1.plot(self.xaxis, np.absolute(data), color = 'blue', label = 'Magnitude') axes2 = axes1.twinx() axes2.spines['left'].set_color('blue') axes2.spines['right'].set_color('red') axes1.set_xlabel('Hz') axes1.set_ylabel('Magnitude') axes2.set_ylabel('Phase angle') axes2.tick_params('y', color = 'red', labelcolor = 'red') axes2.yaxis.label.set_color('red') axes2.plot(self.xaxis, np.angle(data, deg = True), color = 'red', label = 'Phase angle') self.cursor = datacursor(axes = self.figure.get_axes(), formatter = LabelFormatter(), display = 'multiple') self.canvas.draw() def plot_open(self): self.plot_magphase(self.open[0:self.sweep_size]) def plot_short(self): self.plot_magphase(self.short[0:self.sweep_size]) def plot_load(self): self.plot_magphase(self.load[0:self.sweep_size]) def plot_dut(self): self.plot_magphase(self.dut[0:self.sweep_size]) def plot_smith_grid(self, axes, color): load = 50.0 ticks = np.array([0.0, 0.2, 0.5, 1.0, 2.0, 5.0]) for tick in ticks * load: axis = np.logspace(-4, np.log10(1.0e3), 200) * load z = tick + 1.0j * axis gamma = (z - load)/(z + load) axes.plot(gamma.real, gamma.imag, color = color, linewidth = 0.4, alpha = 0.3) axes.plot(gamma.real, -gamma.imag, color = color, linewidth = 0.4, alpha = 0.3) z = axis + 1.0j * tick gamma = (z - load)/(z + load) axes.plot(gamma.real, gamma.imag, color = color, linewidth = 0.4, alpha = 0.3) axes.plot(gamma.real, -gamma.imag, color = color, linewidth = 0.4, alpha = 0.3) if tick == 0.0: axes.text(1.0, 0.0, u'\u221E', color = color, ha = 'left', va = 'center', clip_on = True, fontsize = 18.0) axes.text(-1.0, 0.0, u'0\u03A9', color = color, ha = 'left', va = 'bottom', clip_on = True, fontsize = 12.0) continue lab = u'%d\u03A9' % tick x = (tick - load) / (tick + load) axes.text(x, 0.0, lab, color = color, ha = 'left', va = 'bottom', clip_on = True, fontsize = 12.0) lab = u'j%d\u03A9' % tick z = 1.0j * tick gamma = (z - load)/(z + load) * 1.05 x = gamma.real y = gamma.imag angle = np.angle(gamma) * 180.0 / np.pi - 90.0 axes.text(x, y, lab, color = color, ha = 'center', va = 'center', clip_on = True, rotation = angle, fontsize = 12.0) lab = u'-j%d\u03A9' % tick axes.text(x, -y, lab, color = color, ha = 'center', va = 'center', clip_on = True, rotation = -angle, fontsize = 12.0) def plot_smith(self): if self.cursor is not None: self.cursor.hide().disable() matplotlib.rcdefaults() self.figure.clf() self.figure.subplots_adjust(left = 0.0, bottom = 0.0, right = 1.0, top = 1.0) axes1 = self.figure.add_subplot(111) self.plot_smith_grid(axes1, 'blue') gamma = self.gamma() plot, = axes1.plot(gamma.real, gamma.imag, color = 'red') axes1.axis('equal') axes1.set_xlim(-1.12, 1.12) axes1.set_ylim(-1.12, 1.12) axes1.xaxis.set_visible(False) axes1.yaxis.set_visible(False) for loc, spine in axes1.spines.items(): spine.set_visible(False) self.cursor = datacursor(plot, formatter = SmithFormatter(self.xaxis), display = 'multiple') self.canvas.draw() def plot_imp(self): self.plot_magphase(self.impedance()) def plot_rc(self): self.plot_magphase(self.gamma()) def plot_swr(self): if self.cursor is not None: self.cursor.hide().disable() matplotlib.rcdefaults() self.figure.clf() self.figure.subplots_adjust(left = 0.12, bottom = 0.12, right = 0.88, top = 0.98) axes1 = self.figure.add_subplot(111) axes1.cla() axes1.xaxis.set_major_formatter(FuncFormatter(metric_prefix)) axes1.yaxis.set_major_formatter(FuncFormatter(metric_prefix)) axes1.set_xlabel('Hz') axes1.set_ylabel('SWR') magnitude = np.absolute(self.gamma()) swr = np.maximum(1.0, np.minimum(100.0, (1.0 + magnitude) / np.maximum(1.0e-20, 1.0 - magnitude))) axes1.plot(self.xaxis, swr, color = 'blue', label = 'SWR') self.cursor = datacursor(axes = self.figure.get_axes(), formatter = LabelFormatter(), display = 'multiple') self.canvas.draw() def plot_rl(self): if self.cursor is not None: self.cursor.hide().disable() matplotlib.rcdefaults() self.figure.clf() self.figure.subplots_adjust(left = 0.12, bottom = 0.12, right = 0.88, top = 0.98) axes1 = self.figure.add_subplot(111) axes1.cla() axes1.xaxis.set_major_formatter(FuncFormatter(metric_prefix)) axes1.set_xlabel('Hz') axes1.set_ylabel('Return loss, dB') magnitude = np.absolute(self.gamma()) axes1.plot(self.xaxis, 20.0 * np.log10(magnitude), color = 'blue', label = 'Return loss') self.cursor = datacursor(axes = self.figure.get_axes(), formatter = LabelFormatter(), display = 'multiple') self.canvas.draw() def write_cfg(self): dialog = QFileDialog(self, 'Write configuration settings', '.', '*.ini') dialog.setDefaultSuffix('ini') dialog.setAcceptMode(QFileDialog.AcceptSave) dialog.setOptions(QFileDialog.DontConfirmOverwrite) if dialog.exec() == QDialog.Accepted: name = dialog.selectedFiles() settings = QSettings(name[0], QSettings.IniFormat) self.write_cfg_settings(settings) def read_cfg(self): dialog = QFileDialog(self, 'Read configuration settings', '.', '*.ini') dialog.setDefaultSuffix('ini') dialog.setAcceptMode(QFileDialog.AcceptOpen) if dialog.exec() == QDialog.Accepted: name = dialog.selectedFiles() settings = QSettings(name[0], QSettings.IniFormat) self.read_cfg_settings(settings) def write_cfg_settings(self, settings): settings.setValue('addr', self.addrValue.text()) settings.setValue('start', self.startValue.value()) settings.setValue('stop', self.stopValue.value()) settings.setValue('rate', self.rateValue.currentIndex()) settings.setValue('corr', self.corrValue.value()) size = self.sizeValue.value() settings.setValue('size', size) for i in range(0, size): settings.setValue('open_real_%d' % i, float(self.open.real[i])) settings.setValue('open_imag_%d' % i, float(self.open.imag[i])) for i in range(0, size): settings.setValue('short_real_%d' % i, float(self.short.real[i])) settings.setValue('short_imag_%d' % i, float(self.short.imag[i])) for i in range(0, size): settings.setValue('load_real_%d' % i, float(self.load.real[i])) settings.setValue('load_imag_%d' % i, float(self.load.imag[i])) for i in range(0, size): settings.setValue('dut_real_%d' % i, float(self.dut.real[i])) settings.setValue('dut_imag_%d' % i, float(self.dut.imag[i])) def read_cfg_settings(self, settings): self.addrValue.setText(settings.value('addr', '192.168.1.100')) self.startValue.setValue(settings.value('start', 100, type = int)) self.stopValue.setValue(settings.value('stop', 60000, type = int)) self.rateValue.setCurrentIndex(settings.value('rate', 0, type = int)) self.corrValue.setValue(settings.value('corr', 0, type = int)) size = settings.value('size', 600, type = int) self.sizeValue.setValue(size) for i in range(0, size): real = settings.value('open_real_%d' % i, 0.0, type = float) imag = settings.value('open_imag_%d' % i, 0.0, type = float) self.open[i] = real + 1.0j * imag for i in range(0, size): real = settings.value('short_real_%d' % i, 0.0, type = float) imag = settings.value('short_imag_%d' % i, 0.0, type = float) self.short[i] = real + 1.0j * imag for i in range(0, size): real = settings.value('load_real_%d' % i, 0.0, type = float) imag = settings.value('load_imag_%d' % i, 0.0, type = float) self.load[i] = real + 1.0j * imag for i in range(0, size): real = settings.value('dut_real_%d' % i, 0.0, type = float) imag = settings.value('dut_imag_%d' % i, 0.0, type = float) self.dut[i] = real + 1.0j * imag def write_csv(self): dialog = QFileDialog(self, 'Write csv file', '.', '*.csv') dialog.setDefaultSuffix('csv') dialog.setAcceptMode(QFileDialog.AcceptSave) dialog.setOptions(QFileDialog.DontConfirmOverwrite) if dialog.exec() == QDialog.Accepted: name = dialog.selectedFiles() fh = open(name[0], 'w') gamma = self.gamma() size = self.sizeValue.value() fh.write('frequency;open.real;open.imag;short.real;short.imag;load.real;load.imag;dut.real;dut.imag\n') for i in range(0, size): fh.write('0.0%.8d;%12.9f;%12.9f;%12.9f;%12.9f;%12.9f;%12.9f;%12.9f;%12.9f\n' % (self.xaxis[i], self.open.real[i], self.open.imag[i], self.short.real[i], self.short.imag[i], self.load.real[i], self.load.imag[i], self.dut.real[i], self.dut.imag[i])) fh.close() def write_s1p(self): dialog = QFileDialog(self, 'Write s1p file', '.', '*.s1p') dialog.setDefaultSuffix('s1p') dialog.setAcceptMode(QFileDialog.AcceptSave) dialog.setOptions(QFileDialog.DontConfirmOverwrite) if dialog.exec() == QDialog.Accepted: name = dialog.selectedFiles() fh = open(name[0], 'w') gamma = self.gamma() size = self.sizeValue.value() fh.write('# GHz S MA R 50\n') for i in range(0, size): fh.write('0.0%.8d %8.6f %7.2f\n' % (self.xaxis[i], np.absolute(gamma[i]), np.angle(gamma[i], deg = True))) fh.close() def write_s2p(self): dialog = QFileDialog(self, 'Write s2p file', '.', '*.s2p') dialog.setDefaultSuffix('s2p') dialog.setAcceptMode(QFileDialog.AcceptSave) dialog.setOptions(QFileDialog.DontConfirmOverwrite) if dialog.exec() == QDialog.Accepted: name = dialog.selectedFiles() fh = open(name[0], 'w') gain = self.gain() gamma = self.gamma() size = self.sizeValue.value() fh.write('# GHz S MA R 50\n') for i in range(0, size): fh.write('0.0%.8d %8.6f %7.2f %8.6f %7.2f 0.000000 0.00 0.000000 0.00\n' % (self.xaxis[i], np.absolute(gamma[i]), np.angle(gamma[i], deg = True), np.absolute(gain[i]), np.angle(gain[i], deg = True))) fh.close()
class Main(QMainWindow): def __init__(self, *args): super(Main, self).__init__(*args) loadUi('mainwindow.ui', self) self.host.setText("localhost") self.port.setText("11010") self.prompt.setText("M114") self.conn = QTcpSocket(self) self.conn.readyRead.connect(self.readSocket) self.conn.error.connect(self.socketError) self.conn.connected.connect(self.socketConnect) self.conn.disconnected.connect(self.socketDisconnect) self.connected = False self.actionSave.triggered.connect(self.save) self.prompt.setFocus() self.do_connect() def append(self, text): self.text.append(text) if self.autoscroll.isChecked(): c = self.text.textCursor() c.movePosition(QTextCursor.End, QTextCursor.MoveAnchor) self.text.setTextCursor(c) def readSocket(self): r = self.conn.readAll() if r: r = str(r).strip() for chunk in r.splitlines(): if chunk: if chunk[0] == '<': self.text.setTextColor(QColor(200, 0, 0)) elif chunk[0] == '>': self.text.setTextColor(QColor(0, 200, 0)) else: self.text.setTextColor(QColor(0, 0, 200)) self.append(chunk) def info(self, errtext): self.text.setTextColor(QColor(20, 20, 20)) self.append(errtext) def err(self, errtext): self.text.setTextColor(QColor(100, 0, 0)) self.append(errtext) def socketDisconnect(self): self.connected = False self.err("Disconnected") def socketConnect(self): self.connected = True self.info("Connected") def socketError(self, socketError): if socketError == QAbstractSocket.RemoteHostClosedError: pass elif socketError == QAbstractSocket.HostNotFoundError: self.err("The host was not found. Please check the host name and " "port settings.") elif socketError == QAbstractSocket.ConnectionRefusedError: self.err("The connection was refused by the peer. Make sure the " "server is running, and check that the host name " "and port settings are correct.") else: self.err("The following error occurred: {0}" .format(self.conn.errorString())) def save(self): fname, sel = QFileDialog.getSaveFileName( self, 'Save Log',) #'/path/to/default/directory', FIXME: lastused #selectedFilter='*.txt') if fname: with open(fname, 'w+') as f: f.write(self.text.toPlainText()) def do_connect(self): self.conn.abort() self.conn.connectToHost(self.host.text(), int(self.port.text())) @pyqtSlot() def on_connect_clicked(self): self.do_connect() self.prompt.setFocus() @pyqtSlot() def on_send_clicked(self): if not self.connected: self.err("Not connected") return out = (self.prompt.text() + '\n').encode('ascii') self.conn.write(out) @pyqtSlot() def on_right_on_clicked(self): self.action("e1")
class Scanner(QMainWindow, Ui_Scanner): def __init__(self): super(Scanner, self).__init__() self.setupUi(self) # IP address validator rx = QRegExp('^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$') self.addrValue.setValidator(QRegExpValidator(rx, self.addrValue)) # state variable self.idle = True # number of samples to show on the plot self.size = 512 * 512 self.freq = 143.0 # buffer and offset for the incoming samples self.buffer = bytearray(8 * self.size) self.offset = 0 self.data = np.frombuffer(self.buffer, np.int32) # create figure figure = Figure() figure.set_facecolor('none') self.axes = figure.add_subplot(111) self.canvas = FigureCanvas(figure) self.plotLayout.addWidget(self.canvas) self.axes.axis((0.0, 512.0, 0.0, 512.0)) x, y = np.meshgrid(np.linspace(0.0, 512.0, 513), np.linspace(0.0, 512.0, 513)) z = x / 512.0 + y * 0.0 self.mesh = self.axes.pcolormesh(x, y, z, cmap = cm.plasma) # create navigation toolbar self.toolbar = NavigationToolbar(self.canvas, self.plotWidget, False) # remove subplots action actions = self.toolbar.actions() if int(matplotlib.__version__[0]) < 2: self.toolbar.removeAction(actions[7]) else: self.toolbar.removeAction(actions[6]) self.plotLayout.addWidget(self.toolbar) # create TCP socket self.socket = QTcpSocket(self) self.socket.connected.connect(self.connected) self.socket.readyRead.connect(self.read_data) self.socket.error.connect(self.display_error) # connect signals from buttons and boxes self.connectButton.clicked.connect(self.start) self.scanButton.clicked.connect(self.scan) self.periodValue.valueChanged.connect(self.set_period) self.trgtimeValue.valueChanged.connect(self.set_trgtime) self.trginvCheck.stateChanged.connect(self.set_trginv) self.shdelayValue.valueChanged.connect(self.set_shdelay) self.shtimeValue.valueChanged.connect(self.set_shtime) self.shinvCheck.stateChanged.connect(self.set_shinv) self.acqdelayValue.valueChanged.connect(self.set_acqdelay) self.samplesValue.valueChanged.connect(self.set_samples) self.pulsesValue.valueChanged.connect(self.set_pulses) # create timers self.startTimer = QTimer(self) self.startTimer.timeout.connect(self.timeout) self.meshTimer = QTimer(self) self.meshTimer.timeout.connect(self.update_mesh) # set default values self.periodValue.setValue(200.0) def start(self): if self.idle: self.connectButton.setEnabled(False) self.socket.connectToHost(self.addrValue.text(), 1001) self.startTimer.start(5000) else: self.stop() def stop(self): self.idle = True self.socket.abort() self.offset = 0 self.connectButton.setText('Connect') self.connectButton.setEnabled(True) self.scanButton.setEnabled(True) def timeout(self): self.display_error('timeout') def connected(self): self.startTimer.stop() self.idle = False self.set_period(self.periodValue.value()) self.set_trgtime(self.trgtimeValue.value()) self.set_trginv(self.trginvCheck.checkState()) self.set_shdelay(self.shdelayValue.value()) self.set_shtime(self.shtimeValue.value()) self.set_shinv(self.shinvCheck.checkState()) self.set_acqdelay(self.acqdelayValue.value()) self.set_samples(self.samplesValue.value()) self.set_pulses(self.pulsesValue.value()) # start pulse generators self.socket.write(struct.pack('<I', 9<<28)) self.connectButton.setText('Disconnect') self.connectButton.setEnabled(True) self.scanButton.setEnabled(True) def read_data(self): size = self.socket.bytesAvailable() if self.offset + size < 8 * self.size: self.buffer[self.offset:self.offset + size] = self.socket.read(size) self.offset += size else: self.meshTimer.stop() self.buffer[self.offset:8 * self.size] = self.socket.read(8 * self.size - self.offset) self.offset = 0 self.update_mesh() self.scanButton.setEnabled(True) def display_error(self, socketError): self.startTimer.stop() if socketError == 'timeout': QMessageBox.information(self, 'Scanner', 'Error: connection timeout.') else: QMessageBox.information(self, 'Scanner', 'Error: %s.' % self.socket.errorString()) self.stop() def set_period(self, value): # set maximum delays and times to half period maximum = int(value * 5.0 + 0.5) / 10.0 self.trgtimeValue.setMaximum(maximum) self.shdelayValue.setMaximum(maximum) self.shtimeValue.setMaximum(maximum) self.acqdelayValue.setMaximum(maximum) # set maximum number of samples per pulse maximum = int(value * 500.0 + 0.5) / 10.0 if maximum > 256.0: maximum = 256.0 self.samplesValue.setMaximum(maximum) shdelay = value * 0.25 samples = value * 0.5 if self.idle: return self.socket.write(struct.pack('<I', 0<<28 | int(value * self.freq))) def set_trgtime(self, value): if self.idle: return self.socket.write(struct.pack('<I', 1<<28 | int(value * self.freq))) def set_trginv(self, checked): if self.idle: return self.socket.write(struct.pack('<I', 2<<28 | int(checked == Qt.Checked))) def set_shdelay(self, value): if self.idle: return self.socket.write(struct.pack('<I', 3<<28 | int(value * self.freq))) def set_shtime(self, value): if self.idle: return self.socket.write(struct.pack('<I', 4<<28 | int(value * self.freq))) def set_shinv(self, checked): if self.idle: return self.socket.write(struct.pack('<I', 5<<28 | int(checked == Qt.Checked))) def set_acqdelay(self, value): if self.idle: return self.socket.write(struct.pack('<I', 6<<28 | int(value * self.freq))) def set_samples(self, value): if self.idle: return self.socket.write(struct.pack('<I', 7<<28 | int(value))) def set_pulses(self, value): if self.idle: return self.socket.write(struct.pack('<I', 8<<28 | int(value))) def scan(self): if self.idle: return self.scanButton.setEnabled(False) self.data[:] = np.zeros(2 * 512 * 512, np.int32) self.update_mesh() self.socket.write(struct.pack('<I', 10<<28)) self.meshTimer.start(1000) def update_mesh(self): self.mesh.set_array(self.data[0::2]/(self.samplesValue.value() * self.pulsesValue.value() * 8192.0)) self.canvas.draw()
class TcpSocketClient(QObject, ICommunicateTCPIP): readyReadClientID = pyqtSignal(int) disconnectedClientID = pyqtSignal(int) def __init__(self, parent=None): super(TcpSocketClient, self).__init__() self.tcpSocketClient = QTcpSocket(parent) self.setIsConnected(False) self.setTcpClientID(0) self.setPeerFullAddrStr(str()) self.tcpSocketClient.readyRead.connect(self.dataReceived) self.connectClientDisconnect(self.disConnected) def createConnection(self, ip, port): self.tcpSocketClient.connectToHost(ip, port) # 向目的ip服务器的端口进行连接 isOK = self.tcpSocketClient.waitForConnected( 2000) # 等2s, 若还无法连上服务器就算失败 self.setIsConnected(isOK) return isOK def send(self, data): """ 发送 :param data: str or bytearray :return: int """ if len(data) == 0 or data is None: return if isinstance(data, str): return self.tcpSocketClient.write(QByteArray(bytes(data, 'utf8'))) else: return self.tcpSocketClient.write(QByteArray(data)) def connectRec(self, slotRec): self.tcpSocketClient.readyRead.connect(slotRec) def connectClientDisconnect(self, slotRec): self.tcpSocketClient.disconnected.connect(slotRec) def read(self): """ 读取数据 :return: bytes """ datagram = self.tcpSocketClient.readAll() self.setRecSrcIp(self.tcpSocketClient.peerAddress()) self.setRecSrcPort(self.tcpSocketClient.peerPort()) return datagram.data() def close(self): self.tcpSocketClient.close() def connectRecWithClientID(self, slotRec): self.readyReadClientID.connect(slotRec) def connectDisconnectWithClientID(self, slotRec): self.disconnectedClientID.connect(slotRec) def setSocketDescriptor(self, socketDescriptor): return self.tcpSocketClient.setSocketDescriptor(socketDescriptor) @pyqtSlot() def dataReceived(self): self.readyReadClientID.emit(self.getTcpClientID()) @pyqtSlot() def disConnected(self): self.disconnectedClientID.emit(self.getTcpClientID()) def setIsConnected(self, isConnected): self.isConnected = isConnected def getIsConnected(self): return self.isConnected def setTcpClientID(self, tcpClientID): self.tcpClientID = tcpClientID def getTcpClientID(self): return self.tcpClientID def setPeerFullAddrStr(self, peerFullAddrStr): self.peerFullAddrStr = peerFullAddrStr def getPeerFullAddrStr(self): return self.peerFullAddrStr def getPeerIp(self): return self.tcpSocketClient.peerAddress().toString() def getPeerPort(self): return self.tcpSocketClient.peerPort()
class sendMessage(QObject): doSomeThing = pyqtSignal(str) # 收到一条命令去执行 def __init__(self, parent=None): # 初始化发送对象,首先要先建立连接 super(sendMessage, self).__init__(parent) self.socket = QTcpSocket() self.nextBlockSize = 0 self.socket.connectToHost(IP, PORT) self.deviceInfo = deviceInfo(DEVICE_FIX_ID, REGION_PROVINCE, REGION_CITY, REGION_AREA) # 保存盒子信息,可从某个文件读取 self.socket.connected.connect(self.initConnected) # 初始化连接,第一次连上就发送信息 self.socket.waitForConnected() # 等待设备连接完成 time.sleep(0.1) self.socket.readyRead.connect(self.readResponse) self.socket.disconnected.connect(self.serverHasStopped) self.socket.error.connect(self.serverHasError) self.doSomeThing.connect(self.doWhat) # 收到某条命令要执行的函数 def doWhat(self, order): # 收到dosome命令要执行的函数 if order: if ',' in order: order, model_type = order.split(",") else: model_type = None order_instance = generateOrder(order) t = Thread(target=order_instance.run, args=(self.deviceInfo, IP, 8870, model_type)) t.start() def fileToBytes(self, fileName): # 将文件转换成二进制 file = QFile(fileName) print(file.size()) count = 0 with open(fileName, 'rb') as f: while 1: filedata = f.read(1024) if not filedata: break count = count + filedata.__len__() print(count) @startSendMessage def initConnected( self, stream): # 每次连接上后 发送盒子的设备信息 fixID(固定id) region(所在地区) stream.writeQString('deviceInfo') # 设定信息类型 state deviceInfoToByte = pickle.dumps( deviceInfoJson ) # 将设备信息序列化成二进制发送 s = pickle.dumps(sendMessage1.deviceInfo) stream.writeBytes(deviceInfoToByte) ''' 接下来还有几点 1、盒子连接建立,发送设备信息。接收端接收一次。 2、规定好发送文件的格式 3、设计数据库 4、与网页交互 ''' @startSendMessage def sendFileBytes(self, stream, filePath, fileBytes): # stream 由装饰器传值 状态 文件名 文件字节 file = QFile(filePath) print(filePath) stream.writeQString('sendFile') # 发送文件 状态 stream.writeQString(file.fileName()) # 发送文件的名字 print(file.size()) stream.writeQString(str(file.size())) # 发送文件的大小 stream.writeBytes(fileBytes) def sendFile(self, filePath): with open(filePath, 'rb') as f: count = 0 while 1: # 循环传输 filedata = f.read(204800) print(filedata.__sizeof__()) if not filedata: break self.sendFileBytes(filePath, filedata) count = count + filedata.__sizeof__() print(count) @startSendMessage def sendImage(self, stream, imagePath, kind): # 传递图片,与图片类型 状态 图片类型 图片 stream.writeQString('sendImage') stream.writeQString(kind) stream.writeBytes(self.fileToBytes(imagePath)) @startSendMessage def sendResult( self, stream, kind, result, startTime, usedTime): # ,发送成功的状态,发送来 success 日期 信号类型 识别结果 识别开始时间 识别时间 stream.writeQString('successResult') # 发送成功状态 dateNow = time.strftime("%Y-%m-%d", time.localtime()) resultObject = resultInfo(dateNow, kind, result, startTime, usedTime) # 结果对象 (日期,类型,结果,开始时间,识别用时) resultBytes = pickle.dumps(resultObject) stream.writeBytes(resultBytes) def readResponse(self): # 收命令,要做的事情, stream = QDataStream(self.socket) print('--------------------') print('服务器响应') stream.setVersion(QDataStream.Qt_5_7) while True: self.nextBlockSize = 0 if self.nextBlockSize == 0: if self.socket.bytesAvailable() < SIZEOF_UINT16: print('没有内容了') break self.nextBlockSize = stream.readUInt16() else: print('错误') # 客户端主动断开时,去掉字典中的对应,在这里做一部分操作。 # 客户端主动断开的时候,要将其从self.myParent.sockeIdToSocketDict self.myParent.fixIdToSocketIdDict 中删掉 break if self.socket.bytesAvailable() < self.nextBlockSize: print("错误2") if (not self.socket.waitForReadyRead(60000) or self.socket.bytesAvailable() < self.nextBlockSize): break state = stream.readQString() # 读命令 sendModel print('state==' + state) if state == 'SENDFILE': filename = stream.readQString() # 读文件名 fileSize = stream.readInt() # 读文件大小 with open('../TEST/' + filename, 'ab') as f: while self.nextBlockSize > 0: fileBytes = stream.readBytes() # 读文件部分字节 f.write(fileBytes) print(fileBytes.__len__()) self.nextBlockSize = stream.readUInt64() print('self.nextBlockSize:' + str(self.nextBlockSize)) state = stream.readQString() filename = stream.readQString() # 读文件名 fileSize = stream.readInt() # 读文件大小 print('filename:' + filename) print('fileSize:' + str(fileSize)) elif state == 'test': print(stream.readQString()) elif state == 'ORDER': # 收到一条命令 要执行的命令 order = stream.readQString() # 读是什么命令 if order: # shou dao doThing self.doSomeThing.emit(order) def serverHasStopped(self): print('连接断开') self.socket.close() self.socket = QTcpSocket() print(self.socket.state()) # while self.socket.state() == 0: # print("重新连接") # time.sleep(5) # self.socket.connectToHost(IP, PORT) # self.socket.waitForConnected() # self.socket.close() def serverHasError(self, error): self.socket.close()
class IrcWidget(QWidget, Ui_IrcWidget): """ Class implementing the IRC window. @signal autoConnected() emitted after an automatic connection was initiated """ autoConnected = pyqtSignal() ServerDisconnected = 1 ServerConnected = 2 ServerConnecting = 3 def __init__(self, parent=None): """ Constructor @param parent reference to the parent widget (QWidget) """ super(IrcWidget, self).__init__(parent) self.setupUi(self) from .IrcNetworkManager import IrcNetworkManager self.__ircNetworkManager = IrcNetworkManager(self) self.__leaveButton = QToolButton(self) self.__leaveButton.setIcon( UI.PixmapCache.getIcon("ircCloseChannel.png")) self.__leaveButton.setToolTip( self.tr("Press to leave the current channel")) self.__leaveButton.clicked.connect(self.__leaveChannel) self.__leaveButton.setEnabled(False) self.channelsWidget.setCornerWidget( self.__leaveButton, Qt.BottomRightCorner) self.channelsWidget.setTabsClosable(False) if not isMacPlatform(): self.channelsWidget.setTabPosition(QTabWidget.South) height = self.height() self.splitter.setSizes([height * 0.6, height * 0.4]) self.__channelList = [] self.__channelTypePrefixes = "" self.__userName = "" self.__identityName = "" self.__quitMessage = "" self.__nickIndex = -1 self.__nickName = "" self.__server = None self.__registering = False self.__connectionState = IrcWidget.ServerDisconnected self.__sslErrorLock = False self.__buffer = "" self.__userPrefix = {} self.__socket = None if SSL_AVAILABLE: self.__sslErrorHandler = E5SslErrorHandler(self) else: self.__sslErrorHandler = None self.__patterns = [ # :[email protected] PRIVMSG bar_ :some long message (re.compile(r":([^!]+)!([^ ]+)\sPRIVMSG\s([^ ]+)\s:(.*)"), self.__query), # :foo.bar.net COMMAND some message (re.compile(r""":([^ ]+)\s+([A-Z]+)\s+(.+)"""), self.__handleNamedMessage), # :foo.bar.net 123 * :info (re.compile(r""":([^ ]+)\s+(\d{3})\s+(.+)"""), self.__handleNumericMessage), # PING :ping message (re.compile(r"""PING\s+:(.*)"""), self.__ping), ] self.__prefixRe = re.compile(r""".*\sPREFIX=\((.*)\)([^ ]+).*""") self.__chanTypesRe = re.compile(r""".*\sCHANTYPES=([^ ]+).*""") ircPic = UI.PixmapCache.getPixmap("irc128.png") self.__emptyLabel = QLabel() self.__emptyLabel.setPixmap(ircPic) self.__emptyLabel.setAlignment(Qt.AlignVCenter | Qt.AlignHCenter) self.channelsWidget.addTab(self.__emptyLabel, "") # all initialized, do connections now self.__ircNetworkManager.dataChanged.connect(self.__networkDataChanged) self.networkWidget.initialize(self.__ircNetworkManager) self.networkWidget.connectNetwork.connect(self.__connectNetwork) self.networkWidget.editNetwork.connect(self.__editNetwork) self.networkWidget.joinChannel.connect(self.__joinChannel) self.networkWidget.nickChanged.connect(self.__changeNick) self.networkWidget.sendData.connect(self.__send) self.networkWidget.away.connect(self.__away) self.networkWidget.autoConnected.connect(self.autoConnected) def shutdown(self): """ Public method to shut down the widget. @return flag indicating successful shutdown (boolean) """ if self.__server: if Preferences.getIrc("AskOnShutdown"): ok = E5MessageBox.yesNo( self, self.tr("Disconnect from Server"), self.tr( """<p>Do you really want to disconnect from""" """ <b>{0}</b>?</p><p>All channels will be closed.""" """</p>""").format(self.__server.getName())) else: ok = True if ok: self.__socket.blockSignals(True) self.__send("QUIT :" + self.__quitMessage) self.__socket.flush() self.__socket.close() self.__socket.deleteLater() self.__socket = None else: ok = True if ok: self.__ircNetworkManager.close() return ok def autoConnect(self): """ Public method to initiate the IRC auto connection. """ self.networkWidget.autoConnect() def __connectNetwork(self, name, connect, silent=False): """ Private slot to connect to or disconnect from the given network. @param name name of the network to connect to (string) @param connect flag indicating to connect (boolean) @keyparam silent flag indicating a silent connect/disconnect (boolean) """ if connect: network = self.__ircNetworkManager.getNetwork(name) if network: self.__server = network.getServer() self.__identityName = network.getIdentityName() identity = self.__ircNetworkManager.getIdentity( self.__identityName) self.__userName = identity.getIdent() self.__quitMessage = identity.getQuitMessage() if self.__server: useSSL = self.__server.useSSL() if useSSL and not SSL_AVAILABLE: E5MessageBox.critical( self, self.tr("SSL Connection"), self.tr( """An encrypted connection to the IRC""" """ network was requested but SSL is not""" """ available. Please change the server""" """ configuration.""")) return if useSSL: # create SSL socket self.__socket = QSslSocket(self) self.__socket.encrypted.connect(self.__hostConnected) self.__socket.sslErrors.connect(self.__sslErrors) else: # create TCP socket self.__socket = QTcpSocket(self) self.__socket.connected.connect(self.__hostConnected) self.__socket.hostFound.connect(self.__hostFound) self.__socket.disconnected.connect(self.__hostDisconnected) self.__socket.readyRead.connect(self.__readyRead) self.__socket.error.connect(self.__tcpError) self.__connectionState = IrcWidget.ServerConnecting if useSSL: self.networkWidget.addServerMessage( self.tr("Info"), self.tr("Looking for server {0} (port {1})" " using an SSL encrypted connection" "...").format(self.__server.getName(), self.__server.getPort())) self.__socket.connectToHostEncrypted( self.__server.getName(), self.__server.getPort()) else: self.networkWidget.addServerMessage( self.tr("Info"), self.tr( "Looking for server {0} (port {1})...").format( self.__server.getName(), self.__server.getPort())) self.__socket.connectToHost(self.__server.getName(), self.__server.getPort()) else: if silent: ok = True else: ok = E5MessageBox.yesNo( self, self.tr("Disconnect from Server"), self.tr("""<p>Do you really want to disconnect from""" """ <b>{0}</b>?</p><p>All channels will be""" """ closed.</p>""") .format(self.__server.getName())) if ok: self.networkWidget.addServerMessage( self.tr("Info"), self.tr("Disconnecting from server {0}...").format( self.__server.getName())) self.__closeAllChannels() self.__send("QUIT :" + self.__quitMessage) self.__socket and self.__socket.flush() self.__socket and self.__socket.close() self.__userName = "" self.__identityName = "" self.__quitMessage = "" def __editNetwork(self, name): """ Private slot to edit the network configuration. @param name name of the network to edit (string) """ from .IrcNetworkListDialog import IrcNetworkListDialog dlg = IrcNetworkListDialog(self.__ircNetworkManager, self) dlg.exec_() def __networkDataChanged(self): """ Private slot handling changes of the network and identity definitions. """ identity = self.__ircNetworkManager.getIdentity(self.__identityName) if identity: partMsg = identity.getPartMessage() for channel in self.__channelList: channel.setPartMessage(partMsg) def __joinChannel(self, name, key=""): """ Private slot to join a channel. @param name name of the channel (string) @param key key of the channel (string) """ # step 1: check, if this channel is already joined for channel in self.__channelList: if channel.name() == name: return from .IrcChannelWidget import IrcChannelWidget channel = IrcChannelWidget(self) channel.setName(name) channel.setUserName(self.__nickName) identity = self.__ircNetworkManager.getIdentity(self.__identityName) channel.setPartMessage(identity.getPartMessage()) channel.setUserPrivilegePrefix(self.__userPrefix) channel.initAutoWho() channel.sendData.connect(self.__send) channel.sendCtcpReply.connect(self.__sendCtcpReply) channel.channelClosed.connect(self.__closeChannel) channel.openPrivateChat.connect(self.__openPrivate) self.channelsWidget.addTab(channel, name) self.__channelList.append(channel) self.channelsWidget.setCurrentWidget(channel) joinCommand = ["JOIN", name] if key: joinCommand.append(key) self.__send(" ".join(joinCommand)) self.__send("MODE " + name) emptyIndex = self.channelsWidget.indexOf(self.__emptyLabel) if emptyIndex > -1: self.channelsWidget.removeTab(emptyIndex) self.__leaveButton.setEnabled(True) self.channelsWidget.setTabsClosable(True) def __query(self, match): """ Private method to handle a new private connection. @param match reference to the match object @return flag indicating, if the message was handled (boolean) """ # group(1) sender user name # group(2) sender user@host # group(3) target nick # group(4) message if match.group(4).startswith("\x01"): return self.__handleCtcp(match) self.__openPrivate(match.group(1)) # the above call sets the new channel as the current widget channel = self.channelsWidget.currentWidget() channel.addMessage(match.group(1), match.group(4)) channel.setPrivateInfo( "{0} - {1}".format(match.group(1), match.group(2))) return True @pyqtSlot(str) def __openPrivate(self, name): """ Private slot to open a private chat with the given user. @param name name of the user (string) """ from .IrcChannelWidget import IrcChannelWidget channel = IrcChannelWidget(self) channel.setName(self.__nickName) channel.setUserName(self.__nickName) identity = self.__ircNetworkManager.getIdentity(self.__identityName) channel.setPartMessage(identity.getPartMessage()) channel.setUserPrivilegePrefix(self.__userPrefix) channel.setPrivate(True, name) channel.addUsers([name, self.__nickName]) channel.sendData.connect(self.__send) channel.sendCtcpReply.connect(self.__sendCtcpReply) channel.channelClosed.connect(self.__closeChannel) self.channelsWidget.addTab(channel, name) self.__channelList.append(channel) self.channelsWidget.setCurrentWidget(channel) @pyqtSlot() def __leaveChannel(self): """ Private slot to leave a channel and close the associated tab. """ channel = self.channelsWidget.currentWidget() channel.requestLeave() def __closeAllChannels(self): """ Private method to close all channels. """ while self.__channelList: channel = self.__channelList.pop() self.channelsWidget.removeTab(self.channelsWidget.indexOf(channel)) channel.deleteLater() channel = None self.channelsWidget.addTab(self.__emptyLabel, "") self.__emptyLabel.show() self.__leaveButton.setEnabled(False) self.channelsWidget.setTabsClosable(False) def __closeChannel(self, name): """ Private slot handling the closing of a channel. @param name name of the closed channel (string) """ for channel in self.__channelList: if channel.name() == name: self.channelsWidget.removeTab( self.channelsWidget.indexOf(channel)) self.__channelList.remove(channel) channel.deleteLater() if self.channelsWidget.count() == 0: self.channelsWidget.addTab(self.__emptyLabel, "") self.__emptyLabel.show() self.__leaveButton.setEnabled(False) self.channelsWidget.setTabsClosable(False) @pyqtSlot(int) def on_channelsWidget_tabCloseRequested(self, index): """ Private slot to close a channel by pressing the close button of the channels widget. @param index index of the tab to be closed (integer) """ channel = self.channelsWidget.widget(index) channel.requestLeave() def __send(self, data): """ Private slot to send data to the IRC server. @param data data to be sent (string) """ if self.__socket: self.__socket.write( QByteArray("{0}\r\n".format(data).encode("utf-8"))) def __sendCtcpReply(self, receiver, text): """ Private slot to send a CTCP reply. @param receiver nick name of the receiver (string) @param text text to be sent (string) """ self.__send("NOTICE {0} :\x01{1}\x01".format(receiver, text)) def __hostFound(self): """ Private slot to indicate the host was found. """ self.networkWidget.addServerMessage( self.tr("Info"), self.tr("Server found,connecting...")) def __hostConnected(self): """ Private slot to log in to the server after the connection was established. """ self.networkWidget.addServerMessage( self.tr("Info"), self.tr("Connected,logging in...")) self.networkWidget.setConnected(True) self.__registering = True serverPassword = self.__server.getPassword() if serverPassword: self.__send("PASS " + serverPassword) nick = self.networkWidget.getNickname() if not nick: self.__nickIndex = 0 try: nick = self.__ircNetworkManager.getIdentity( self.__identityName).getNickNames()[self.__nickIndex] except IndexError: nick = "" if not nick: nick = self.__userName self.__nickName = nick self.networkWidget.setNickName(nick) realName = self.__ircNetworkManager.getIdentity( self.__identityName).getRealName() if not realName: realName = "eric IDE chat" self.__send("NICK " + nick) self.__send("USER " + self.__userName + " 0 * :" + realName) def __hostDisconnected(self): """ Private slot to indicate the host was disconnected. """ if self.networkWidget.isConnected(): self.__closeAllChannels() self.networkWidget.addServerMessage( self.tr("Info"), self.tr("Server disconnected.")) self.networkWidget.setRegistered(False) self.networkWidget.setConnected(False) self.__server = None self.__nickName = "" self.__nickIndex = -1 self.__channelTypePrefixes = "" self.__socket.deleteLater() self.__socket = None self.__connectionState = IrcWidget.ServerDisconnected self.__sslErrorLock = False def __readyRead(self): """ Private slot to read data from the socket. """ if self.__socket: self.__buffer += str( self.__socket.readAll(), Preferences.getSystem("IOEncoding"), 'replace') if self.__buffer.endswith("\r\n"): for line in self.__buffer.splitlines(): line = line.strip() if line: logging.debug("<IRC> " + line) handled = False # step 1: give channels a chance to handle the message for channel in self.__channelList: handled = channel.handleMessage(line) if handled: break else: # step 2: try to process the message ourselves for patternRe, patternFunc in self.__patterns: match = patternRe.match(line) if match is not None: if patternFunc(match): break else: # Oops, the message wasn't handled self.networkWidget.addErrorMessage( self.tr("Message Error"), self.tr( "Unknown message received from server:" "<br/>{0}").format(line)) self.__updateUsersCount() self.__buffer = "" def __handleNamedMessage(self, match): """ Private method to handle a server message containing a message name. @param match reference to the match object @return flag indicating, if the message was handled (boolean) """ name = match.group(2) if name == "NOTICE": try: msg = match.group(3).split(":", 1)[1] except IndexError: msg = match.group(3) if "!" in match.group(1): name = match.group(1).split("!", 1)[0] msg = "-{0}- {1}".format(name, msg) self.networkWidget.addServerMessage(self.tr("Notice"), msg) return True elif name == "MODE": self.__registering = False if ":" in match.group(3): # :detlev_ MODE detlev_ :+i name, modes = match.group(3).split(" :") sourceNick = match.group(1) if not self.isChannelName(name): if name == self.__nickName: if sourceNick == self.__nickName: msg = self.tr( "You have set your personal modes to" " <b>[{0}]</b>.").format(modes) else: msg = self.tr( "{0} has changed your personal modes to" " <b>[{1}]</b>.").format(sourceNick, modes) self.networkWidget.addServerMessage( self.tr("Mode"), msg, filterMsg=False) return True elif name == "PART": nick = match.group(1).split("!", 1)[0] if nick == self.__nickName: channel = match.group(3).split(None, 1)[0] self.networkWidget.addMessage( self.tr("You have left channel {0}.").format(channel)) return True elif name == "QUIT": # don't do anything with it here return True elif name == "NICK": # :[email protected] NICK :newnick oldNick = match.group(1).split("!", 1)[0] newNick = match.group(3).split(":", 1)[1] if oldNick == self.__nickName: self.networkWidget.addMessage( self.tr("You are now known as {0}.").format(newNick)) self.__nickName = newNick self.networkWidget.setNickName(newNick) else: self.networkWidget.addMessage( self.tr("User {0} is now known as {1}.").format( oldNick, newNick)) return True elif name == "ERROR": self.networkWidget.addErrorMessage( self.tr("Server Error"), match.group(3).split(":", 1)[1]) return True return False def __handleNumericMessage(self, match): """ Private method to handle a server message containing a numeric code. @param match reference to the match object @return flag indicating, if the message was handled (boolean) """ code = int(match.group(2)) if code < 400: return self.__handleServerReply( code, match.group(1), match.group(3)) else: return self.__handleServerError( code, match.group(1), match.group(3)) def __handleServerError(self, code, server, message): """ Private slot to handle a server error reply. @param code numerical code sent by the server (integer) @param server name of the server (string) @param message message sent by the server (string) @return flag indicating, if the message was handled (boolean) """ if code == 433: if self.__registering: self.__handleNickInUseLogin() else: self.__handleNickInUse() else: self.networkWidget.addServerMessage(self.tr("Error"), message) return True def __handleServerReply(self, code, server, message): """ Private slot to handle a server reply. @param code numerical code sent by the server (integer) @param server name of the server (string) @param message message sent by the server (string) @return flag indicating, if the message was handled (boolean) """ # determine message type if code in [1, 2, 3, 4]: msgType = self.tr("Welcome") elif code == 5: msgType = self.tr("Support") elif code in [250, 251, 252, 253, 254, 255, 265, 266]: msgType = self.tr("User") elif code in [372, 375, 376]: msgType = self.tr("MOTD") elif code in [305, 306]: msgType = self.tr("Away") else: msgType = self.tr("Info ({0})").format(code) # special treatment for some messages if code == 375: message = self.tr("Message of the day") elif code == 376: message = self.tr("End of message of the day") elif code == 4: parts = message.strip().split() message = self.tr( "Server {0} (Version {1}), User-Modes: {2}," " Channel-Modes: {3}")\ .format(parts[1], parts[2], parts[3], parts[4]) elif code == 265: parts = message.strip().split() message = self.tr( "Current users on {0}: {1}, max. {2}").format( server, parts[1], parts[2]) elif code == 266: parts = message.strip().split() message = self.tr( "Current users on the network: {0}, max. {1}").format( parts[1], parts[2]) elif code == 305: message = self.tr("You are no longer marked as being away.") elif code == 306: message = self.tr("You have been marked as being away.") else: first, message = message.split(None, 1) if message.startswith(":"): message = message[1:] else: message = message.replace(":", "", 1) self.networkWidget.addServerMessage(msgType, message) if code == 1: # register with services after the welcome message self.__connectionState = IrcWidget.ServerConnected self.__registerWithServices() self.networkWidget.setRegistered(True) QTimer.singleShot(1000, self.__autoJoinChannels) elif code == 5: # extract the user privilege prefixes # ... PREFIX=(ov)@+ ... m = self.__prefixRe.match(message) if m: self.__setUserPrivilegePrefix(m.group(1), m.group(2)) # extract the channel type prefixes # ... CHANTYPES=# ... m = self.__chanTypesRe.match(message) if m: self.__setChannelTypePrefixes(m.group(1)) return True def __registerWithServices(self): """ Private method to register to services. """ identity = self.__ircNetworkManager.getIdentity(self.__identityName) service = identity.getServiceName() password = identity.getPassword() if service and password: self.__send("PRIVMSG " + service + " :identify " + password) def __autoJoinChannels(self): """ Private slot to join channels automatically once a server got connected. """ for channel in self.networkWidget.getNetworkChannels(): if channel.autoJoin(): name = channel.getName() key = channel.getKey() self.__joinChannel(name, key) def __tcpError(self, error): """ Private slot to handle errors reported by the TCP socket. @param error error code reported by the socket (QAbstractSocket.SocketError) """ if error == QAbstractSocket.RemoteHostClosedError: # ignore this one, it's a disconnect if self.__sslErrorLock: self.networkWidget.addErrorMessage( self.tr("SSL Error"), self.tr( """Connection to server {0} (port {1}) lost while""" """ waiting for user response to an SSL error.""") .format(self.__server.getName(), self.__server.getPort())) self.__connectionState = IrcWidget.ServerDisconnected elif error == QAbstractSocket.HostNotFoundError: self.networkWidget.addErrorMessage( self.tr("Socket Error"), self.tr( "The host was not found. Please check the host name" " and port settings.")) elif error == QAbstractSocket.ConnectionRefusedError: self.networkWidget.addErrorMessage( self.tr("Socket Error"), self.tr( "The connection was refused by the peer. Please check the" " host name and port settings.")) elif error == QAbstractSocket.SslHandshakeFailedError: self.networkWidget.addErrorMessage( self.tr("Socket Error"), self.tr("The SSL handshake failed.")) else: if self.__socket: self.networkWidget.addErrorMessage( self.tr("Socket Error"), self.tr( "The following network error occurred:<br/>{0}") .format(self.__socket.errorString())) else: self.networkWidget.addErrorMessage( self.tr("Socket Error"), self.tr("A network error occurred.")) def __sslErrors(self, errors): """ Private slot to handle SSL errors. @param errors list of SSL errors (list of QSslError) """ ignored, defaultChanged = self.__sslErrorHandler.sslErrors( errors, self.__server.getName(), self.__server.getPort()) if ignored == E5SslErrorHandler.NotIgnored: self.networkWidget.addErrorMessage( self.tr("SSL Error"), self.tr( """Could not connect to {0} (port {1}) using an SSL""" """ encrypted connection. Either the server does not""" """ support SSL (did you use the correct port?) or""" """ you rejected the certificate.""") .format(self.__server.getName(), self.__server.getPort())) self.__socket.close() else: if defaultChanged: self.__socket.setSslConfiguration( QSslConfiguration.defaultConfiguration()) if ignored == E5SslErrorHandler.UserIgnored: self.networkWidget.addErrorMessage( self.tr("SSL Error"), self.tr( """The SSL certificate for the server {0} (port {1})""" """ failed the authenticity check. SSL errors""" """ were accepted by you.""") .format(self.__server.getName(), self.__server.getPort())) if self.__connectionState == IrcWidget.ServerConnecting: self.__socket.ignoreSslErrors() def __setUserPrivilegePrefix(self, prefix1, prefix2): """ Private method to set the user privilege prefix. @param prefix1 first part of the prefix (string) @param prefix2 indictors the first part gets mapped to (string) """ # PREFIX=(ov)@+ # o = @ -> @ircbot , channel operator # v = + -> +userName , voice operator for i in range(len(prefix1)): self.__userPrefix["+" + prefix1[i]] = prefix2[i] self.__userPrefix["-" + prefix1[i]] = "" def __ping(self, match): """ Private method to handle a PING message. @param match reference to the match object @return flag indicating, if the message was handled (boolean) """ self.__send("PONG " + match.group(1)) return True def __handleCtcp(self, match): """ Private method to handle a CTCP command. @param match reference to the match object @return flag indicating, if the message was handled (boolean) """ # group(1) sender user name # group(2) sender user@host # group(3) target nick # group(4) message if match.group(4).startswith("\x01"): ctcpCommand = match.group(4)[1:].split("\x01", 1)[0] if " " in ctcpCommand: ctcpRequest, ctcpArg = ctcpCommand.split(" ", 1) else: ctcpRequest, ctcpArg = ctcpCommand, "" ctcpRequest = ctcpRequest.lower() if ctcpRequest == "version": if Version.startswith("@@"): vers = "" else: vers = " " + Version msg = "Eric IRC client{0}, {1}".format(vers, Copyright) self.networkWidget.addServerMessage( self.tr("CTCP"), self.tr("Received Version request from {0}.").format( match.group(1))) self.__sendCtcpReply(match.group(1), "VERSION " + msg) elif ctcpRequest == "ping": self.networkWidget.addServerMessage( self.tr("CTCP"), self.tr( "Received CTCP-PING request from {0}," " sending answer.").format(match.group(1))) self.__sendCtcpReply( match.group(1), "PING {0}".format(ctcpArg)) elif ctcpRequest == "clientinfo": self.networkWidget.addServerMessage( self.tr("CTCP"), self.tr( "Received CTCP-CLIENTINFO request from {0}," " sending answer.").format(match.group(1))) self.__sendCtcpReply( match.group(1), "CLIENTINFO CLIENTINFO PING VERSION") else: self.networkWidget.addServerMessage( self.tr("CTCP"), self.tr( "Received unknown CTCP-{0} request from {1}.") .format(ctcpRequest, match.group(1))) return True return False def __updateUsersCount(self): """ Private method to update the users count on the channel tabs. """ for channel in self.__channelList: index = self.channelsWidget.indexOf(channel) self.channelsWidget.setTabText( index, self.tr("{0} ({1})", "channel name, users count").format( channel.name(), channel.getUsersCount())) def __handleNickInUseLogin(self): """ Private method to handle a 443 server error at login. """ self.__nickIndex += 1 try: nick = self.__ircNetworkManager.getIdentity(self.__identityName)\ .getNickNames()[self.__nickIndex] self.__nickName = nick except IndexError: self.networkWidget.addServerMessage( self.tr("Critical"), self.tr( "No nickname acceptable to the server configured" " for <b>{0}</b>. Disconnecting...") .format(self.__userName), filterMsg=False) self.__connectNetwork("", False, silent=True) self.__nickName = "" self.__nickIndex = -1 return self.networkWidget.setNickName(nick) self.__send("NICK " + nick) def __handleNickInUse(self): """ Private method to handle a 443 server error. """ self.networkWidget.addServerMessage( self.tr("Critical"), self.tr("The given nickname is already in use.")) def __changeNick(self, nick): """ Private slot to use a new nick name. @param nick nick name to use (str) """ if nick and nick != self.__nickName: self.__send("NICK " + nick) def __setChannelTypePrefixes(self, prefixes): """ Private method to set the channel type prefixes. @param prefixes channel prefix characters (string) """ self.__channelTypePrefixes = prefixes def isChannelName(self, name): """ Public method to check, if the given name is a channel name. @param name name to check (string) @return flag indicating a channel name (boolean) """ if not name: return False if self.__channelTypePrefixes: return name[0] in self.__channelTypePrefixes else: return name[0] in "#&" def __away(self, isAway): """ Private slot handling the change of the away state. @param isAway flag indicating the current away state (boolean) """ if isAway and self.__identityName: identity = self.__ircNetworkManager.getIdentity( self.__identityName) if identity.rememberAwayPosition(): for channel in self.__channelList: channel.setMarkerLine()
class Dialog(QDialog): TotalBytes = 50 * 1024 * 1024 PayloadSize = 65536 def __init__(self, parent=None): super(Dialog, self).__init__(parent) self.tcpServer = QTcpServer() self.tcpClient = QTcpSocket() self.bytesToWrite = 0 self.bytesWritten = 0 self.bytesReceived = 0 self.clientProgressBar = QProgressBar() self.clientStatusLabel = QLabel("Client ready") self.serverProgressBar = QProgressBar() self.serverStatusLabel = QLabel("Server ready") self.startButton = QPushButton("&Start") self.quitButton = QPushButton("&Quit") buttonBox = QDialogButtonBox() buttonBox.addButton(self.startButton, QDialogButtonBox.ActionRole) buttonBox.addButton(self.quitButton, QDialogButtonBox.RejectRole) self.startButton.clicked.connect(self.start) self.quitButton.clicked.connect(self.close) self.tcpServer.newConnection.connect(self.acceptConnection) self.tcpClient.connected.connect(self.startTransfer) self.tcpClient.bytesWritten.connect(self.updateClientProgress) self.tcpClient.error.connect(self.displayError) mainLayout = QVBoxLayout() mainLayout.addWidget(self.clientProgressBar) mainLayout.addWidget(self.clientStatusLabel) mainLayout.addWidget(self.serverProgressBar) mainLayout.addWidget(self.serverStatusLabel) mainLayout.addStretch(1) mainLayout.addSpacing(10) mainLayout.addWidget(buttonBox) self.setLayout(mainLayout) self.setWindowTitle("Loopback") def start(self): self.startButton.setEnabled(False) QApplication.setOverrideCursor(Qt.WaitCursor) self.bytesWritten = 0 self.bytesReceived = 0 while not self.tcpServer.isListening() and not self.tcpServer.listen(): ret = QMessageBox.critical( self, "Loopback", "Unable to start the test: %s." % self.tcpServer.errorString(), QMessageBox.Retry | QMessageBox.Cancel, ) if ret == QMessageBox.Cancel: return self.serverStatusLabel.setText("Listening") self.clientStatusLabel.setText("Connecting") self.tcpClient.connectToHost(QHostAddress(QHostAddress.LocalHost), self.tcpServer.serverPort()) def acceptConnection(self): self.tcpServerConnection = self.tcpServer.nextPendingConnection() self.tcpServerConnection.readyRead.connect(self.updateServerProgress) self.tcpServerConnection.error.connect(self.displayError) self.serverStatusLabel.setText("Accepted connection") self.tcpServer.close() def startTransfer(self): self.bytesToWrite = Dialog.TotalBytes - self.tcpClient.write( QByteArray(Dialog.PayloadSize, "@")) self.clientStatusLabel.setText("Connected") def updateServerProgress(self): self.bytesReceived += self.tcpServerConnection.bytesAvailable() self.tcpServerConnection.readAll() self.serverProgressBar.setMaximum(Dialog.TotalBytes) self.serverProgressBar.setValue(self.bytesReceived) self.serverStatusLabel.setText("Received %dMB" % (self.bytesReceived / (1024 * 1024))) if self.bytesReceived == Dialog.TotalBytes: self.tcpServerConnection.close() self.startButton.setEnabled(True) QApplication.restoreOverrideCursor() def updateClientProgress(self, numBytes): self.bytesWritten += numBytes if self.bytesToWrite > 0: self.bytesToWrite -= self.tcpClient.write( QByteArray(min(self.bytesToWrite, Dialog.PayloadSize), "@")) self.clientProgressBar.setMaximum(Dialog.TotalBytes) self.clientProgressBar.setValue(self.bytesWritten) self.clientStatusLabel.setText("Sent %dMB" % (self.bytesWritten / (1024 * 1024))) def displayError(self, socketError): if socketError == QTcpSocket.RemoteHostClosedError: return QMessageBox.information( self, "Network error", "The following error occured: %s." % self.tcpClient.errorString(), ) self.tcpClient.close() self.tcpServer.close() self.clientProgressBar.reset() self.serverProgressBar.reset() self.clientStatusLabel.setText("Client ready") self.serverStatusLabel.setText("Server ready") self.startButton.setEnabled(True) QApplication.restoreOverrideCursor()
class Voltmeter(QtWidgets.QMainWindow, Ui_MainWindow): VOLTMETER_PORT = 5000 def __init__(self, parent=None): super(Voltmeter, self).__init__(parent) self.setupUi(self) self.needle = QwtDialSimpleNeedle(QwtDialSimpleNeedle.Arrow) self.Dial.setNeedle(self.needle) self.Dial.setValue(1.5) self.lcdNumber.display(1.5) self.actionQuit.triggered.connect(self.quit) self.connect_pb.clicked.connect(self.connect) self.calib = 3.3 / 256 self.client_socket = QTcpSocket(self) self.connected = False def connect(self): if self.connected: self.client_socket.close() self.connect_pb.setChecked(False) self.connect_pb.setText("Connect to Voltmeter") return print("Connecting") server_ip = str(self.ip_address_text.text()) port = self.VOLTMETER_PORT print("Server IP: ", server_ip) if server_ip.find('xxx') != -1: print("bad IP") QMessageBox.about( self, 'Bad Server IP', 'Please give a correct Server IP\n' 'IP is ' + server_ip) self.connect_pb.setChecked(False) return else: print("Connecting to " + server_ip + ":", port) self.client_socket.connectToHost(server_ip, port) self.client_socket.waitForConnected(1000) if self.client_socket.state() != QTcpSocket.ConnectedState: QMessageBox.warning( self, 'Connection failed', 'Please check IP address and port number\nIs the server running?' ) self.connect_pb.setChecked(False) return print("Connection established") self.client_socket.readyRead.connect(self.treatMeas) self.connect_pb.setText("Connected") def treatMeas(self): # get new values and display them msg = self.client_socket.readAll() newValue = int(bytes(msg).decode()) print("new value: ", newValue) response = 'ok\n' self.client_socket.write(bytes(response, encoding="ascii")) newVoltage = int(newValue) * self.calib print(newVoltage) self.lcdNumber.display(newVoltage) self.Dial.setValue(newVoltage) def quit(self): app.exit()
class ControlCar(QWidget): HOST = '127.0.0.1' PORT = 8888 def __init__(self, *args, **kwargs): super(ControlCar, self).__init__(*args, **kwargs) self._connCar = None # 加载UI文件 uic.loadUi('carui.ui', self) self.resize(800, 600) # 绑定连接按钮信号 self.buttonConnect.clicked.connect(self.doConnect) # 绑定拉动信号 self.sliderForward.valueChanged.connect(self.doForward) self.sliderBackward.valueChanged.connect(self.doBackward) self.sliderLeft.valueChanged.connect(self.doLeft) self.sliderRight.valueChanged.connect(self.doRight) # 设置初始拉动条不能用 self.sliderForward.setEnabled(False) self.sliderBackward.setEnabled(False) self.sliderLeft.setEnabled(False) self.sliderRight.setEnabled(False) # 定时器定时向图片服务器发送请求 self._timer = QTimer(self, timeout=self.doGetImage) def _clearConn(self): """清理连接""" if self._connCar: self._connCar.close() self._connCar.deleteLater() del self._connCar self._connCar = None def closeEvent(self, event): """窗口关闭事件""" self._timer.stop() self._clearConn() super(ControlCar, self).closeEvent(event) def doConnect(self): """连接服务器""" self.buttonConnect.setEnabled(False) self._timer.stop() self._clearConn() self.browserResult.append('正在连接服务器') # 连接控制小车的服务器 self._connCar = QTcpSocket(self) self._connCar.connected.connect(self.onConnected) # 绑定连接成功信号 self._connCar.disconnected.connect(self.onDisconnected) # 绑定连接丢失信号 self._connCar.readyRead.connect(self.onReadyRead) # 准备读取信号 self._connCar.error.connect(self.onError) # 连接错误信号 self._connCar.connectToHost(self.HOST, self.PORT) def onConnected(self): """连接成功""" self.buttonConnect.setEnabled(False) # 按钮不可用 # 设置初始拉动条可用 self.sliderForward.setEnabled(True) self.sliderBackward.setEnabled(True) self.sliderLeft.setEnabled(True) self.sliderRight.setEnabled(True) self.browserResult.append('连接成功') # 记录日志 # 开启获取摄像头图片定时器 self._timer.start(200) def onDisconnected(self): """丢失连接""" self._timer.stop() self.buttonConnect.setEnabled(True) # 按钮可用 # 设置初始拉动条不可用 self.sliderForward.setEnabled(False) self.sliderBackward.setEnabled(False) self.sliderLeft.setEnabled(False) self.sliderRight.setEnabled(False) # 把数据设置为最小值 self.sliderForward.setValue(self.sliderForward.minimum()) self.sliderBackward.setValue(self.sliderBackward.minimum()) self.sliderLeft.setValue(self.sliderLeft.minimum()) self.sliderRight.setValue(self.sliderRight.minimum()) self.browserResult.append('丢失连接') # 记录日志 def onReadyRead(self): """接收到数据""" while self._connCar.bytesAvailable() > 0: try: data = self._connCar.readAll().data() if data and data.find(b'JFIF') > -1: self.qlabel.setPixmap( # 图片 QPixmap.fromImage(QImage.fromData(data))) else: self.browserResult.append('接收到数据: ' + data.decode()) except Exception as e: self.browserResult.append('解析数据错误: ' + str(e)) def onError(self, _): """连接报错""" self._timer.stop() self.buttonConnect.setEnabled(True) # 按钮可用 self.browserResult.append('连接服务器错误: ' + self._connCar.errorString()) def doForward(self, value): """向前""" # 发送的内容为 F:1 类似的 self.sendData('F:', str(value)) def doBackward(self, value): """向后""" # 发送的内容为 B:1 类似的 self.sendData('B:', str(value)) def doLeft(self, value): """向左""" # 发送的内容为 L:1 类似的 self.sendData('L:', str(value)) def doRight(self, value): """向右""" # 发送的内容为 R:1 类似的 self.sendData('R:', str(value)) def doGetImage(self): # 请求图片 self.sendData('getimage', '') def sendData(self, ver, data): """发送数据""" if not self._connCar or not self._connCar.isWritable(): return self.browserResult.append('服务器未连接或不可写入数据') self._connCar.write(ver.encode() + str(data).encode() + b'\n')
class Client(QDialog): def __init__(self, parent=None): super(Client, self).__init__(parent) self.networkSession = None self.blockSize = 0 self.currentFortune = "" hostLabel = QLabel("&Server name:") portLabel = QLabel("S&erver port:") self.hostCombo = QComboBox() self.hostCombo.setEditable(True) name = QHostInfo.localHostName() if name != "": self.hostCombo.addItem(name) domain = QHostInfo.localDomainName() if domain != "": self.hostCombo.addItem(name + "." + domain) if name != "localhost": self.hostCombo.addItem("localhost") ipAddressesList = QNetworkInterface.allAddresses() for ipAddress in ipAddressesList: if not ipAddress.isLoopback(): self.hostCombo.addItem(ipAddress.toString()) for ipAddress in ipAddressesList: if ipAddress.isLoopback(): self.hostCombo.addItem(ipAddress.toString()) self.portLineEdit = QLineEdit() self.portLineEdit.setValidator(QIntValidator(1, 65535, self)) hostLabel.setBuddy(self.hostCombo) portLabel.setBuddy(self.portLineEdit) self.statusLabel = QLabel("This examples requires that you run " "the Fortune Server example as well.") self.getFortuneButton = QPushButton("Get Fortune") self.getFortuneButton.setDefault(True) self.getFortuneButton.setEnabled(False) quitButton = QPushButton("Quit") buttonBox = QDialogButtonBox() buttonBox.addButton(self.getFortuneButton, QDialogButtonBox.ActionRole) buttonBox.addButton(quitButton, QDialogButtonBox.RejectRole) self.tcpSocket = QTcpSocket(self) self.hostCombo.editTextChanged.connect(self.enableGetFortuneButton) self.portLineEdit.textChanged.connect(self.enableGetFortuneButton) self.getFortuneButton.clicked.connect(self.requestNewFortune) quitButton.clicked.connect(self.close) self.tcpSocket.readyRead.connect(self.readFortune) self.tcpSocket.error.connect(self.displayError) mainLayout = QGridLayout() mainLayout.addWidget(hostLabel, 0, 0) mainLayout.addWidget(self.hostCombo, 0, 1) mainLayout.addWidget(portLabel, 1, 0) mainLayout.addWidget(self.portLineEdit, 1, 1) mainLayout.addWidget(self.statusLabel, 2, 0, 1, 2) mainLayout.addWidget(buttonBox, 3, 0, 1, 2) self.setLayout(mainLayout) self.setWindowTitle("Fortune Client") self.portLineEdit.setFocus() manager = QNetworkConfigurationManager() if manager.capabilities() & QNetworkConfigurationManager.NetworkSessionRequired: settings = QSettings(QSettings.UserScope, "QtProject") settings.beginGroup("QtNetwork") id = settings.value("DefaultNetworkConfiguration") settings.endGroup() config = manager.configurationFromIdentifier(id) if config.state() & QNetworkConfiguration.Discovered == 0: config = manager.defaultConfiguration() self.networkSession = QNetworkSession(config, self) self.networkSession.opened.connect(self.sessionOpened) self.getFortuneButton.setEnabled(False) self.statusLabel.setText("Opening network session.") self.networkSession.open() def requestNewFortune(self): self.getFortuneButton.setEnabled(False) self.blockSize = 0 self.tcpSocket.abort() self.tcpSocket.connectToHost(self.hostCombo.currentText(), int(self.portLineEdit.text())) def readFortune(self): instr = QDataStream(self.tcpSocket) instr.setVersion(QDataStream.Qt_4_0) if self.blockSize == 0: if self.tcpSocket.bytesAvailable() < 2: return self.blockSize = instr.readUInt16() if self.tcpSocket.bytesAvailable() < self.blockSize: return nextFortune = instr.readQString() if nextFortune == self.currentFortune: QTimer.singleShot(0, self.requestNewFortune) return self.currentFortune = nextFortune self.statusLabel.setText(self.currentFortune) self.getFortuneButton.setEnabled(True) def displayError(self, socketError): if socketError == QAbstractSocket.RemoteHostClosedError: pass elif socketError == QAbstractSocket.HostNotFoundError: QMessageBox.information( self, "Fortune Client", "The host was not found. Please check the host name and " "port settings." ) elif socketError == QAbstractSocket.ConnectionRefusedError: QMessageBox.information( self, "Fortune Client", "The connection was refused by the peer. Make sure the " "fortune server is running, and check that the host name " "and port settings are correct.", ) else: QMessageBox.information( self, "Fortune Client", "The following error occurred: %s." % self.tcpSocket.errorString() ) self.getFortuneButton.setEnabled(True) def enableGetFortuneButton(self): self.getFortuneButton.setEnabled( (self.networkSession is None or self.networkSession.isOpen()) and self.hostCombo.currentText() != "" and self.portLineEdit.text() != "" ) def sessionOpened(self): config = self.networkSession.configuration() if config.type() == QNetworkConfiguration.UserChoice: id = self.networkSession.sessionProperty("UserChoiceConfiguration") else: id = config.identifier() settings = QSettings(QSettings.UserScope, "QtProject") settings.beginGroup("QtNetwork") settings.setValue("DefaultNetworkConfiguration", id) settings.endGroup() self.statusLabel.setText("This examples requires that you run the " "Fortune Server example as well.") self.enableGetFortuneButton()
class VNA(QMainWindow, Ui_VNA): graphs = ['open', 'short', 'load', 'dut', 'smith', 'imp', 'swr', 'gamma', 'rl', 'gain_short', 'gain_open'] def __init__(self): super(VNA, self).__init__() self.setupUi(self) # IP address validator rx = QRegExp('^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$') self.addrValue.setValidator(QRegExpValidator(rx, self.addrValue)) # state variables self.idle = True self.reading = False self.auto = False # sweep parameters self.sweep_start = 10 self.sweep_stop = 60000 self.sweep_size = 6000 # buffer and offset for the incoming samples self.buffer = bytearray(16 * 32768) self.offset = 0 self.data = np.frombuffer(self.buffer, np.complex64) # create measurements self.open = Measurement(self.sweep_start, self.sweep_stop, self.sweep_size) self.short = Measurement(self.sweep_start, self.sweep_stop, self.sweep_size) self.load = Measurement(self.sweep_start, self.sweep_stop, self.sweep_size) self.dut = Measurement(self.sweep_start, self.sweep_stop, self.sweep_size) self.mode = 'open' # create figures self.tabs = {} for i in range(len(self.graphs)): layout = getattr(self, '%sLayout' % self.graphs[i]) self.tabs[i] = FigureTab(layout, self.open, self.short, self.load, self.dut) # configure widgets self.rateValue.addItems(['10000', '5000', '1000', '500', '100', '50', '10', '5', '1']) self.rateValue.lineEdit().setReadOnly(True) self.rateValue.lineEdit().setAlignment(Qt.AlignRight) for i in range(self.rateValue.count()): self.rateValue.setItemData(i, Qt.AlignRight, Qt.TextAlignmentRole) self.set_enabled(False) # read settings settings = QSettings('vna.ini', QSettings.IniFormat) self.read_cfg_settings(settings) # create TCP socket self.socket = QTcpSocket(self) self.socket.connected.connect(self.connected) self.socket.readyRead.connect(self.read_data) self.socket.error.connect(self.display_error) # connect signals from widgets self.connectButton.clicked.connect(self.start) self.writeButton.clicked.connect(self.write_cfg) self.readButton.clicked.connect(self.read_cfg) self.openSweep.clicked.connect(partial(self.sweep, 'open')) self.shortSweep.clicked.connect(partial(self.sweep, 'short')) self.loadSweep.clicked.connect(partial(self.sweep, 'load')) self.singleSweep.clicked.connect(partial(self.sweep, 'dut')) self.autoSweep.clicked.connect(self.sweep_auto) self.stopSweep.clicked.connect(self.cancel) self.csvButton.clicked.connect(self.write_csv) self.s1pButton.clicked.connect(self.write_s1p) self.s2pshortButton.clicked.connect(self.write_s2p_short) self.s2popenButton.clicked.connect(self.write_s2p_open) self.startValue.valueChanged.connect(self.set_start) self.stopValue.valueChanged.connect(self.set_stop) self.sizeValue.valueChanged.connect(self.set_size) self.rateValue.currentIndexChanged.connect(self.set_rate) self.corrValue.valueChanged.connect(self.set_corr) self.levelValue.valueChanged.connect(self.set_level) self.tabWidget.currentChanged.connect(self.update_tab) # create timers self.startTimer = QTimer(self) self.startTimer.timeout.connect(self.timeout) self.sweepTimer = QTimer(self) self.sweepTimer.timeout.connect(self.sweep_timeout) def set_enabled(self, enabled): widgets = [self.corrValue, self.rateValue, self.levelValue, self.sizeValue, self.stopValue, self.startValue, self.openSweep, self.shortSweep, self.loadSweep, self.singleSweep, self.autoSweep] for entry in widgets: entry.setEnabled(enabled) def start(self): if self.idle: self.connectButton.setEnabled(False) self.socket.connectToHost(self.addrValue.text(), 1001) self.startTimer.start(5000) else: self.stop() def stop(self): self.idle = True self.cancel() self.socket.abort() self.connectButton.setText('Connect') self.connectButton.setEnabled(True) self.set_enabled(False) def timeout(self): self.display_error('timeout') def connected(self): self.startTimer.stop() self.idle = False self.set_rate(self.rateValue.currentIndex()) self.set_corr(self.corrValue.value()) self.set_level(self.levelValue.value()) self.set_gpio(1) self.connectButton.setText('Disconnect') self.connectButton.setEnabled(True) self.set_enabled(True) def read_data(self): while(self.socket.bytesAvailable() > 0): if not self.reading: self.socket.readAll() return size = self.socket.bytesAvailable() self.progressBar.setValue((self.offset + size) / 16) limit = 16 * self.sweep_size if self.offset + size < limit: self.buffer[self.offset:self.offset + size] = self.socket.read(size) self.offset += size else: self.buffer[self.offset:limit] = self.socket.read(limit - self.offset) adc1 = self.data[0::2] adc2 = self.data[1::2] attr = getattr(self, self.mode) start = self.sweep_start stop = self.sweep_stop size = self.sweep_size attr.freq = np.linspace(start, stop, size) attr.data = adc1[0:size].copy() self.update_tab() self.reading = False if not self.auto: self.progressBar.setValue(0) self.set_enabled(True) def display_error(self, socketError): self.startTimer.stop() if socketError == 'timeout': QMessageBox.information(self, 'VNA', 'Error: connection timeout.') else: QMessageBox.information(self, 'VNA', 'Error: %s.' % self.socket.errorString()) self.stop() def set_start(self, value): self.sweep_start = value def set_stop(self, value): self.sweep_stop = value def set_size(self, value): self.sweep_size = value def set_rate(self, value): if self.idle: return rate = [5, 10, 50, 100, 500, 1000, 5000, 10000, 50000][value] self.socket.write(struct.pack('<I', 3<<28 | int(rate))) def set_corr(self, value): if self.idle: return self.socket.write(struct.pack('<I', 4<<28 | int(value))) def set_level(self, value): if self.idle: return self.socket.write(struct.pack('<I', 5<<28 | int(32766 * np.power(10.0, value / 20.0)))) self.socket.write(struct.pack('<I', 6<<28 | int(0))) def set_gpio(self, value): if self.idle: return self.socket.write(struct.pack('<I', 7<<28 | int(value))) def sweep(self, mode): if self.idle: return self.set_enabled(False) self.mode = mode self.offset = 0 self.reading = True self.socket.write(struct.pack('<I', 0<<28 | int(self.sweep_start * 1000))) self.socket.write(struct.pack('<I', 1<<28 | int(self.sweep_stop * 1000))) self.socket.write(struct.pack('<I', 2<<28 | int(self.sweep_size))) self.socket.write(struct.pack('<I', 8<<28)) self.progressBar.setMinimum(0) self.progressBar.setMaximum(self.sweep_size) self.progressBar.setValue(0) def cancel(self): self.sweepTimer.stop() self.auto = False self.reading = False self.socket.write(struct.pack('<I', 9<<28)) self.progressBar.setValue(0) self.set_enabled(True) def sweep_auto(self): self.auto = True self.sweepTimer.start(100) def sweep_timeout(self): if not self.reading: self.sweep('dut') def update_tab(self): index = self.tabWidget.currentIndex() self.tabs[index].update(self.graphs[index]) def write_cfg(self): dialog = QFileDialog(self, 'Write configuration settings', '.', '*.ini') dialog.setDefaultSuffix('ini') dialog.selectFile('vna.ini') dialog.setAcceptMode(QFileDialog.AcceptSave) dialog.setOptions(QFileDialog.DontConfirmOverwrite) if dialog.exec() == QDialog.Accepted: name = dialog.selectedFiles() settings = QSettings(name[0], QSettings.IniFormat) self.write_cfg_settings(settings) def read_cfg(self): dialog = QFileDialog(self, 'Read configuration settings', '.', '*.ini') dialog.setDefaultSuffix('ini') dialog.selectFile('vna.ini') dialog.setAcceptMode(QFileDialog.AcceptOpen) if dialog.exec() == QDialog.Accepted: name = dialog.selectedFiles() settings = QSettings(name[0], QSettings.IniFormat) self.read_cfg_settings(settings) window.update_tab() def write_cfg_settings(self, settings): settings.setValue('addr', self.addrValue.text()) settings.setValue('rate', self.rateValue.currentIndex()) settings.setValue('corr', self.corrValue.value()) settings.setValue('level', self.levelValue.value()) settings.setValue('open_start', int(self.open.freq[0])) settings.setValue('open_stop', int(self.open.freq[-1])) settings.setValue('open_size', self.open.freq.size) settings.setValue('short_start', int(self.short.freq[0])) settings.setValue('short_stop', int(self.short.freq[-1])) settings.setValue('short_size', self.short.freq.size) settings.setValue('load_start', int(self.load.freq[0])) settings.setValue('load_stop', int(self.load.freq[-1])) settings.setValue('load_size', self.load.freq.size) settings.setValue('dut_start', int(self.dut.freq[0])) settings.setValue('dut_stop', int(self.dut.freq[-1])) settings.setValue('dut_size', self.dut.freq.size) for i in range(len(FigureTab.cursors)): settings.setValue('cursor_%d' % i, FigureTab.cursors[i]) data = self.open.data for i in range(self.open.freq.size): settings.setValue('open_real_%d' % i, float(data.real[i])) settings.setValue('open_imag_%d' % i, float(data.imag[i])) data = self.short.data for i in range(self.short.freq.size): settings.setValue('short_real_%d' % i, float(data.real[i])) settings.setValue('short_imag_%d' % i, float(data.imag[i])) data = self.load.data for i in range(self.load.freq.size): settings.setValue('load_real_%d' % i, float(data.real[i])) settings.setValue('load_imag_%d' % i, float(data.imag[i])) data = self.dut.data for i in range(self.dut.freq.size): settings.setValue('dut_real_%d' % i, float(data.real[i])) settings.setValue('dut_imag_%d' % i, float(data.imag[i])) def read_cfg_settings(self, settings): self.addrValue.setText(settings.value('addr', '192.168.1.100')) self.rateValue.setCurrentIndex(settings.value('rate', 0, type = int)) self.corrValue.setValue(settings.value('corr', 0, type = int)) self.levelValue.setValue(settings.value('level', 0, type = int)) open_start = settings.value('open_start', 10, type = int) open_stop = settings.value('open_stop', 60000, type = int) open_size = settings.value('open_size', 6000, type = int) short_start = settings.value('short_start', 10, type = int) short_stop = settings.value('short_stop', 60000, type = int) short_size = settings.value('short_size', 6000, type = int) load_start = settings.value('load_start', 10, type = int) load_stop = settings.value('load_stop', 60000, type = int) load_size = settings.value('load_size', 6000, type = int) dut_start = settings.value('dut_start', 10, type = int) dut_stop = settings.value('dut_stop', 60000, type = int) dut_size = settings.value('dut_size', 6000, type = int) self.startValue.setValue(dut_start) self.stopValue.setValue(dut_stop) self.sizeValue.setValue(dut_size) for i in range(len(FigureTab.cursors)): FigureTab.cursors[i] = settings.value('cursor_%d' % i, FigureTab.cursors[i], type = int) self.open.freq = np.linspace(open_start, open_stop, open_size) self.open.data = np.zeros(open_size, np.complex64) for i in range(open_size): real = settings.value('open_real_%d' % i, 0.0, type = float) imag = settings.value('open_imag_%d' % i, 0.0, type = float) self.open.data[i] = real + 1.0j * imag self.short.freq = np.linspace(short_start, short_stop, short_size) self.short.data = np.zeros(short_size, np.complex64) for i in range(short_size): real = settings.value('short_real_%d' % i, 0.0, type = float) imag = settings.value('short_imag_%d' % i, 0.0, type = float) self.short.data[i] = real + 1.0j * imag self.load.freq = np.linspace(load_start, load_stop, load_size) self.load.data = np.zeros(load_size, np.complex64) for i in range(load_size): real = settings.value('load_real_%d' % i, 0.0, type = float) imag = settings.value('load_imag_%d' % i, 0.0, type = float) self.load.data[i] = real + 1.0j * imag self.dut.freq = np.linspace(dut_start, dut_stop, dut_size) self.dut.data = np.zeros(dut_size, np.complex64) for i in range(dut_size): real = settings.value('dut_real_%d' % i, 0.0, type = float) imag = settings.value('dut_imag_%d' % i, 0.0, type = float) self.dut.data[i] = real + 1.0j * imag def write_csv(self): dialog = QFileDialog(self, 'Write csv file', '.', '*.csv') dialog.setDefaultSuffix('csv') dialog.setAcceptMode(QFileDialog.AcceptSave) dialog.setOptions(QFileDialog.DontConfirmOverwrite) if dialog.exec() == QDialog.Accepted: name = dialog.selectedFiles() fh = open(name[0], 'w') f = self.dut.freq o = np.interp(f, self.open.freq, self.open.data, period = self.open.period) s = np.interp(f, self.short.freq, self.short.data, period = self.short.period) l = np.interp(f, self.load.freq, self.load.data, period = self.load.period) d = self.dut.data fh.write('frequency;open.real;open.imag;short.real;short.imag;load.real;load.imag;dut.real;dut.imag\n') for i in range(f.size): fh.write('0.0%.8d;%12.9f;%12.9f;%12.9f;%12.9f;%12.9f;%12.9f;%12.9f;%12.9f\n' % (f[i] * 1000, o.real[i], o.imag[i], s.real[i], s.imag[i], l.real[i], l.imag[i], d.real[i], d.imag[i])) fh.close() def write_s1p(self): dialog = QFileDialog(self, 'Write s1p file', '.', '*.s1p') dialog.setDefaultSuffix('s1p') dialog.setAcceptMode(QFileDialog.AcceptSave) dialog.setOptions(QFileDialog.DontConfirmOverwrite) if dialog.exec() == QDialog.Accepted: name = dialog.selectedFiles() fh = open(name[0], 'w') freq = self.dut.freq gamma = self.gamma(freq) fh.write('# GHz S MA R 50\n') for i in range(freq.size): fh.write('0.0%.8d %8.6f %7.2f\n' % (freq[i] * 1000, np.absolute(gamma[i]), np.angle(gamma[i], deg = True))) fh.close() def write_s2p(self, gain): dialog = QFileDialog(self, 'Write s2p file', '.', '*.s2p') dialog.setDefaultSuffix('s2p') dialog.setAcceptMode(QFileDialog.AcceptSave) dialog.setOptions(QFileDialog.DontConfirmOverwrite) if dialog.exec() == QDialog.Accepted: name = dialog.selectedFiles() fh = open(name[0], 'w') freq = self.dut.freq gamma = self.gamma(freq) fh.write('# GHz S MA R 50\n') for i in range(freq.size): fh.write('0.0%.8d %8.6f %7.2f %8.6f %7.2f 0.000000 0.00 0.000000 0.00\n' % (freq[i] * 1000, np.absolute(gamma[i]), np.angle(gamma[i], deg = True), np.absolute(gain[i]), np.angle(gain[i], deg = True))) fh.close() def write_s2p_short(self): self.write_s2p(self.gain_short(self.dut.freq)) def write_s2p_open(self): self.write_s2p(self.gain_open(self.dut.freq))
class PulsedNMR(QMainWindow, Ui_PulsedNMR): rates = {0:25.0e3, 1:50.0e3, 2:250.0e3, 3:500.0e3, 4:2500.0e3} def __init__(self): super(PulsedNMR, self).__init__() self.setupUi(self) self.rateValue.addItems(['25', '50', '250', '500', '2500']) # IP address validator rx = QRegExp('^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]).){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$') self.addrValue.setValidator(QRegExpValidator(rx, self.addrValue)) # state variable self.idle = True # number of samples to show on the plot self.size = 50000 # buffer and offset for the incoming samples self.buffer = bytearray(8 * self.size) self.offset = 0 # create figure figure = Figure() figure.set_facecolor('none') self.axes = figure.add_subplot(111) self.canvas = FigureCanvas(figure) self.plotLayout.addWidget(self.canvas) # create navigation toolbar self.toolbar = NavigationToolbar(self.canvas, self.plotWidget, False) # remove subplots action actions = self.toolbar.actions() self.toolbar.removeAction(actions[7]) self.plotLayout.addWidget(self.toolbar) # create TCP socket self.socket = QTcpSocket(self) self.socket.connected.connect(self.connected) self.socket.readyRead.connect(self.read_data) self.socket.error.connect(self.display_error) # connect signals from buttons and boxes self.startButton.clicked.connect(self.start) self.freqValue.valueChanged.connect(self.set_freq) self.awidthValue.valueChanged.connect(self.set_awidth) self.deltaValue.valueChanged.connect(self.set_delta) self.rateValue.currentIndexChanged.connect(self.set_rate) # set rate self.rateValue.setCurrentIndex(2) # create timer for the repetitions self.timer = QTimer(self) self.timer.timeout.connect(self.fire) def start(self): if self.idle: self.startButton.setEnabled(False) self.socket.connectToHost(self.addrValue.text(), 1001) else: self.idle = True self.timer.stop() self.socket.close() self.offset = 0 self.startButton.setText('Start') self.startButton.setEnabled(True) def connected(self): self.idle = False self.set_freq(self.freqValue.value()) self.set_rate(self.rateValue.currentIndex()) self.set_awidth(self.awidthValue.value()) self.fire() self.timer.start(self.deltaValue.value()) self.startButton.setText('Stop') self.startButton.setEnabled(True) def read_data(self): size = self.socket.bytesAvailable() if self.offset + size < 8 * self.size: self.buffer[self.offset:self.offset + size] = self.socket.read(size) self.offset += size else: self.buffer[self.offset:8 * self.size] = self.socket.read(8 * self.size - self.offset) self.offset = 0 # plot the signal envelope data = np.frombuffer(self.buffer, np.complex64) self.curve.set_ydata(np.abs(data)) self.canvas.draw() def display_error(self, socketError): if socketError == QAbstractSocket.RemoteHostClosedError: pass else: QMessageBox.information(self, 'PulsedNMR', 'Error: %s.' % self.socket.errorString()) self.startButton.setText('Start') self.startButton.setEnabled(True) def set_freq(self, value): if self.idle: return self.socket.write(struct.pack('<I', 0<<28 | int(1.0e6 * value))) def set_rate(self, index): # time axis rate = float(PulsedNMR.rates[index]) time = np.linspace(0.0, (self.size - 1) * 1000.0 / rate, self.size) # reset toolbar self.toolbar.home() self.toolbar._views.clear() self.toolbar._positions.clear() # reset plot self.axes.clear() self.axes.grid() # plot zeros and get store the returned Line2D object self.curve, = self.axes.plot(time, np.zeros(self.size)) x1, x2, y1, y2 = self.axes.axis() # set y axis limits self.axes.axis((x1, x2, -0.1, 0.4)) self.axes.set_xlabel('time, ms') self.canvas.draw() # set repetition time minimum = self.size / rate * 2000.0 if minimum < 100.0: minimum = 100.0 self.deltaValue.setMinimum(minimum) self.deltaValue.setValue(minimum) if self.idle: return self.socket.write(struct.pack('<I', 1<<28 | index)) def set_awidth(self, value): if self.idle: return self.socket.write(struct.pack('<I', 2<<28 | int(1.0e1 * value))) def set_delta(self, value): if self.idle: return self.timer.stop() self.timer.start(value) def fire(self): if self.idle: return self.socket.write(struct.pack('<I', 3<<28))
class PulsedNMR(QMainWindow, Ui_PulsedNMR): rates = {0: 25.0e3, 1: 50.0e3, 2: 250.0e3, 3: 500.0e3, 4: 2500.0e3} def __init__(self): super(PulsedNMR, self).__init__() self.setupUi(self) self.rateValue.addItems(['25', '50', '250', '500', '2500']) # IP address validator rx = QRegExp( '^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$' ) self.addrValue.setValidator(QRegExpValidator(rx, self.addrValue)) # state variable self.idle = True # number of samples to show on the plot self.size = 50000 # buffer and offset for the incoming samples self.buffer = bytearray(8 * self.size) self.offset = 0 self.data = np.frombuffer(self.buffer, np.complex64) # create figure figure = Figure() figure.set_facecolor('none') self.axes = figure.add_subplot(111) self.canvas = FigureCanvas(figure) self.plotLayout.addWidget(self.canvas) # create navigation toolbar self.toolbar = NavigationToolbar(self.canvas, self.plotWidget, False) # remove subplots action actions = self.toolbar.actions() self.toolbar.removeAction(actions[7]) self.plotLayout.addWidget(self.toolbar) # create TCP socket self.socket = QTcpSocket(self) self.socket.connected.connect(self.connected) self.socket.readyRead.connect(self.read_data) self.socket.error.connect(self.display_error) # connect signals from buttons and boxes self.startButton.clicked.connect(self.start) self.freqValue.valueChanged.connect(self.set_freq) self.awidthValue.valueChanged.connect(self.set_awidth) self.deltaValue.valueChanged.connect(self.set_delta) self.rateValue.currentIndexChanged.connect(self.set_rate) # set rate self.rateValue.setCurrentIndex(2) # create timer for the repetitions self.timer = QTimer(self) self.timer.timeout.connect(self.fire) def start(self): if self.idle: self.startButton.setEnabled(False) self.socket.connectToHost(self.addrValue.text(), 1001) else: self.idle = True self.timer.stop() self.socket.close() self.offset = 0 self.startButton.setText('Start') self.startButton.setEnabled(True) def connected(self): self.idle = False self.set_freq(self.freqValue.value()) self.set_rate(self.rateValue.currentIndex()) self.set_awidth(self.awidthValue.value()) self.fire() self.timer.start(self.deltaValue.value()) self.startButton.setText('Stop') self.startButton.setEnabled(True) def read_data(self): size = self.socket.bytesAvailable() if self.offset + size < 8 * self.size: self.buffer[self.offset:self.offset + size] = self.socket.read(size) self.offset += size else: self.buffer[self.offset:8 * self.size] = self.socket.read(8 * self.size - self.offset) self.offset = 0 # plot the signal envelope self.curve.set_ydata(np.real(self.data)) self.canvas.draw() def display_error(self, socketError): if socketError == QAbstractSocket.RemoteHostClosedError: pass else: QMessageBox.information(self, 'PulsedNMR', 'Error: %s.' % self.socket.errorString()) self.startButton.setText('Start') self.startButton.setEnabled(True) def set_freq(self, value): if self.idle: return self.socket.write(struct.pack('<I', 0 << 28 | int(1.0e6 * value))) def set_rate(self, index): # time axis rate = float(PulsedNMR.rates[index]) time = np.linspace(0.0, (self.size - 1) * 1000.0 / rate, self.size) # reset toolbar self.toolbar.home() self.toolbar._views.clear() self.toolbar._positions.clear() # reset plot self.axes.clear() self.axes.grid() # plot zeros and get store the returned Line2D object self.curve, = self.axes.plot(time, np.zeros(self.size)) x1, x2, y1, y2 = self.axes.axis() # set y axis limits self.axes.axis((x1, x2, -0.1, 0.4)) self.axes.set_xlabel('time, ms') self.canvas.draw() # set repetition time minimum = self.size / rate * 2000.0 if minimum < 100.0: minimum = 100.0 self.deltaValue.setMinimum(minimum) self.deltaValue.setValue(minimum) if self.idle: return self.socket.write(struct.pack('<I', 1 << 28 | index)) def set_awidth(self, value): if self.idle: return self.socket.write(struct.pack('<I', 2 << 28 | int(1.0e1 * value))) def set_delta(self, value): if self.idle: return self.timer.stop() self.timer.start(value) def fire(self): if self.idle: return self.socket.write(struct.pack('<I', 3 << 28))
class VNA(QMainWindow, Ui_VNA): graphs = ['open', 'short', 'load', 'dut', 'smith', 'imp', 'swr', 'gamma', 'rl', 'gain_short', 'gain_open'] def __init__(self): super(VNA, self).__init__() self.setupUi(self) # IP address validator rx = QRegExp('^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$') self.addrValue.setValidator(QRegExpValidator(rx, self.addrValue)) # state variables self.idle = True self.reading = False self.auto = False # sweep parameters self.sweep_start = 10 self.sweep_stop = 60000 self.sweep_size = 6000 # buffer and offset for the incoming samples self.buffer = bytearray(16 * 32768) self.offset = 0 self.data = np.frombuffer(self.buffer, np.complex64) # create measurements self.open = Measurement(self.sweep_start, self.sweep_stop, self.sweep_size) self.short = Measurement(self.sweep_start, self.sweep_stop, self.sweep_size) self.load = Measurement(self.sweep_start, self.sweep_stop, self.sweep_size) self.dut = Measurement(self.sweep_start, self.sweep_stop, self.sweep_size) self.mode = 'open' # create figures self.tabs = {} for i in range(len(self.graphs)): layout = getattr(self, '%sLayout' % self.graphs[i]) self.tabs[i] = FigureTab(layout, self) # configure widgets self.rateValue.addItems(['10000', '5000', '1000', '500', '100', '50', '10', '5', '1']) self.rateValue.lineEdit().setReadOnly(True) self.rateValue.lineEdit().setAlignment(Qt.AlignRight) for i in range(self.rateValue.count()): self.rateValue.setItemData(i, Qt.AlignRight, Qt.TextAlignmentRole) self.set_enabled(False) self.stopSweep.setEnabled(False) # read settings settings = QSettings('vna.ini', QSettings.IniFormat) self.read_cfg_settings(settings) # create TCP socket self.socket = QTcpSocket(self) self.socket.connected.connect(self.connected) self.socket.readyRead.connect(self.read_data) self.socket.error.connect(self.display_error) # connect signals from widgets self.connectButton.clicked.connect(self.start) self.writeButton.clicked.connect(self.write_cfg) self.readButton.clicked.connect(self.read_cfg) self.openSweep.clicked.connect(partial(self.sweep, 'open')) self.shortSweep.clicked.connect(partial(self.sweep, 'short')) self.loadSweep.clicked.connect(partial(self.sweep, 'load')) self.singleSweep.clicked.connect(partial(self.sweep, 'dut')) self.autoSweep.clicked.connect(self.sweep_auto) self.stopSweep.clicked.connect(self.cancel) self.csvButton.clicked.connect(self.write_csv) self.s1pButton.clicked.connect(self.write_s1p) self.s2pshortButton.clicked.connect(self.write_s2p_short) self.s2popenButton.clicked.connect(self.write_s2p_open) self.startValue.valueChanged.connect(self.set_start) self.stopValue.valueChanged.connect(self.set_stop) self.sizeValue.valueChanged.connect(self.set_size) self.rateValue.currentIndexChanged.connect(self.set_rate) self.corrValue.valueChanged.connect(self.set_corr) self.phase1Value.valueChanged.connect(self.set_phase1) self.phase2Value.valueChanged.connect(self.set_phase2) self.level1Value.valueChanged.connect(self.set_level1) self.level2Value.valueChanged.connect(self.set_level2) self.tabWidget.currentChanged.connect(self.update_tab) # create timers self.startTimer = QTimer(self) self.startTimer.timeout.connect(self.timeout) self.sweepTimer = QTimer(self) self.sweepTimer.timeout.connect(self.sweep_timeout) def set_enabled(self, enabled): widgets = [self.rateValue, self.level1Value, self.level2Value, self.corrValue, self.phase1Value, self.phase2Value, self.startValue, self.stopValue, self.sizeValue, self.openSweep, self.shortSweep, self.loadSweep, self.singleSweep, self.autoSweep] for entry in widgets: entry.setEnabled(enabled) def start(self): if self.idle: self.connectButton.setEnabled(False) self.socket.connectToHost(self.addrValue.text(), 1001) self.startTimer.start(5000) else: self.stop() def stop(self): self.idle = True self.cancel() self.socket.abort() self.connectButton.setText('Connect') self.connectButton.setEnabled(True) self.set_enabled(False) self.stopSweep.setEnabled(False) def timeout(self): self.display_error('timeout') def connected(self): self.startTimer.stop() self.idle = False self.set_rate(self.rateValue.currentIndex()) self.set_corr(self.corrValue.value()) self.set_phase1(self.phase1Value.value()) self.set_phase2(self.phase2Value.value()) self.set_level1(self.level1Value.value()) self.set_level2(self.level2Value.value()) self.set_gpio(1) self.connectButton.setText('Disconnect') self.connectButton.setEnabled(True) self.set_enabled(True) self.stopSweep.setEnabled(True) def read_data(self): while(self.socket.bytesAvailable() > 0): if not self.reading: self.socket.readAll() return size = self.socket.bytesAvailable() self.progressBar.setValue((self.offset + size) / 16) limit = 16 * self.sweep_size if self.offset + size < limit: self.buffer[self.offset:self.offset + size] = self.socket.read(size) self.offset += size else: self.buffer[self.offset:limit] = self.socket.read(limit - self.offset) adc1 = self.data[0::2] adc2 = self.data[1::2] attr = getattr(self, self.mode) start = self.sweep_start stop = self.sweep_stop size = self.sweep_size attr.freq = np.linspace(start, stop, size) attr.data = adc1[0:size].copy() self.update_tab() self.reading = False if not self.auto: self.progressBar.setValue(0) self.set_enabled(True) def display_error(self, socketError): self.startTimer.stop() if socketError == 'timeout': QMessageBox.information(self, 'VNA', 'Error: connection timeout.') else: QMessageBox.information(self, 'VNA', 'Error: %s.' % self.socket.errorString()) self.stop() def set_start(self, value): self.sweep_start = value def set_stop(self, value): self.sweep_stop = value def set_size(self, value): self.sweep_size = value def set_rate(self, value): if self.idle: return rate = [5, 10, 50, 100, 500, 1000, 5000, 10000, 50000][value] self.socket.write(struct.pack('<I', 3<<28 | int(rate))) def set_corr(self, value): if self.idle: return self.socket.write(struct.pack('<I', 4<<28 | int(value))) def set_phase1(self, value): if self.idle: return self.socket.write(struct.pack('<I', 5<<28 | int(value))) def set_phase2(self, value): if self.idle: return self.socket.write(struct.pack('<I', 6<<28 | int(value))) def set_level1(self, value): if self.idle: return data = 0 if value == -90 else int(32766 * np.power(10.0, value / 20.0)) self.socket.write(struct.pack('<I', 7<<28 | int(data))) def set_level2(self, value): if self.idle: return data = 0 if value == -90 else int(32766 * np.power(10.0, value / 20.0)) self.socket.write(struct.pack('<I', 8<<28 | int(data))) def set_gpio(self, value): if self.idle: return self.socket.write(struct.pack('<I', 9<<28 | int(value))) def sweep(self, mode): if self.idle: return self.set_enabled(False) self.mode = mode self.offset = 0 self.reading = True self.socket.write(struct.pack('<I', 0<<28 | int(self.sweep_start * 1000))) self.socket.write(struct.pack('<I', 1<<28 | int(self.sweep_stop * 1000))) self.socket.write(struct.pack('<I', 2<<28 | int(self.sweep_size))) self.socket.write(struct.pack('<I', 10<<28)) self.progressBar.setMinimum(0) self.progressBar.setMaximum(self.sweep_size) self.progressBar.setValue(0) def cancel(self): self.sweepTimer.stop() self.auto = False self.reading = False self.socket.write(struct.pack('<I', 11<<28)) self.progressBar.setValue(0) self.set_enabled(True) def sweep_auto(self): self.auto = True self.sweepTimer.start(100) def sweep_timeout(self): if not self.reading: self.sweep('dut') def update_tab(self): index = self.tabWidget.currentIndex() self.tabs[index].update(self.graphs[index]) def interp(self, freq, meas): real = np.interp(freq, meas.freq, meas.data.real, period = meas.period) imag = np.interp(freq, meas.freq, meas.data.imag, period = meas.period) return real + 1j * imag def gain_short(self, freq): short = self.interp(freq, self.short) dut = self.interp(freq, self.dut) return np.divide(dut, short) def gain_open(self, freq): open = self.interp(freq, self.open) dut = self.interp(freq, self.dut) return np.divide(dut, open) def impedance(self, freq): open = self.interp(freq, self.open) short = self.interp(freq, self.short) load = self.interp(freq, self.load) dut = self.interp(freq, self.dut) z = np.divide(50.0 * (open - load) * (dut - short), (load - short) * (open - dut)) z = np.asarray(z) z.real[z.real < 1.0e-2] = 9.99e-3 return z def gamma(self, freq): z = self.impedance(freq) return np.divide(z - 50.0, z + 50.0) def swr(self, freq): magnitude = np.absolute(self.gamma(freq)) swr = np.divide(1.0 + magnitude, 1.0 - magnitude) return np.clip(swr, 1.0, 99.99) def write_cfg(self): dialog = QFileDialog(self, 'Write configuration settings', '.', '*.ini') dialog.setDefaultSuffix('ini') dialog.selectFile('vna.ini') dialog.setAcceptMode(QFileDialog.AcceptSave) dialog.setOptions(QFileDialog.DontConfirmOverwrite) if dialog.exec() == QDialog.Accepted: name = dialog.selectedFiles() settings = QSettings(name[0], QSettings.IniFormat) self.write_cfg_settings(settings) def read_cfg(self): dialog = QFileDialog(self, 'Read configuration settings', '.', '*.ini') dialog.setDefaultSuffix('ini') dialog.selectFile('vna.ini') dialog.setAcceptMode(QFileDialog.AcceptOpen) if dialog.exec() == QDialog.Accepted: name = dialog.selectedFiles() settings = QSettings(name[0], QSettings.IniFormat) self.read_cfg_settings(settings) window.update_tab() def write_cfg_settings(self, settings): settings.setValue('addr', self.addrValue.text()) settings.setValue('rate', self.rateValue.currentIndex()) settings.setValue('corr', self.corrValue.value()) settings.setValue('phase_1', self.phase1Value.value()) settings.setValue('phase_2', self.phase2Value.value()) settings.setValue('level_1', self.level1Value.value()) settings.setValue('level_2', self.level2Value.value()) settings.setValue('open_start', int(self.open.freq[0])) settings.setValue('open_stop', int(self.open.freq[-1])) settings.setValue('open_size', self.open.freq.size) settings.setValue('short_start', int(self.short.freq[0])) settings.setValue('short_stop', int(self.short.freq[-1])) settings.setValue('short_size', self.short.freq.size) settings.setValue('load_start', int(self.load.freq[0])) settings.setValue('load_stop', int(self.load.freq[-1])) settings.setValue('load_size', self.load.freq.size) settings.setValue('dut_start', int(self.dut.freq[0])) settings.setValue('dut_stop', int(self.dut.freq[-1])) settings.setValue('dut_size', self.dut.freq.size) for i in range(len(FigureTab.cursors)): settings.setValue('cursor_%d' % i, FigureTab.cursors[i]) data = self.open.data for i in range(self.open.freq.size): settings.setValue('open_real_%d' % i, float(data.real[i])) settings.setValue('open_imag_%d' % i, float(data.imag[i])) data = self.short.data for i in range(self.short.freq.size): settings.setValue('short_real_%d' % i, float(data.real[i])) settings.setValue('short_imag_%d' % i, float(data.imag[i])) data = self.load.data for i in range(self.load.freq.size): settings.setValue('load_real_%d' % i, float(data.real[i])) settings.setValue('load_imag_%d' % i, float(data.imag[i])) data = self.dut.data for i in range(self.dut.freq.size): settings.setValue('dut_real_%d' % i, float(data.real[i])) settings.setValue('dut_imag_%d' % i, float(data.imag[i])) def read_cfg_settings(self, settings): self.addrValue.setText(settings.value('addr', '192.168.1.100')) self.rateValue.setCurrentIndex(settings.value('rate', 0, type = int)) self.corrValue.setValue(settings.value('corr', 0, type = int)) self.phase1Value.setValue(settings.value('phase_1', 0, type = int)) self.phase2Value.setValue(settings.value('phase_2', 0, type = int)) self.level1Value.setValue(settings.value('level_1', 0, type = int)) self.level2Value.setValue(settings.value('level_2', -90, type = int)) open_start = settings.value('open_start', 10, type = int) open_stop = settings.value('open_stop', 60000, type = int) open_size = settings.value('open_size', 6000, type = int) short_start = settings.value('short_start', 10, type = int) short_stop = settings.value('short_stop', 60000, type = int) short_size = settings.value('short_size', 6000, type = int) load_start = settings.value('load_start', 10, type = int) load_stop = settings.value('load_stop', 60000, type = int) load_size = settings.value('load_size', 6000, type = int) dut_start = settings.value('dut_start', 10, type = int) dut_stop = settings.value('dut_stop', 60000, type = int) dut_size = settings.value('dut_size', 6000, type = int) self.startValue.setValue(dut_start) self.stopValue.setValue(dut_stop) self.sizeValue.setValue(dut_size) for i in range(len(FigureTab.cursors)): FigureTab.cursors[i] = settings.value('cursor_%d' % i, FigureTab.cursors[i], type = int) self.open.freq = np.linspace(open_start, open_stop, open_size) self.open.data = np.zeros(open_size, np.complex64) for i in range(open_size): real = settings.value('open_real_%d' % i, 0.0, type = float) imag = settings.value('open_imag_%d' % i, 0.0, type = float) self.open.data[i] = real + 1.0j * imag self.short.freq = np.linspace(short_start, short_stop, short_size) self.short.data = np.zeros(short_size, np.complex64) for i in range(short_size): real = settings.value('short_real_%d' % i, 0.0, type = float) imag = settings.value('short_imag_%d' % i, 0.0, type = float) self.short.data[i] = real + 1.0j * imag self.load.freq = np.linspace(load_start, load_stop, load_size) self.load.data = np.zeros(load_size, np.complex64) for i in range(load_size): real = settings.value('load_real_%d' % i, 0.0, type = float) imag = settings.value('load_imag_%d' % i, 0.0, type = float) self.load.data[i] = real + 1.0j * imag self.dut.freq = np.linspace(dut_start, dut_stop, dut_size) self.dut.data = np.zeros(dut_size, np.complex64) for i in range(dut_size): real = settings.value('dut_real_%d' % i, 0.0, type = float) imag = settings.value('dut_imag_%d' % i, 0.0, type = float) self.dut.data[i] = real + 1.0j * imag def write_csv(self): dialog = QFileDialog(self, 'Write csv file', '.', '*.csv') dialog.setDefaultSuffix('csv') dialog.setAcceptMode(QFileDialog.AcceptSave) dialog.setOptions(QFileDialog.DontConfirmOverwrite) if dialog.exec() == QDialog.Accepted: name = dialog.selectedFiles() fh = open(name[0], 'w') f = self.dut.freq o = self.interp(f, self.open) s = self.interp(f, self.short) l = self.interp(f, self.load) d = self.dut.data fh.write('frequency;open.real;open.imag;short.real;short.imag;load.real;load.imag;dut.real;dut.imag\n') for i in range(f.size): fh.write('0.0%.8d;%12.9f;%12.9f;%12.9f;%12.9f;%12.9f;%12.9f;%12.9f;%12.9f\n' % (f[i] * 1000, o.real[i], o.imag[i], s.real[i], s.imag[i], l.real[i], l.imag[i], d.real[i], d.imag[i])) fh.close() def write_s1p(self): dialog = QFileDialog(self, 'Write s1p file', '.', '*.s1p') dialog.setDefaultSuffix('s1p') dialog.setAcceptMode(QFileDialog.AcceptSave) dialog.setOptions(QFileDialog.DontConfirmOverwrite) if dialog.exec() == QDialog.Accepted: name = dialog.selectedFiles() fh = open(name[0], 'w') freq = self.dut.freq gamma = self.gamma(freq) fh.write('# GHz S MA R 50\n') for i in range(freq.size): fh.write('0.0%.8d %8.6f %7.2f\n' % (freq[i] * 1000, np.absolute(gamma[i]), np.angle(gamma[i], deg = True))) fh.close() def write_s2p(self, gain): dialog = QFileDialog(self, 'Write s2p file', '.', '*.s2p') dialog.setDefaultSuffix('s2p') dialog.setAcceptMode(QFileDialog.AcceptSave) dialog.setOptions(QFileDialog.DontConfirmOverwrite) if dialog.exec() == QDialog.Accepted: name = dialog.selectedFiles() fh = open(name[0], 'w') freq = self.dut.freq gamma = self.gamma(freq) fh.write('# GHz S MA R 50\n') for i in range(freq.size): fh.write('0.0%.8d %8.6f %7.2f %8.6f %7.2f 0.000000 0.00 0.000000 0.00\n' % (freq[i] * 1000, np.absolute(gamma[i]), np.angle(gamma[i], deg = True), np.absolute(gain[i]), np.angle(gain[i], deg = True))) fh.close() def write_s2p_short(self): self.write_s2p(self.gain_short(self.dut.freq)) def write_s2p_open(self): self.write_s2p(self.gain_open(self.dut.freq))
class RedirectedIORunWrapper(): """Wrapper to run a script with redirected IO""" def __init__(self): self.__socket = None self.__redirected = False self.__procuuid = None def redirected(self): """True if streams are redirected""" return self.__redirected def main(self): """Run wrapper driver""" if '--' not in sys.argv: print("Unexpected arguments", file=sys.stderr) return 1 self.__procuuid, host, port, args = self.parseArgs() if self.__procuuid is None or host is None or port is None: print("Not enough arguments", file=sys.stderr) return 1 remoteAddress = self.resolveHost(host) self.connect(remoteAddress, port) sendJSONCommand(self.__socket, METHOD_PROC_ID_INFO, self.__procuuid, None) try: waitForIDEMessage(self.__socket, METHOD_PROLOGUE_CONTINUE, WAIT_CONTINUE_TIMEOUT) except Exception as exc: print(str(exc), file=sys.stderr) return 1 # Setup redirections stdoutOld = sys.stdout stderrOld = sys.stderr sys.stdout = OutStreamRedirector(self.__socket, True, self.__procuuid) sys.stderr = OutStreamRedirector(self.__socket, False, self.__procuuid) self.__redirected = True # Run the script retCode = 0 try: self.__runScript(args) except SystemExit as exc: if CLIENT_DEBUG: print(traceback.format_exc(), file=sys.__stderr__) if exc.code is None: retCode = 0 elif isinstance(exc.code, int): retCode = exc.code else: retCode = 1 print(str(exc.code), file=sys.stderr) except KeyboardInterrupt as exc: if CLIENT_DEBUG: print(traceback.format_exc(), file=sys.__stderr__) retCode = 1 print(traceback.format_exc(), file=sys.stderr) except Exception as exc: if CLIENT_DEBUG: print(traceback.format_exc(), file=sys.__stderr__) retCode = 1 print(traceback.format_exc(), file=sys.stderr) except: if CLIENT_DEBUG: print(traceback.format_exc(), file=sys.__stderr__) retCode = 1 print(traceback.format_exc(), file=sys.stderr) sys.stderr = stderrOld sys.stdout = stdoutOld self.__redirected = False # Send the return code back try: sendJSONCommand(self.__socket, METHOD_EPILOGUE_EXIT_CODE, self.__procuuid, {'exitCode': retCode}) except Exception as exc: print(str(exc), file=sys.stderr) self.close() return 1 self.close() return 0 def connect(self, remoteAddress, port): """Establishes a connection with the IDE""" self.__socket = QTcpSocket() if remoteAddress is None: self.__socket.connectToHost(QHostAddress.LocalHost, port) else: self.__socket.connectToHost(remoteAddress, port) if not self.__socket.waitForConnected(1000): raise Exception('Cannot connect to the IDE') self.__socket.setSocketOption(QAbstractSocket.KeepAliveOption, 1) self.__socket.setSocketOption(QAbstractSocket.LowDelayOption, 1) self.__socket.disconnected.connect(self.__onDisconnected) def __onDisconnected(self): """IDE dropped the socket""" sys.exit(0) def __runScript(self, arguments): """Runs the python script""" try: # In Py 2.x, the builtins were in __builtin__ builtins = sys.modules['__builtin__'] except KeyError: # In Py 3.x, they're in builtins builtins = sys.modules['builtins'] fileName = arguments[0] oldMainMod = sys.modules['__main__'] mainMod = imp.new_module('__main__') sys.modules['__main__'] = mainMod mainMod.__file__ = fileName mainMod.__builtins__ = builtins # Set sys.argv properly. oldArgv = sys.argv sys.argv = arguments # Without this imports of what is located at the script directory do # not work normCWD = os.path.normpath(os.getcwd()) normScriptDir = os.path.normpath(os.path.dirname(fileName)) sys.path.insert(0, os.getcwd()) if normCWD != normScriptDir: sys.path.insert(0, os.path.dirname(fileName)) with open(fileName, 'rb') as fileToRead: source = fileToRead.read() # We have the source. `compile` still needs the last line to be clean, # so make sure it is, then compile a code object from it. if not source or source[-1] != b'\n': source += b'\n' code = compile(source, fileName, "exec") exec(code, mainMod.__dict__) # Restore the old __main__ sys.modules['__main__'] = oldMainMod # Restore the old argv and path sys.argv = oldArgv def close(self): """Closes the connection if so""" try: if self.__socket: # Wait exit needed because otherwise IDE may get socket # disconnected before it has a chance to read the script # exit code. Wait for the explicit command to exit guarantees # that all the data will be received. waitForIDEMessage(self.__socket, METHOD_EPILOGUE_EXIT, WAIT_EXIT_COMMAND_TIMEOUT) finally: if self.__socket: self.__socket.close() self.__socket = None def input(self, prompt, echo): """Implements 'input' using the redirected input""" sendJSONCommand(self.__socket, METHOD_STDIN, self.__procuuid, { 'prompt': prompt, 'echo': echo }) params = waitForIDEMessage(self.__socket, METHOD_STDIN, 60 * 60 * 24 * 7) return params['input'] @staticmethod def resolveHost(host): """Resolves a hostname to an IP address""" try: host, _ = host.split("@@") family = socket.AF_INET6 except ValueError: # version = 'v4' family = socket.AF_INET return socket.getaddrinfo(host, None, family, socket.SOCK_STREAM)[0][4][0] @staticmethod def parseArgs(): """Parses the arguments""" host = None port = None procuuid = None args = sys.argv[1:] while args[0]: if args[0] in ['--host']: host = args[1] del args[0] del args[0] elif args[0] in ['--port']: port = int(args[1]) del args[0] del args[0] elif args[0] in ['--procuuid']: procuuid = args[1] del args[0] del args[0] elif args[0] == '--': del args[0] break return procuuid, host, port, args
class JsonRpcTcpClient(QObject): def __init__(self, request_handler_instance): QObject.__init__(self) self.socket = QTcpSocket(self) self.connectionAttempts = 1 self.socket.readyRead.connect(self.onData) self.socket.error.connect(self.onSocketError) self.request_handler_instance = request_handler_instance self.nextid = 1 self.callbacks_result = {} self.callbacks_error = {} self.buffer = b'' def connect(self, host, port): self.host = host self.port = port self.socket.connectToHost(host, port) @QtCore.pyqtSlot(QAbstractSocket.SocketError) def onSocketError(self, error): if (error == QAbstractSocket.ConnectionRefusedError): self.socket.connectToHost(self.host, self.port) self.connectionAttempts += 1 #self._logger.info("reconnecting to JSONRPC server {}".format(self.connectionAttempts)) else: raise RuntimeError( "Connection error to JSON RPC server: {} ({})".format( self.socket.errorString(), error)) def close(self): self.socket.close() def parseRequest(self, request): try: m = getattr(self.request_handler_instance, request["method"]) if "params" in request and len(request["params"]) > 0: result = m(*request["params"]) else: result = m() # we do not only have a notification, but a request which awaits a response if "id" in request: responseObject = { "id": request["id"], "result": result, "jsonrpc": "2.0" } self.socket.write(json.dumps(responseObject)) except AttributeError: if "id" in request: responseObject = { "id": request["id"], "error": "no such method", "jsonrpc": "2.0" } self.socket.write(json.dumps(responseObject)) def parseResponse(self, response): if "error" in response: self._logger.error("response error {}".format(response)) if "id" in response: if response["id"] in self.callbacks_error: self.callbacks_error[response["id"]](response["error"]) elif "result" in response: if "id" in response: if response["id"] in self.callbacks_result: self.callbacks_result[response["id"]](response["result"]) if "id" in response: self.callbacks_error.pop(response["id"], None) self.callbacks_result.pop(response["id"], None) @QtCore.pyqtSlot() def onData(self): newData = b'' while self.socket.bytesAvailable(): newData += bytes(self.socket.readAll()) # this seems to be a new notification, which invalidates our buffer. This may happen on malformed JSON data if newData.startswith(b"{\"jsonrpc\":\"2.0\""): if len(self.buffer) > 0: self._logger.error( "parse error: discarding old possibly malformed buffer data {}" .format(self.buffer)) self.buffer = newData else: self.buffer += newData self.buffer = self.processBuffer(self.buffer.strip()) #from https://github.com/joncol/jcon-cpp/blob/master/src/jcon/json_rpc_endpoint.cpp#L107 def processBuffer(self, buf): if len(buf) == 0: return b'' if not buf.startswith(b'{'): self._logger.error( "parse error: buffer expected to start {{: {}".format(buf)) return b'' in_string = False brace_nesting_level = 0 for i, c in enumerate(buf): if c == ord('"'): in_string = not in_string if not in_string: if c == ord('{'): brace_nesting_level += 1 if c == ord('}'): brace_nesting_level -= 1 if brace_nesting_level < 0: self._logger.error( "parse error: brace_nesting_level < 0: {}".format( buf)) return b'' if brace_nesting_level == 0: complete_json_buf = buf[:i + 1] remaining_buf = buf[i + 1:] try: request = json.loads(complete_json_buf) except ValueError: self._logger.error( "json.loads failed for {}".format( complete_json_buf)) return b'' print("JsonRpcTcpClient received: {}".format(request)) # is this a request? if "method" in request: self.parseRequest(request) # this is only a response else: self.parseResponse(request) return self.processBuffer(remaining_buf.strip()) return buf def call(self, method, args=[], callback_result=None, callback_error=None): if self.socket.state() != QAbstractSocket.ConnectedState: raise RuntimeError("Not connected to the JSONRPC server.") rpcObject = {"method": method, "params": args, "jsonrpc": "2.0"} if callback_result: rpcObject["id"] = self.nextid self.callbacks_result[self.nextid] = callback_result if callback_error: self.callbacks_error[self.nextid] = callback_error self.nextid += 1 self._logger.debug("sending JSONRPC object {}".format(rpcObject)) self.socket.write(json.dumps(rpcObject).encode("utf-8") + b'\n')
class Dialog(QDialog): TotalBytes = 50 * 1024 * 1024 PayloadSize = 65536 def __init__(self, parent=None): super(Dialog, self).__init__(parent) self.tcpServer = QTcpServer() self.tcpClient = QTcpSocket() self.bytesToWrite = 0 self.bytesWritten = 0 self.bytesReceived = 0 self.clientProgressBar = QProgressBar() self.clientStatusLabel = QLabel("Client ready") self.serverProgressBar = QProgressBar() self.serverStatusLabel = QLabel("Server ready") self.startButton = QPushButton("&Start") self.quitButton = QPushButton("&Quit") buttonBox = QDialogButtonBox() buttonBox.addButton(self.startButton, QDialogButtonBox.ActionRole) buttonBox.addButton(self.quitButton, QDialogButtonBox.RejectRole) self.startButton.clicked.connect(self.start) self.quitButton.clicked.connect(self.close) self.tcpServer.newConnection.connect(self.acceptConnection) self.tcpClient.connected.connect(self.startTransfer) self.tcpClient.bytesWritten.connect(self.updateClientProgress) self.tcpClient.error.connect(self.displayError) mainLayout = QVBoxLayout() mainLayout.addWidget(self.clientProgressBar) mainLayout.addWidget(self.clientStatusLabel) mainLayout.addWidget(self.serverProgressBar) mainLayout.addWidget(self.serverStatusLabel) mainLayout.addStretch(1) mainLayout.addSpacing(10) mainLayout.addWidget(buttonBox) self.setLayout(mainLayout) self.setWindowTitle("Loopback") def start(self): self.startButton.setEnabled(False) QApplication.setOverrideCursor(Qt.WaitCursor) self.bytesWritten = 0 self.bytesReceived = 0 while not self.tcpServer.isListening() and not self.tcpServer.listen(): ret = QMessageBox.critical(self, "Loopback", "Unable to start the test: %s." % self.tcpServer.errorString(), QMessageBox.Retry | QMessageBox.Cancel) if ret == QMessageBox.Cancel: return self.serverStatusLabel.setText("Listening") self.clientStatusLabel.setText("Connecting") self.tcpClient.connectToHost(QHostAddress(QHostAddress.LocalHost), self.tcpServer.serverPort()) def acceptConnection(self): self.tcpServerConnection = self.tcpServer.nextPendingConnection() self.tcpServerConnection.readyRead.connect(self.updateServerProgress) self.tcpServerConnection.error.connect(self.displayError) self.serverStatusLabel.setText("Accepted connection") self.tcpServer.close() def startTransfer(self): self.bytesToWrite = Dialog.TotalBytes - self.tcpClient.write(QByteArray(Dialog.PayloadSize, '@')) self.clientStatusLabel.setText("Connected") def updateServerProgress(self): self.bytesReceived += self.tcpServerConnection.bytesAvailable() self.tcpServerConnection.readAll() self.serverProgressBar.setMaximum(Dialog.TotalBytes) self.serverProgressBar.setValue(self.bytesReceived) self.serverStatusLabel.setText("Received %dMB" % (self.bytesReceived / (1024 * 1024))) if self.bytesReceived == Dialog.TotalBytes: self.tcpServerConnection.close() self.startButton.setEnabled(True) QApplication.restoreOverrideCursor() def updateClientProgress(self, numBytes): self.bytesWritten += numBytes if self.bytesToWrite > 0: self.bytesToWrite -= self.tcpClient.write(QByteArray( min(self.bytesToWrite, Dialog.PayloadSize), '@')) self.clientProgressBar.setMaximum(Dialog.TotalBytes) self.clientProgressBar.setValue(self.bytesWritten) self.clientStatusLabel.setText("Sent %dMB" % (self.bytesWritten / (1024 * 1024))) def displayError(self, socketError): if socketError == QTcpSocket.RemoteHostClosedError: return QMessageBox.information(self, "Network error", "The following error occured: %s." % self.tcpClient.errorString()) self.tcpClient.close() self.tcpServer.close() self.clientProgressBar.reset() self.serverProgressBar.reset() self.clientStatusLabel.setText("Client ready") self.serverStatusLabel.setText("Server ready") self.startButton.setEnabled(True) QApplication.restoreOverrideCursor()
class Client(QDialog): def __init__(self): super().__init__() self.tcpSocket = QTcpSocket(self) self.blockSize = 0 self.makeRequest() self.tcpSocket.waitForConnected(1000) # send any message you like it could come from a widget text. self.tcpSocket.write(b'hello') self.tcpSocket.readyRead.connect(self.dealCommunication) self.tcpSocket.error.connect(self.displayError) def makeRequest(self): HOST = '127.0.0.1' PORT = 8000 self.tcpSocket.connectToHost(HOST, PORT, QIODevice.ReadWrite) def dealCommunication(self): instr = QDataStream(self.tcpSocket) instr.setVersion(QDataStream.Qt_5_0) if self.blockSize == 0: if self.tcpSocket.bytesAvailable() < 2: return self.blockSize = instr.readUInt16() if self.tcpSocket.bytesAvailable() < self.blockSize: return # Print response to terminal, we could use it anywhere else we wanted. print(str(instr.readString(), encoding='ascii')) def displayError(self, socketError): if socketError == QAbstractSocket.RemoteHostClosedError: pass else: print(self, "The following error occurred: %s." % self.tcpSocket.errorString())