40 from PySide2.QtCore
import QThread, QByteArray, QDataStream, QIODevice
41 from PySide2.QtNetwork
import QTcpServer, QTcpSocket, QAbstractSocket, \
50 SERVER_ERROR_INVALID_ADDRESS = 1
54 SERVER_ERROR_PORT_OCCUPIED = 2
61 COMMAND_EXECUTED_CONFIRMATION_MESSAGE =
"Command executed successfully" 65 CLIENT_COMMAND_EXECUTED = 0
69 CLIENT_COMMAND_FAILED = 1
73 CLIENT_ERROR_RESPONSE_NOT_COMPLETE = 2
77 CLIENT_ERROR_NO_RESPONSE = 3
81 CLIENT_ERROR_BLOCK_NOT_WRITTEN = 4
85 CLIENT_ERROR_NO_CONNECTION = 5
116 super(CommandThread, self).
__init__(parent)
134 tcpSocket = QTcpSocket()
136 FreeCAD.Console.PrintError(
"Socket not accepted.\n")
138 FreeCAD.Console.PrintLog(
"Socket accepted.\n")
141 if not tcpSocket.waitForReadyRead(msecs=WAIT_TIME_MS):
142 FreeCAD.Console.PrintError(
"No request send.\n")
146 instr = QDataStream(tcpSocket)
147 instr.setVersion(QDataStream.Qt_4_0)
151 if tcpSocket.bytesAvailable() < 2:
152 FreeCAD.Console.PrintError(
"Received message " 153 +
"has too few bytes.\n")
158 if tcpSocket.bytesAvailable() < self.
blockSize:
159 FreeCAD.Console.PrintError(
"Received message has less bytes " 160 +
"then it's supposed to.\n")
164 cmd = instr.readRawData(self.
blockSize).decode(
"UTF-8")
165 FreeCAD.Console.PrintLog(
"CommandServer received> " 171 except Exception
as e:
172 FreeCAD.Console.PrintError(
"Executing external command failed:" 174 message =
"Command failed - " + str(e)
176 FreeCAD.Console.PrintLog(
"Executing external command succeeded!\n")
177 message = COMMAND_EXECUTED_CONFIRMATION_MESSAGE
180 FreeCAD.Console.PrintLog(
"CommandServer sending> " + message +
" \n")
182 len(message.encode(
"UTF-8")).to_bytes(2, byteorder=
'big')
183 + message.encode(
"UTF-8"))
184 outstr = QDataStream(block, QIODevice.WriteOnly)
185 outstr.setVersion(QDataStream.Qt_4_0)
188 tcpSocket.write(block)
189 tcpSocket.disconnectFromHost()
190 tcpSocket.waitForDisconnected()
209 super(CommandServer, self).
__init__(parent)
224 thread.finished.connect(thread.deleteLater)
231 super(CommandServer, self).
close()
232 FreeCAD.Console.PrintLog(
"Server closed.\n")
245 if ip.upper() ==
"LOCALHOST":
248 numbers = ip.split(
".")
249 if len(numbers) == 4:
250 if all([(0 <= int(num) <= 255)
for num
in numbers]):
276 return SERVER_ERROR_INVALID_ADDRESS
278 if addr.upper() ==
"LOCALHOST":
279 addr = QHostAddress(QHostAddress.LocalHost)
281 addr = QHostAddress(addr)
284 if not server.listen(addr, port):
285 FreeCAD.Console.PrintLog(
"Unable to start the server: %s.\n" 286 % server.errorString())
287 return SERVER_ERROR_PORT_OCCUPIED
290 FreeCAD.Console.PrintLog(
"The server is running on address %s" 291 % server.serverAddress().toString()
292 +
" and port %d.\n" % server.serverPort())
368 if not self.
tcpSocket.waitForConnected(msecs=WAIT_TIME_MS):
369 if "FreeCAD" in sys.modules:
370 FreeCAD.Console.PrintError(
"CommandClient.sendCommand error: " 373 print(
"CommandClient.sendCommand error: No connection\n")
374 return CLIENT_ERROR_NO_CONNECTION
378 len(cmd.encode(
"UTF-8")).to_bytes(2, byteorder=
'big')
379 + cmd.encode(
"UTF-8"))
380 outstr = QDataStream(block, QIODevice.WriteOnly)
381 outstr.setVersion(QDataStream.Qt_4_0)
384 if "FreeCAD" in sys.modules:
385 FreeCAD.Console.PrintMessage(
"CommandClient sending> " 388 print(
"CommandClient sending> " + cmd +
"\n")
390 if not self.
tcpSocket.waitForBytesWritten(msecs=WAIT_TIME_MS):
391 if "FreeCAD" in sys.modules:
392 FreeCAD.Console.PrintError(
"CommandClient.sendCommand error: " 393 +
"Block not written\n")
395 print(
"CommandClient.sendCommand error: Block not written\n")
396 return CLIENT_ERROR_BLOCK_NOT_WRITTEN
399 if not self.
tcpSocket.waitForReadyRead(msecs=WAIT_TIME_MS):
400 if "FreeCAD" in sys.modules:
401 FreeCAD.Console.PrintError(
"CommandClient.sendCommand error: " 402 +
"No response received.\n")
404 print(
"CommandClient.sendCommand error: " 405 +
"No response received.\n")
406 return CLIENT_ERROR_NO_RESPONSE
410 instr.setVersion(QDataStream.Qt_4_0)
413 return CLIENT_ERROR_RESPONSE_NOT_COMPLETE
417 return CLIENT_ERROR_RESPONSE_NOT_COMPLETE
418 response = instr.readRawData(self.
blockSize).decode(
"UTF-8")
419 if "FreeCAD" in sys.modules:
420 FreeCAD.Console.PrintMessage(
"CommandClient received> " 423 print(
"CommandClient received> " + response +
"\n")
431 if response == COMMAND_EXECUTED_CONFIRMATION_MESSAGE:
432 return CLIENT_COMMAND_EXECUTED
434 return CLIENT_COMMAND_FAILED
447 if socketError != QAbstractSocket.RemoteHostClosedError:
448 if "FreeCAD" in sys.modules:
449 FreeCAD.Console.PrintError(
"CommandClient error occurred> %s." 453 print(
"CommandClient error occurred> %s." 485 tcpSocket = QTcpSocket()
486 tcpSocket.connectToHost(host, port, QIODevice.ReadWrite)
487 if not tcpSocket.waitForConnected(msecs=wait_time):
488 return CLIENT_ERROR_NO_CONNECTION
492 len(cmd.encode(
"UTF-8")).to_bytes(2, byteorder=
'big')
493 + cmd.encode(
"UTF-8"))
494 outstr = QDataStream(block, QIODevice.WriteOnly)
495 outstr.setVersion(QDataStream.Qt_4_0)
496 tcpSocket.write(block)
499 if not tcpSocket.waitForBytesWritten(msecs=wait_time):
500 return CLIENT_ERROR_BLOCK_NOT_WRITTEN
503 if not tcpSocket.waitForReadyRead(msecs=wait_time):
504 return CLIENT_ERROR_NO_RESPONSE
507 instr = QDataStream(tcpSocket)
508 instr.setVersion(QDataStream.Qt_4_0)
511 if tcpSocket.bytesAvailable() < 2:
512 return CLIENT_ERROR_RESPONSE_NOT_COMPLETE
513 blockSize = instr.readUInt16()
514 if tcpSocket.bytesAvailable() < blockSize:
515 return CLIENT_ERROR_RESPONSE_NOT_COMPLETE
518 tcpSocket.waitForDisconnected()
521 if instr.readRawData(blockSize).decode(
"UTF-8") \
522 == COMMAND_EXECUTED_CONFIRMATION_MESSAGE:
523 return CLIENT_COMMAND_EXECUTED
525 return CLIENT_COMMAND_FAILED
def sendClientCommand(host, port, cmd, wait_time=WAIT_TIME_MS)
Method to be used for sending commands.
QTcpServer class used to receive commands and execute them.
host
A QtHostAddress to the CommandServer.
def startServer(addr, port)
Method used to try to start a CommandServer at a valid IP address and port.
def __init__(self, host, port)
Initialization method for CommandClient.
def run(self)
Thread's functionality method.
def displayError(self, socketError)
Qt's slot method to print out received tcpSocket's error.
Class to be used for sending commands.
port
An int of port at which CommandServer is listening.
blockSize
An int representing size of incoming tcp message.
def close(self)
Method used to close the CommandServer and inform user about it.
def __init__(self, socketDescriptor, parent)
Initialization method for CommandThread.
blockSize
An int representing size of incoming tcp message.
def __init__(self, parent=None)
Initialization method for CommandServer.
QThread class used to receive commands, try to execute and respond to them.
def checkIPIsValid(ip)
Method used to check a selected IP is possible to use with a Qt's QHostAddress.
tcpSocket
A QTcpSocket used to contact CommandSErver
socketDescriptor
A Qt's qintptr socket descriptor to initialize tcpSocket.
def incomingConnection(self, socketDescriptor)
Method to handle an incoming connection by dispatching a CommandThread.
def sendCommand(self, cmd)
Method used to send commands from client to CommandServer.