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() block = QByteArray() outstr = QDataStream(block, QIODevice.WriteOnly) outstr.setVersion(QDataStream.Qt_4_0) while socket.bytesAvailable() < blockSize: if not socket.waitForReadyRead(Timeout): self.error.emit(socket.error(), socket.errorString()) return self.mutex.lock() outstr.writeUInt16(0) outstr.writeQString("Message to Server") outstr.device().seek(0) outstr.writeUInt16(block.size() - 2) socket.write(block) # socket.write(block) 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 CommandClient: ## @property host # A QtHostAddress to the `CommandServer`. ## @property port # An int of port at which `CommandServer` is listening. ## @property tcpSocket # A QTcpSocket used to contact `CommandSErver` ## @property blockSize # An int representing size of incomming tcp message. ## @brief Initialization method for CommandClient. # #A class instance is created and its attributes are initialized. # # # @param host A QtHostAddress to the `CommandServer`. # @param port An int of port at which `CommandServer` is listening. # def __init__(self, host, port): self.host = host self.port = port self.tcpSocket = QTcpSocket() self.blockSize = 0 ## @brief Method used to send commands from client to `CommandServer`. # #This method tries to connect to a specified host `CommandServer` via #`tcpSocket`. If connection was successfull, the command `cmd` is sent. #Then the response is expected. If the response is equal to #COMMAND_EXECUTED_CONFIRMATION_MESSAGE, then the execution was successfull. #The progress and result of `sendCommand` can be obtained from printed logs and #return value. # # # @param cmd A str command to be executed. # # @return # `CLIENT_COMMAND_EXECUTED` if all went great and command was executed. # `CLIENT_COMMAND_FAILED` if `cmd` execution failed. # `CLIENT_ERROR_RESPONSE_NOT_COMPLETE` if a response received was incomplete. # `CLIENT_ERROR_NO_RESPONSE` if there was no response within `WAIT_TIME_MS`. # `CLIENT_ERROR_BLOCK_NOT_WRITTEN` if communication failed during sending. # `CLIENT_ERROR_NO_CONNECTION` if no connection to a host was established. # def sendCommand(self, cmd): # connect a Qt slot to receive and print errors self.tcpSocket.error.connect(self.displayError) # Try to connect to a host server self.tcpSocket.connectToHost(self.host, self.port, QIODevice.ReadWrite) if not self.tcpSocket.waitForConnected(msecs=WAIT_TIME_MS): if "FreeCAD" in sys.modules: FreeCAD.Console.PrintError( "CommandClient.sendCommand error: " + "No connection\n") else: print("CommandClient.sendCommand error: No connection\n") return CLIENT_ERROR_NO_CONNECTION # Prepare a command message to be sent block = QByteArray() outstr = QDataStream(block, QIODevice.WriteOnly) outstr.setVersion(QDataStream.Qt_4_0) outstr.writeUInt16(0) outstr.writeQString(cmd) outstr.device().seek(0) outstr.writeUInt16(block.size() - 2) # Try to send the message if "FreeCAD" in sys.modules: FreeCAD.Console.PrintMessage("CommandClient sending> " + cmd + "\n") else: print("CommandClient sending> " + cmd + "\n") self.tcpSocket.write(block) if not self.tcpSocket.waitForBytesWritten(msecs=WAIT_TIME_MS): if "FreeCAD" in sys.modules: FreeCAD.Console.PrintError( "CommandClient.sendCommand error: " + "Block not written\n") else: print("CommandClient.sendCommand error: Block not written\n") return CLIENT_ERROR_BLOCK_NOT_WRITTEN # Wait for a response from the host server if not self.tcpSocket.waitForReadyRead(msecs=WAIT_TIME_MS): if "FreeCAD" in sys.modules: FreeCAD.Console.PrintError( "CommandClient.sendCommand error: " + "No response received.\n") else: print("CommandClient.sendCommand error: " + "No response received.\n") return CLIENT_ERROR_NO_RESPONSE # Try to read the response instr = QDataStream(self.tcpSocket) instr.setVersion(QDataStream.Qt_4_0) if self.blockSize == 0: if self.tcpSocket.bytesAvailable() < 2: return CLIENT_ERROR_RESPONSE_NOT_COMPLETE self.blockSize = instr.readUInt16() if self.tcpSocket.bytesAvailable() < self.blockSize: return CLIENT_ERROR_RESPONSE_NOT_COMPLETE response = instr.readString() if "FreeCAD" in sys.modules: FreeCAD.Console.PrintMessage("CommandClient received> " + response + "\n") else: print("CommandClient received> " + response + "\n") # Wait until the host server terminates the connection self.tcpSocket.waitForDisconnected() # Reset blockSize to prepare for sending next command self.blockSize = 0 # Return value representing a command execution status if response == COMMAND_EXECUTED_CONFIRMATION_MESSAGE: return CLIENT_COMMAND_EXECUTED else: return CLIENT_COMMAND_FAILED ## @brief `Qt`'s slot method to print out received `tcpSocket`'s error. # #QAbstractSocket.RemoteHostClosedError is not printed, because it occurs #naturaly when the `tcpSocket` closes after a transaction is over. Except that #all errors are printed. # # # @param socketError A QAbstractSocket::SocketError enum describing occured error. # def displayError(self, socketError): if socketError != QAbstractSocket.RemoteHostClosedError: if "FreeCAD" in sys.modules: FreeCAD.Console.PrintError( "CommandClient error occurred> %s." % self.tcpSocket.errorString() + "\n") else: print("CommandClient error occurred> %s." % self.tcpSocket.errorString() + "\n")
class CommandClient: """ Class to be used for sending commands. This class can be used in FreeCAD's or regular python console to send commands to a `CommandServer` using `sendCommand()`. The class prints logs as it moves along. Attributes: host: A QtHostAddress to the `CommandServer`. port: An int of port at which `CommandServer` is listening. tcpSocket: A QTcpSocket used to contact `CommandSErver` blockSize: An int representing size of incoming tcp message. To send a commands do: client = CommandClient("127.0.0.1",54321) client.sendCommand('FreeCAD.Console.PrintError("Hello World\\n")\n') client.sendCommand('FreeCAD.Console.PrintError("Bye Bye\\n")\n') """ def __init__(self, host, port): """ Initialization method for CommandClient. A class instance is created and its attributes are initialized. Args: host: A QtHostAddress to the `CommandServer`. port: An int of port at which `CommandServer` is listening. """ self.host = host self.port = port self.tcpSocket = QTcpSocket() self.blockSize = 0 def sendCommand(self, cmd): """ Method used to send commands from client to `CommandServer`. This method tries to connect to a specified host `CommandServer` via `tcpSocket`. If connection was successful, the command `cmd` is sent. Then the response is expected. If the response is equal to COMMAND_EXECUTED_CONFIRMATION_MESSAGE, then the execution was successful. The progress and result of `sendCommand` can be obtained from printed logs and return value. Args: cmd: A str command to be executed. Returns: `CLIENT_COMMAND_EXECUTED` if all went great and command was executed. `CLIENT_COMMAND_FAILED` if `cmd` execution failed. `CLIENT_ERROR_RESPONSE_NOT_COMPLETE` if a response received was incomplete. `CLIENT_ERROR_NO_RESPONSE` if there was no response within `WAIT_TIME_MS`. `CLIENT_ERROR_BLOCK_NOT_WRITTEN` if communication failed during sending. `CLIENT_ERROR_NO_CONNECTION` if no connection to a host was established. """ # connect a Qt slot to receive and print errors self.tcpSocket.error.connect(self.displayError) # Try to connect to a host server self.tcpSocket.connectToHost(self.host, self.port, QIODevice.ReadWrite) if not self.tcpSocket.waitForConnected(msecs=WAIT_TIME_MS): if "FreeCAD" in sys.modules: FreeCAD.Console.PrintError( "CommandClient.sendCommand error: " + "No connection\n") else: print("CommandClient.sendCommand error: No connection\n") return CLIENT_ERROR_NO_CONNECTION # Prepare a command message to be sent block = QByteArray( len(cmd.encode("UTF-8")).to_bytes(2, byteorder='big') + cmd.encode("UTF-8")) outstr = QDataStream(block, QIODevice.WriteOnly) outstr.setVersion(QDataStream.Qt_4_0) # Try to send the message if "FreeCAD" in sys.modules: FreeCAD.Console.PrintMessage("CommandClient sending> " + cmd + "\n") else: print("CommandClient sending> " + cmd + "\n") self.tcpSocket.write(block) if not self.tcpSocket.waitForBytesWritten(msecs=WAIT_TIME_MS): if "FreeCAD" in sys.modules: FreeCAD.Console.PrintError( "CommandClient.sendCommand error: " + "Block not written\n") else: print("CommandClient.sendCommand error: Block not written\n") return CLIENT_ERROR_BLOCK_NOT_WRITTEN # Wait for a response from the host server if not self.tcpSocket.waitForReadyRead(msecs=WAIT_TIME_MS): if "FreeCAD" in sys.modules: FreeCAD.Console.PrintError( "CommandClient.sendCommand error: " + "No response received.\n") else: print("CommandClient.sendCommand error: " + "No response received.\n") return CLIENT_ERROR_NO_RESPONSE # Try to read the response instr = QDataStream(self.tcpSocket) instr.setVersion(QDataStream.Qt_4_0) if self.blockSize == 0: if self.tcpSocket.bytesAvailable() < 2: return CLIENT_ERROR_RESPONSE_NOT_COMPLETE self.blockSize = instr.readUInt16() if self.tcpSocket.bytesAvailable() < self.blockSize: return CLIENT_ERROR_RESPONSE_NOT_COMPLETE response = instr.readRawData(self.blockSize).decode("UTF-8") if "FreeCAD" in sys.modules: FreeCAD.Console.PrintMessage("CommandClient received> " + response + "\n") else: print("CommandClient received> " + response + "\n") # Wait until the host server terminates the connection self.tcpSocket.waitForDisconnected() # Reset blockSize to prepare for sending next command self.blockSize = 0 # Return value representing a command execution status if response == COMMAND_EXECUTED_CONFIRMATION_MESSAGE: return CLIENT_COMMAND_EXECUTED else: return CLIENT_COMMAND_FAILED def displayError(self, socketError): """ `Qt`'s slot method to print out received `tcpSocket`'s error. QAbstractSocket.RemoteHostClosedError is not printed, because it occurs naturally when the `tcpSocket` closes after a transaction is over. Except that all errors are printed. Args: socketError: A QAbstractSocket::SocketError enum describing occurred error. """ if socketError != QAbstractSocket.RemoteHostClosedError: if "FreeCAD" in sys.modules: FreeCAD.Console.PrintError( "CommandClient error occurred> %s." % self.tcpSocket.errorString() + "\n") else: print("CommandClient error occurred> %s." % self.tcpSocket.errorString() + "\n")