I want to create a SocketIO server in Python on Windows as a simulator for a SocketIO client I'm writing. The server uses eventlet
to listen to local port 0.0.0.0. The simulator uses PyQt5 and has two buttons. One button emits one message from the server and the other button emits a different message from the server.
Upon execution, the client connects to the server without issue but the QDialog hangs and the QPushButtons are not displayed.
If I comment out the line that begins with eventlet =
then the QDialog displays without issue but [obviously] the client cannot connect to the server.
Any suggestions how I can overcome this issue so that I can connect from the client and also emit server messages by clicking the QPushButtons? Here is my server script:
from PyQt5.QtWidgets import QPushButton, QDialog, QApplication
import socketio, sys, eventlet
class My_Server(QDialog):
def __init__(self, parent=None):
super(My_Server, self).__init__(parent)
self.setWindowTitle("My SocketIO Server")
self.resize(300,150)
self.move(300, 200)
self.btn1 = QPushButton(self)
self.btn1.setText('Msg 1')
self.btn1.move(50,75)
self.btn1.clicked.connect(self.send_btn1)
self.btn2 = QPushButton(self)
self.btn2.setText('Msg 2')
self.btn2.move(175,75)
self.btn2.clicked.connect(self.send_btn2)
self.show()
self.sio = socketio.Server()
self.serverapp = socketio.WSGIApp(self.sio, static_files={'/': {'content_type': 'text/html', 'filename': 'index.html'}})
eventlet.wsgi.server(eventlet.listen(('', 5000)), self.serverapp)
def send_btn1(self):
self.sio.emit('message1', {"Message 1": "Hello"})
def send_btn2(self):
self.sio.emit('message2', {"Message 2": "World"})
if __name__ == '__main__':
app = QApplication(sys.argv)
form = My_Server()
form.show()
sys.exit(app.exec_())
Use eventlet-pyqt to spawn greenlets which hold server and other networking operations.
import socketio, sys, eventlet
from hgoldfish.utils import eventlet as eventlet_pyqt
class My_Server(QDialog):
def __init__(self, parent=None):
# anything you do previously
self.operations = eventlet_pyqt.GreenletGroup()
self.operations.spawn(self.serve)
def serve(self):
self.sio = socketio.Server()
self.serverapp = socketio.WSGIApp(self.sio, static_files={'/': {'content_type': 'text/html', 'filename': 'index.html'}})
eventlet.wsgi.server(eventlet.listen(('', 5000)), self.serverapp)
if __name__ == '__main__':
app = QApplication(sys.argv)
form = My_Server()
form.show()
sys.exit(eventlet.start_application(quitOnLastWindowClosed = True))
my solution for socketio on pyqt5 threading.I couldn't convert socketio server to the class but it is working like that anyway..
i have 2 pyqt5 gui both for for server and client device and both gui he socketio threads to communicate each other both pyqt files depending on.ui files which is not included here fell free to remove them
SocketServer.py
import eventlet
import socketio
sio = socketio.Server()
app = socketio.WSGIApp(sio)
def get_device_id(environ):
return environ.get('HTTP_DEVICE_ID', None)
@sio.event
def connect(sid, environ):
device_id = get_device_id(environ) or sid
sio.save_session(sid, {'device_id': device_id})
print('{} is connected'.format(device_id))
# this function run on demand
@sio.on('send')
def send(sid, data):
session = sio.get_session(sid)
print('Received data from {}: {}'.format(session['device_id'], data))
sio.emit('receive', {'page': 'main', 'camera': True, 'capture': False,
'scan': False, 'cpu': 35, 'battery_1': 7.32, 'battery_2': 3.5})
# this function running real time
@sio.on('talk')
def talk(sid):
session = sio.get_session(sid)
# print('Received -> Sent to {}'.format(session['device_id']))
sio.emit('listen', {'page': 0, 'cpu_temp': 35, 'battery_1': 7.32, 'battery_2': 3.5, 'camera': True, 'capture': False,
'scan': False,'think':True,'talk':False,'speak':False})
@sio.event
def disconnect(sid):
print('disconnect ', sid)
def run():
print("Server Started")
eventlet.wsgi.server(eventlet.listen(
('192.168.2.19', 5000)), app, log_output=False)
#use when you need to run standalone
# if __name__ == '__main__':
# print("Server Started")
# eventlet.wsgi.server(eventlet.listen(
# ('192.168.2.19', 5000)), app, log_output=False)
PyQt5.py file
import SocketServer as Server
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
class ServerThread(QThread):
server = Server
def __init__(self, parent=None):
super().__init__(parent)
def run(self):
self.server.run()
class MainWindow(QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.resize(640, 480)
self.centralwidget = QWidget(self)
self.setCentralWidget(self.centralwidget)
VBL = QVBoxLayout(self.centralwidget)
VBL.setContentsMargins(0, 0, 0, 0)
VBL.addWidget(self.topbar)
self.screens = QStackedLayout()
VBL.addLayout(self.screens)
self.worker = ServerThread()
self.worker.start()
if __name__ == "__main__":
App = QApplication(sys.argv)
App.setStyle('Breeze')
Root = MainWindow()
Root.show()
sys.exit(App.exec())
Client.py file
import sys
from xmlrpc.client import boolean
from PyQt5.QtWidgets import QMainWindow, QFileDialog, QTableWidgetItem, QMessageBox, QApplication
from PyQt5.QtCore import QThread, QTimer, pyqtSlot
from PyQt5.QtGui import QPixmap
from PyQt5 import QtCore
from PyQt5 import uic
import socketio
import time
ui_form = uic.loadUiType("UI_client.ui")[0]
class SocketClient(QThread):
add_log = QtCore.pyqtSignal(object)
dataUpdate = QtCore.pyqtSignal(object)
connStatus = QtCore.pyqtSignal(bool)
sio = socketio.Client()
def __init__(self, parent=None):
super().__init__()
self.main = parent
self.ip = '192.168.2.19'
self.port = 5000
self.host = 'http://%s:%s' % (self.ip, self.port)
def set_host(self, ip, port):
self.ip = ip
self.port = port
def run(self):
self.connect(self.host)
def connect(self, host):
SocketClient.sio.on('receive', self.receive)
SocketClient.sio.on('listen', self.listen)
try:
SocketClient.sio.connect(host)
self.connStatus.emit(True)
self.add_log.emit('Connection to the server has been completed.')
except socketio.exceptions.ConnectionError as err:
self.add_log.emit('Server not found! Try again...')
self.connStatus.emit(False)
else:
pass
# real time
def talk(self):
if not SocketClient.sio.connected:
self.connect(self.host)
try:
SocketClient.sio.emit('talk')
except:
self.connStatus.emit(False)
# real time
def listen(self, msg):
if msg:
self.connStatus.emit(True)
# this data will process
self.dataUpdate.emit(msg)
else:
self.connStatus.emit(False)
# on demand
def send(self, msg):
try:
SocketClient.sio.emit('send', msg)
self.add_log.emit('[Me]:%s' % (msg))
except:
self.add_log.emit('[Server] %s' %
("Cant send message to server"))
# on demand
def receive(self, msg):
if msg:
self.add_log.emit('[Server] %s' % (msg))
else:
self.add_log.emit('[Server] %s' %
("server message is empty !"))
class ChatWindow(QMainWindow, ui_form):
def __init__(self):
super().__init__()
self.setupUi(self)
# fill inputs for test
self.INPUT_ip.setPlainText("192.168.2.19")
self.INPUT_port.setPlainText("5000")
self.BTN_send.setDisabled(True)
self.BTN_disconnect.hide()
self.BTN_send.clicked.connect(self.send_message)
self.BTN_connect.clicked.connect(self.socket_connection)
self.BTN_disconnect.clicked.connect(self.socket_quit)
self.connStatus = False
self.flipImage = 0
self.sc = SocketClient(self)
self.timer = QTimer()
self.timer.timeout.connect(self.realtime_comminication)
self.sc.add_log.connect(self.add_chat)
self.sc.dataUpdate.connect(self.read_values)
self.sc.connStatus.connect(self.enable_send_button)
def enable_send_button(self, status):
self.connStatus = status
if status:
self.BTN_disconnect.show()
else:
self.BTN_disconnect.hide()
self.BTN_send.setEnabled(status)
self.CONNECTION_BAR.setEnabled(not status)
self.LED_connect.setPixmap(
QPixmap('icons/led-green-on.png' if status else 'icons/led-red-on.png'))
self.LED_rx_tx.setPixmap(QPixmap(
'icons/rx-tx-on.png' if (self.flipImage % 2) == 0 else 'icons/rx-tx.png'))
self.flipImage += 1
def read_values(self, data):
for key, value in data.items():
# set LED status
led = "LED_"+key
if hasattr(self, led):
led = getattr(self, led)
if value:
led.setPixmap(QPixmap('icons/led-green-on.png'))
else:
led.setPixmap(QPixmap('icons/led-red-on.png'))
# set Button Status
button = "BTN_"+key
if hasattr(self, button):
getattr(self, button).setChecked(value)
reading = "VALUE_"+key
if hasattr(self, reading):
getattr(self, reading).display(value)
if key == "page":
switcher = ["BTN_main",
"BTN_clock",
"BTN_weather"]
for index, name in enumerate(switcher):
led = getattr(self, "LED_page_"+str(index))
if index == value:
getattr(self, switcher[index]).setChecked(True)
led.setPixmap(QPixmap('icons/led-green-on.png'))
else:
getattr(self, switcher[index]).setChecked(False)
led.setPixmap(QPixmap('icons/led-red-on.png'))
# setattr(self, value, True if value else False)
def socket_connection(self):
ip = self.INPUT_ip.toPlainText()
port = self.INPUT_port.toPlainText()
if (not ip) or (not port):
self.add_chat('The ip or port number is empty.')
return
self.sc.set_host(ip, port)
if not self.connStatus:
self.sc.start()
self.timer.start(500)
def socket_quit(self):
sys.exit()
def realtime_comminication(self):
self.sc.talk()
def send_message(self):
if not self.connStatus:
self.add_chat('Connection Lost!...')
return
msg = self.INPUT_message.toPlainText()
self.sc.send(msg)
self.INPUT_message.setPlainText('')
@pyqtSlot(object)
def add_chat(self, msg):
self.chats.appendPlainText(msg)
if __name__ == "__main__":
app = QApplication(sys.argv)
myWindow = ChatWindow()
myWindow.setWindowTitle('Remote Command')
myWindow.show()
app.exec_()
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.