def handleRecv(self): ip = QHostAddress() buf = bytes() buf, ip, port = self.udpSocket.readDatagram(1024) ip = ip.toString() message = buf.decode() self.ui.textEdit.setText('{Ip},{Port}:{Message}'.format(Ip=ip, Port=port, Message=message))
def sessionOpened(self): if self.networkSession is not None: 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.tcpServer = QTcpServer(self) if not self.tcpServer.listen(): QMessageBox.critical(self, "Fortune Server", "Unable to start the server: %s." % self.tcpServer.errorString()) self.close() return for ipAddress in QNetworkInterface.allAddresses(): if ipAddress != QHostAddress.LocalHost and ipAddress.toIPv4Address() != 0: break else: ipAddress = QHostAddress(QHostAddress.LocalHost) ipAddress = ipAddress.toString() self.statusLabel.setText("The server is running on\n\nIP: %s\nport %d\n\n" "Run the Fortune Client example now." % (ipAddress, self.tcpServer.serverPort()))
def getIPAddress(): for ipAddress in QNetworkInterface.allAddresses(): if ipAddress != QHostAddress.LocalHost and ipAddress.toIPv4Address( ) != 0: break else: ipAddress = QHostAddress(QHostAddress.LocalHost) return ipAddress.toString()
def __init__(self, parent=None): super(BlockingClient, self).__init__(parent) self.thread = FortuneThread() self.currentFortune = "" hostLabel = QLabel("&Server name:") portLabel = QLabel("S&erver port:") for ipAddress in QNetworkInterface.allAddresses(): if ipAddress != QHostAddress.LocalHost and ipAddress.toIPv4Address( ) != 0: break else: ipAddress = QHostAddress(QHostAddress.LocalHost) ipAddress = ipAddress.toString() self.hostLineEdit = QLineEdit(ipAddress) self.portLineEdit = QLineEdit() self.portLineEdit.setValidator(QIntValidator(1, 65535, self)) hostLabel.setBuddy(self.hostLineEdit) portLabel.setBuddy(self.portLineEdit) self.statusLabel = QLabel( "This example requires that you run the Fortune Server example as well." ) self.statusLabel.setWordWrap(True) 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.getFortuneButton.clicked.connect(self.requestNewFortune) quitButton.clicked.connect(self.close) self.hostLineEdit.textChanged.connect(self.enableGetFortuneButton) self.portLineEdit.textChanged.connect(self.enableGetFortuneButton) self.thread.newFortune.connect(self.showFortune) self.thread.error.connect(self.displayError) mainLayout = QGridLayout() mainLayout.addWidget(hostLabel, 0, 0) mainLayout.addWidget(self.hostLineEdit, 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("Blocking Fortune Client") self.portLineEdit.setFocus()
def __init__(self, parent=None): super(BlockingClient, self).__init__(parent) self.thread = FortuneThread() self.currentFortune = '' hostLabel = QLabel("&Server name:") portLabel = QLabel("S&erver port:") for ipAddress in QNetworkInterface.allAddresses(): if ipAddress != QHostAddress.LocalHost and ipAddress.toIPv4Address() != 0: break else: ipAddress = QHostAddress(QHostAddress.LocalHost) ipAddress = ipAddress.toString() self.hostLineEdit = QLineEdit(ipAddress) self.portLineEdit = QLineEdit() self.portLineEdit.setValidator(QIntValidator(1, 65535, self)) hostLabel.setBuddy(self.hostLineEdit) portLabel.setBuddy(self.portLineEdit) self.statusLabel = QLabel( "This example requires that you run the Fortune Server example as well.") self.statusLabel.setWordWrap(True) 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.getFortuneButton.clicked.connect(self.requestNewFortune) quitButton.clicked.connect(self.close) self.hostLineEdit.textChanged.connect(self.enableGetFortuneButton) self.portLineEdit.textChanged.connect(self.enableGetFortuneButton) self.thread.newFortune.connect(self.showFortune) self.thread.error.connect(self.displayError) mainLayout = QGridLayout() mainLayout.addWidget(hostLabel, 0, 0) mainLayout.addWidget(self.hostLineEdit, 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("Blocking Fortune Client") self.portLineEdit.setFocus()
def __init__(self, parent=None): super(Dialog, self).__init__(parent) self.server = FortuneServer() statusLabel = QLabel() statusLabel.setWordWrap(True) quitButton = QPushButton("Quit") quitButton.setAutoDefault(False) if not self.server.listen(): QMessageBox.critical( self, "Threaded Fortune Server", "Unable to start the server: %s." % self.server.errorString(), ) self.close() return for ipAddress in QNetworkInterface.allAddresses(): if ipAddress != QHostAddress.LocalHost and ipAddress.toIPv4Address() != 0: break else: ipAddress = QHostAddress(QHostAddress.LocalHost) ipAddress = ipAddress.toString() statusLabel.setText( "The server is running on\n\nIP: %s\nport: %d\n\n" "Run the Fortune Client example now." % (ipAddress, self.server.serverPort()) ) quitButton.clicked.connect(self.close) buttonLayout = QHBoxLayout() buttonLayout.addStretch(1) buttonLayout.addWidget(quitButton) buttonLayout.addStretch(1) mainLayout = QVBoxLayout() mainLayout.addWidget(statusLabel) mainLayout.addLayout(buttonLayout) self.setLayout(mainLayout) self.setWindowTitle("Threaded Fortune Server")
def __init__(self, parent=None): super(Dialog, self).__init__(parent) self.server = FortuneServer() statusLabel = QLabel() statusLabel.setWordWrap(True) quitButton = QPushButton("Quit") quitButton.setAutoDefault(False) if not self.server.listen(): QMessageBox.critical(self, "Threaded Fortune Server", "Unable to start the server: %s." % self.server.errorString()) self.close() return for ipAddress in QNetworkInterface.allAddresses(): if ipAddress != QHostAddress.LocalHost and ipAddress.toIPv4Address() != 0: break else: ipAddress = QHostAddress(QHostAddress.LocalHost) ipAddress = ipAddress.toString() statusLabel.setText("The server is running on\n\nIP: %s\nport: %d\n\n" "Run the Fortune Client example now." % (ipAddress, self.server.serverPort())) quitButton.clicked.connect(self.close) buttonLayout = QHBoxLayout() buttonLayout.addStretch(1) buttonLayout.addWidget(quitButton) buttonLayout.addStretch(1) mainLayout = QVBoxLayout() mainLayout.addWidget(statusLabel) mainLayout.addLayout(buttonLayout) self.setLayout(mainLayout) self.setWindowTitle("Threaded Fortune Server")
def listen(self, host=None, port=3000): """Method making the server listening to a given address.""" # If no address was specified: trying to give the best one if host is None: for ip in self.get_available_ips(): if ip != QHostAddress.LocalHost and ip.toIPv4Address(): host = ip if host is None: # No suitable address was found host = QHostAddress.LocalHost # The address was given as string if type(host) == str: host = QHostAddress(host) # For printing... address = "{}:{}".format(host.toString(), port) # Launching server if not self.__tcpServer.listen(host, port): self.__tcpServer.close() print("Unable to listen on address '{}': {}.".format( address, self.__tcpServer.errorString())) raise ConnectionError(self.__tcpServer.errorString()) else: print("Server is listening on address '{}'.".format(address)) self.listening.emit((host, port))
def sessionOpened(self): if self.networkSession is not None: 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.tcpServer = QTcpServer(self) if not self.tcpServer.listen(): QMessageBox.critical( self, "Fortune Server", "Unable to start the server: %s." % self.tcpServer.errorString()) self.close() return for ipAddress in QNetworkInterface.allAddresses(): if ipAddress != QHostAddress.LocalHost and ipAddress.toIPv4Address( ) != 0: break else: ipAddress = QHostAddress(QHostAddress.LocalHost) ipAddress = ipAddress.toString() self.statusLabel.setText( "The server is running on\n\nIP: %s\nport %d\n\n" "Run the Fortune Client example now." % (ipAddress, self.tcpServer.serverPort()))
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 LogServer(QTcpServer): def __init__(self, main_window, on_connection, log, stop_signal): super().__init__() self.log = log.getChild('TCP') self.log.info('Initializing') self.main_window = main_window self.on_connection = on_connection self.stop_signal = stop_signal self.host, self.port = CONFIG.listen_address self.host = QHostAddress(self.host) self.benchmark = CONFIG['benchmark'] self.threads = [] self.connections = 0 def start(self): self.log.info('Starting the server') if self.benchmark: self.log.debug('Starting a benchmark connection') new_conn = BenchmarkConnection(self, None, "benchmark", self.stop_signal, self.log) self.on_connection(new_conn, "benchmark") self.threads.append(new_conn) new_conn.start() result = self.listen(self.host, self.port) if not result: err_string = self.errorString() show_critical_dialog(self.main_window, 'Error while starting the server', err_string) else: address = "{}:{}".format(self.host.toString(), self.port) self.main_window.set_status( 'Server is listening on {}...'.format(address)) def incomingConnection(self, socketDescriptor): self.connections += 1 name = 'Logger {}'.format(self.connections) self.log.info('New connection: "{}"'.format(name)) new_conn = LogConnection(self, socketDescriptor, name, self.stop_signal, self.log) self.on_connection(new_conn, name) new_conn.finished.connect(new_conn.deleteLater) new_conn.connection_finished.connect(self.cleanup_connection) new_conn.start() self.threads.append(new_conn) def close_server(self, wait=True): self.log.debug('Closing the server') self.main_window.set_status('Stopping the server...') self.close() if wait: self.wait_connections_stopped() self.main_window.set_status('Server has stopped') def wait_connections_stopped(self): self.log.debug('Waiting for {} connections threads to stop'.format( len(self.threads))) to_wait = self.threads.copy( ) # to protect against changes during iteration for thread in to_wait: try: if not thread.wait(1000): self.log.error( 'Thread "{}" didn\'t stop in time, terminating'.format( thread)) thread.terminate() self.log.error('Thread "{}" terminated'.format(thread)) except RuntimeError: # happens when thread has been deleted before we got to it self.log.debug( 'Thread {} has been deleted already'.format(thread)) self.log.debug('All connections stopped') def cleanup_connection(self, connection): try: self.threads.remove(connection) except Exception as e: self.log.error( 'Double delete on connection: {}'.format(connection), exc_info=True)
class TcpServer(QWidget): def __init__(self): super().__init__() self.isUp = False self.port = 8888 self.serverIP = QHostAddress('127.0.0.1') self.tcpClientList = [] self.initUi() def initUi(self): self.ui = ui_tcpServer.Ui_Form() self.ui.setupUi(self) self.ui.splitter.setStretchFactor(1,1) self.ui.portLineEdit.setText(str(self.port)) self.ui.serverIPLineEdit.setText(self.serverIP.toString()) self.ui.openBtn.clicked.connect(self.slotOpenOrClose) self.show() def validate(self): 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 slotOpenOrClose(self): if not self.isUp: if not self.validate(): return self.openRoom() else: self.closeRoom() def openRoom(self): self.ui.openBtn.setText('Close Chat Room') self.isUp = True self.ui.serverIPLineEdit.setEnabled(False) self.ui.portLineEdit.setEnabled(False) self.tcpServer = QTcpServer() self.tcpServer.listen(self.serverIP, self.port) msg = '[*] Server is listening on {}:{} ........'.format(self.serverIP.toString(), self.port) self.ui.contentListWidget.addItem(msg) self.tcpServer.newConnection.connect(self.addClient2List) def closeRoom(self): del (self.tcpServer) self.tcpClientList = [] self.ui.userListWidget.clear() self.isUp = False self.ui.serverIPLineEdit.setEnabled(True) self.ui.portLineEdit.setEnabled(True) self.ui.openBtn.setText('Open Chat Room') msg = '[*] Chat Room is closed........' self.ui.contentListWidget.addItem(msg) def addClient2List(self): tcpClientSocket = self.tcpServer.nextPendingConnection() client = ConnectClient(tcpClientSocket) self.tcpClientList.append(client) tcpClientSocket.readyRead.connect(self.slotDataReceived) tcpClientSocket.disconnected.connect(self.slotDisconnected) self.ui.onlineNumLabel.setText(str(len(self.tcpClientList))) def slotDataReceived(self): tcpClientSocket = self.sender() recvData = '' while tcpClientSocket.bytesAvailable() > 0: recvData += str(tcpClientSocket.read(tcpClientSocket.bytesAvailable()), encoding='utf-8') self.ui.contentListWidget.addItem(recvData) self.ui.contentListWidget.scrollToBottom() self._parseData(recvData, tcpClientSocket) # 实现信息的广播, tcpClientList中保存了所有与服务器相连的TcpClientSocket对象 for client in self.tcpClientList: client.socket.write(bytes(recvData, encoding='utf-8')) def slotDisconnected(self): # 从tcpClientList列表中将断开连接的TcpClientSocket对象删除 tcpClientSocket = self.sender() idx = self._findClient(tcpClientSocket) if idx >= 0: del (self.tcpClientList[idx]) self.ui.onlineNumLabel.setText(str(len(self.tcpClientList))) def _findClient(self, socket): for idx, client in enumerate(self.tcpClientList): if client.socket is socket: return idx return -1 def _parseData(self, data, socket): if data.startswith('[+]'): name = data.split(':')[0][4:] idx = self._findClient(socket) if idx >= 0: self.tcpClientList[idx].name = name self.ui.userListWidget.addItem(name) elif data.startswith('[-]'): idx = self._findClient(socket) if idx >= 0: self.ui.userListWidget.takeItem(idx) def closeEvent(self, event): if self.isUp: msg = 'Are you sure to close the chat room ?' reply = QMessageBox().warning(self, 'Quit', msg, QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if reply == QMessageBox.Yes: self.closeRoom() event.accept() else: event.ignore() else: event.accept()
class QidiConnectionManager(QObject): progressChanged = pyqtSignal(int) conectionStateChanged = pyqtSignal(bool) updateDone = pyqtSignal() def __init__(self, ip_addr, temp_gcode_file, log_enabled=False): super().__init__() self._ip = QHostAddress(ip_addr) self._localTempGcode = temp_gcode_file self._port = 3000 self.BUFSIZE = 1280 self._file_encode = 'utf-8' self._abort = False self._filename = None self._log_enabled = log_enabled self._connected = False self._socket = QUdpSocket(self) self._last_reply = None self._isPrinting = False self._isIdle = False self._print_now = 0 self._print_total = 0 self._busy = False self._printing_filename = "" self._firmware_ver = "" self._printing_time = 0 self._update_fail_cnt = 0 self._last_times = [] self._status = {} self._mutex = Lock() self._config = {'e_mm_per_step': '0.0', 's_machine_type': '0', 's_x_max': '0.0', 's_y_max': '0.0', 's_z_max': '0.0', 'x_mm_per_step': '0.0', 'y_mm_per_step': '0.0', 'z_mm_per_step': '0.0'} self.__log("d", "LocalPort: {}", self._socket.localPort()) def __log(self, log_type: str, message: str, *args, **kwargs): if self._log_enabled: Logger.log(log_type, message, *args, **kwargs) def __send(self, cmd): new_command = cast(str, cmd).encode(self._file_encode, 'ignore') if type(cmd) is str else cast(bytes, cmd) # type: bytes self._socket.writeDatagram(new_command, self._ip, self._port) def __recieve(self, timeout_ms=100): if timeout_ms > 0: start = Timer() + timeout_ms / 1000.0 while Timer() < start and not self._socket.hasPendingDatagrams(): pass msg = '' res = QidiResult.TIMEOUT while self._socket.hasPendingDatagrams(): datagram, host, port = self._socket.readDatagram(self._socket.pendingDatagramSize()) if datagram: msg += datagram.decode(self._file_encode, 'ignore') res = QidiResult.SUCCES if 'Error:Wifi reboot' in msg or 'Error:IP is connected' in msg: res = QidiResult.DISCONNECTED self._connected = False self.conectionStateChanged.emit(self._connected) return msg, res def sendCommand(self, cmd): result = self._mutex.acquire(blocking=True, timeout=1) if result: self.__send(cmd) self._mutex.release() else: self.__log("d", 'timeout: lock not available') def request(self, cmd, timeout_ms=100, retries=1): tryCnt = 0 msg = '' res = QidiResult.TIMEOUT self.__recieve(0) # discard pending datagrams while tryCnt < retries: tryCnt += 1 if type(cmd) is str: self.__log("d", '[{}]sending cmd to {}: {}', tryCnt, self._ip.toString(), cmd) if self.abort is True: return '', QidiResult.ABORTED if not self._connected: return '', QidiResult.DISCONNECTED self.__send(cmd) msg, res = self.__recieve(timeout_ms) if res == QidiResult.SUCCES: if type(cmd) is str: # Log reply message only for str commands self.__log("d", 'got reply from {}: {}', self._ip.toString(), str(msg).rstrip()) break return msg, res def abort(self): self.abort = True def connect(self, retries=1): with self._mutex: return self.__connect(retries) def __connect(self, retries=1): tryCnt = 0 while tryCnt < retries and self._connected == False: tryCnt += 1 self.__send("M4001") msg, res = self.__recieve() if res is not QidiResult.SUCCES: self.__log("w", '{} Connection timeout ', self._ip.toString()) continue self.__log("d", 'Connected') msg = msg.rstrip() self.__log("d", msg) msgs = msg.split(' ') for item in msgs: _ = item.split(':') if len(_) == 2: id = _[0] value = _[1] if id == 'X': self._config["x_mm_per_step"] = value elif id == 'Y': self._config["y_mm_per_step"] = value elif id == 'Z': self._config["z_mm_per_step"] = value elif id == 'E': self._config["e_mm_per_step"] = value elif id == 'T': _ = value.split('/') if len(_) == 5: self._config["s_machine_type"] = _[0] self._config["s_x_max"] = _[1] self._config["s_y_max"] = _[2] self._config["s_z_max"] = _[3] elif id == 'U': self._file_encode = value.replace("'", '') self._connected = True msg, res = self.request('M4002 ', 2000, 2) if res == QidiResult.SUCCES: if 'ok ' in msg: msg = msg.rstrip() msg = msg.split('ok ') self._firmware_ver = msg[1] self.conectionStateChanged.emit(self._connected) return True return False def __compress_gcode(self): exePath = None if Platform.isWindows(): exePath = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'VC_compress_gcode.exe') elif Platform.isOSX(): exePath = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'VC_compress_gcode_MAC') else: self.__log("w", "Could not find gcode compression tool") if exePath is not None and os.path.exists(exePath): cmd = '"' + exePath + '"' + ' "' + self._localTempGcode + '" ' + self._config["x_mm_per_step"] + ' ' + self._config["y_mm_per_step"] + ' ' + self._config["z_mm_per_step"] + ' ' + \ self._config["e_mm_per_step"] + ' "' + os.path.dirname(self._localTempGcode) + '" ' \ + self._config["s_x_max"] + ' ' + self._config["s_y_max"] + ' ' + self._config["s_z_max"] + ' ' + self._config["s_machine_type"] self.__log("d", cmd) ret = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True) self.__log("d", ret.stdout.read().decode('utf-8', 'ignore').rstrip()) if os.path.exists(self._localTempGcode + '.tz'): # check whether the compression succedded return True else: return False def __send_start_write(self, filename): self.__log("i", 'Creating file {}', filename) msg, res = self.request('M28 ' + filename, 2000, 3) if res == QidiResult.SUCCES: if 'Error' in msg: self.__log("e", 'cmd:' + msg) return QidiResult.WRITE_ERROR else: return QidiResult.SUCCES return res def __send_end_write(self, filename): self.__log("i", 'Closing file') msg, res = self.request('M29 ' + filename, 2000, 3) if res == QidiResult.SUCCES: if 'Error' in msg: self.__log("e", 'cmd:' + msg) return QidiResult.WRITE_ERROR else: return QidiResult.SUCCES return res def __send_file_block(self, buff, seek): check_sum = 0 buff += b"000000" dataArray = bytearray(buff) seekArray = struct.pack('>I', seek) datSize = len(dataArray) - 6 dataArray[datSize] = seekArray[3] dataArray[datSize + 1] = seekArray[2] dataArray[datSize + 2] = seekArray[1] dataArray[datSize + 3] = seekArray[0] for i in range(0, datSize + 4, 1): check_sum ^= dataArray[i] dataArray[datSize + 4] = check_sum dataArray[datSize + 5] = 131 datSize = len(dataArray) - 6 if datSize <= 0: raise Exception('error computing checksum!') return return self.request(dataArray, 2000, 3) def __send_file(self, fp): self.__log("i", 'begin sending file') lastProgress = seek = 0 while True: try: if self._abort: return QidiResult.ABORTED seek = fp.tell() data = fp.read(self.BUFSIZE) if int(100 * seek / self.__sendFileSize) > int(100 * lastProgress): lastProgress = seek / self.__sendFileSize progress = int(100 * lastProgress) self.progressChanged.emit(progress) sys.stdout.write('*') sys.stdout.flush() if not data: sys.stdout.write('\r\n') self.__log("d", 'reach file end') return QidiResult.SUCCES #self.__log("d","sending file block: {}", seek) msg, res = self.__send_file_block(data, seek) if res == QidiResult.SUCCES: if 'ok' in msg: continue else: self.__log("w", "got reply: " + msg) if 'resend' in msg: value = re.findall('resend \\d+', msg) if value: resend_offset = int(value[0].replace('resend ', '')) fp.seek(resend_offset, 0) else: self.__log("d", 'bad offset:' + msg) return QidiResult.WRITE_ERROR elif 'Error' in msg: return QidiResult.WRITE_ERROR else: return QidiResult.WRITE_ERROR else: self.__log("e", 'send file block timeout') continue except Exception as e: self.__log("w", str(e)) return QidiResult.WRITE_ERROR def sendfile(self, filename): with self._mutex: ret = self.__sendfile(filename) return ret def __sendfile(self, filename): self._abort = False self._filename = None if not self._connected: if not self.__connect(): return QidiResult.DISCONNECTED if os.path.exists(self._localTempGcode + '.tz'): os.remove(self._localTempGcode + '.tz') if self.__compress_gcode(): filename += '.gcode.tz' send_file_path = self._localTempGcode + '.tz' else: filename += '.gcode' send_file_path = self._localTempGcode self.__log("d", 'file path: ' + send_file_path) try: self.__sendFileSize = os.path.getsize(send_file_path) self.__log("d", 'file size: {}', self.__sendFileSize) if self.__sendFileSize == 0: self.__log("e", 'file empty') return QidiResult.FILE_EMPTY with open(send_file_path, 'rb', buffering=1) as fp: if not self.__send_start_write(filename): return QidiResult.WRITE_ERROR res = self.__send_file(fp) if res is not QidiResult.SUCCES: return res if not self.__send_end_write(filename): return QidiResult.WRITE_ERROR except Exception as e: self.__log("w", str(e)) return QidiResult.WRITE_ERROR self._filename = filename return QidiResult.SUCCES def print(self): msg, res = self.request('M6030 ":' + self._filename + '" I1', 2000, 3) if res == QidiResult.SUCCES and 'Error' in msg: return QidiResult.FAIL return res def update(self): result = self._mutex.acquire(blocking=True, timeout=0.5) if result: ret = self.__update() if ret == QidiResult.SUCCES: self._update_fail_cnt = 0 self.updateDone.emit() else: self._update_fail_cnt += 1 if self._update_fail_cnt > 2: self._connected = False self.conectionStateChanged.emit(self._connected) self._mutex.release() return ret else: self.__log("d", 'timeout: lock not available') return QidiResult.TIMEOUT def __update(self): msg, res = self.request("M4000", 100, 3) if res == QidiResult.SUCCES: prev_printing_time = self._printing_time msg = msg.rstrip() msgs = msg.split(' ') for item in msgs: _ = item.split(':') try: if len(_) == 2: id = _[0] value = _[1] if id == 'B': _ = value.split('/') if len(_) == 2: self._status["bed_nowtemp"] = _[0] self._status["bed_targettemp"] = _[1] elif id == 'E1': _ = value.split('/') if len(_) == 2: self._status["e1_nowtemp"] = _[0] self._status["e1_targettemp"] = _[1] elif id == 'E2': _ = value.split('/') if len(_) == 2: self._status["e2_nowtemp"] = _[0] self._status["e2_targettemp"] = _[1] elif id == 'D': _ = value.split('/') if len(_) == 3: self._print_now = int(_[0]) self._print_total = int(_[1]) self._isIdle = _[2] is '1' elif id == 'F': _ = value.split('/') if len(_) == 2: self._status["fan"] = _[0] elif id == 'X': self._status["x_pos"] = value elif id == 'Y': self._status["y_pos"] = value elif id == 'Z': self._status["z_pos"] = value elif id == 'T': self._printing_time = int(value) except: self.__log("e", "Could not parse M4000 reply: {}", msg) if self._isPrinting == False and self._printing_time > 0: self._last_times = [] self._isPrinting = True msg, res = self.request("M4006", 100, 3) if res == QidiResult.SUCCES: _ = msg.split("'") if len(_) > 2: self._printing_filename = _[1] elif self._printing_time == 0: self._isPrinting = False return res
class LogServer(QTcpServer): def __init__(self, main_window, on_connection, log, stop_signal): super().__init__() self.log = log.getChild('TCP') self.log.info('Initializing') self.main_window = main_window self.on_connection = on_connection self.stop_signal = stop_signal self.host, self.port = CONFIG.listen_address self.host = QHostAddress(self.host) self.benchmark = CONFIG['benchmark'] self.threads = {} # socketDescriptor -> LogConnection self.connections = 0 def start(self): self.log.info('Starting the server') if self.benchmark: self.log.debug('Starting a benchmark connection') tab_closed = asyncio.Event() new_conn = BenchmarkConnection(self, None, "benchmark", self.stop_signal, tab_closed, self.log) self.on_connection(new_conn, "benchmark", tab_closed) self.threads[None] = new_conn new_conn.start() result = self.listen(self.host, self.port) if not result: err_string = self.errorString() show_critical_dialog(self.main_window, 'Error while starting the server', err_string) else: address = "{}:{}".format(self.host.toString(), self.port) self.main_window.set_status( 'Server is listening on {}...'.format(address)) def incomingConnection(self, socketDescriptor): self.connections += 1 name = 'Logger {}'.format(self.connections) self.log.info('New connection: "{}"'.format(name)) tab_closed = asyncio.Event() new_conn = LogConnection(self, socketDescriptor, name, self.stop_signal, tab_closed, self.log) self.on_connection(new_conn, name, tab_closed) new_conn.finished.connect(new_conn.deleteLater) new_conn.connection_finished.connect(self.cleanup_connection) new_conn.start() self.threads[int(socketDescriptor)] = new_conn def close_server(self): self.log.debug('Closing the server') self.close() self.stop_all_connections() def stop_all_connections(self): self.log.debug('Waiting for connection threads to stop') for _, thread in self.threads.items(): thread.exit() for _, thread in self.threads.items(): if not thread.wait(1000): self.log.error( 'Thread "{}" didn\'t stop in time, terminating...'.format( thread)) thread.terminate() self.log.error('Thread "{}" terminated'.format(thread)) self.log.debug('All connections stopped') def cleanup_connection(self, socketDescriptor): try: del self.threads[socketDescriptor] except Exception as e: self.log.error('Bad socketDescriptor: {}'.format(socketDescriptor), exc_info=True)