Is it possible to keep a UDP server running as an asynchronous function receiving data and then passing it to an (PyQt5) widget which is also running as an asynchronous function??
The idea is that when the data coming into the server is updated, it also updates the widget.
I have got a simple UDP server and a (PyQt5) widget already which are working fine independently but I am struggling trying to combine them and keep them both running asynchronously and exchanging data(Server transmitting data to widget)
[UPDATE]
Below is a widget that I am trying out
import sys
from PyQt5 import QtWidgets, QtCore, QtGui
from PyQt5.QtWidgets import QApplication, QMainWindow
import asyncio
class Speedometer(QMainWindow):
angleChanged = QtCore.pyqtSignal(float)
def __init__(self, parent = None):
QtWidgets.QWidget.__init__(self, parent)
self._angle = 0.0
self._margins = 20
self._pointText = {0: "40", 30: "50", 60: "60", 90: "70", 120: "80",
150:"" , 180: "", 210: "",
240: "0", 270: "10", 300: "20", 330: "30", 360: ""}
def paintEvent(self, event):
painter = QtGui.QPainter()
painter.begin(self)
painter.setRenderHint(QtGui.QPainter.Antialiasing)
painter.fillRect(event.rect(), self.palette().brush(QtGui.QPalette.Window))
self.drawMarkings(painter)
self.drawNeedle(painter)
painter.end()
def drawMarkings(self, painter):
painter.save()
painter.translate(self.width()/2, self.height()/2)
scale = min((self.width() - self._margins)/120.0,
(self.height() - self._margins)/60.0)
painter.scale(scale, scale)
font = QtGui.QFont(self.font())
font.setPixelSize(10)
metrics = QtGui.QFontMetricsF(font)
painter.setFont(font)
painter.setPen(self.palette().color(QtGui.QPalette.Shadow))
i = 0
while i < 360:
if i % 30 == 0 and (i <150 or i > 210):
painter.drawLine(0, -40, 0, -50)
painter.drawText(-metrics.width(self._pointText[i])/2.0, -52,
self._pointText[i])
elif i <135 or i > 225:
painter.drawLine(0, -45, 0, -50)
painter.rotate(15)
i += 15
painter.restore()
def drawNeedle(self, painter):
painter.save()
painter.translate(self.width()/2, self.height()/1.5)
painter.rotate(self._angle)
scale = min((self.width() - self._margins)/120.0,
(self.height() - self._margins)/120.0)
painter.scale(scale, scale)
painter.setPen(QtCore.Qt.NoPen)
painter.setBrush(self.palette().brush(QtGui.QPalette.Shadow))
painter.drawPolygon(
QtGui.QPolygon([QtCore.QPoint(-10, 0), QtCore.QPoint(0, -45), QtCore.QPoint(10, 0),
QtCore.QPoint(0, 5), QtCore.QPoint(-10, 0)])
)
painter.setBrush(self.palette().brush(QtGui.QPalette.Highlight))
painter.drawPolygon(
QtGui.QPolygon([QtCore.QPoint(-5, -25), QtCore.QPoint(0, -45), QtCore.QPoint(5, -25),
QtCore.QPoint(0, -30), QtCore.QPoint(-5, -25)])
)
painter.restore()
def sizeHint(self):
return QtCore.QSize(150, 150)
def angle(self):
return self._angle
# @pyqtSlot(float)
def setAngle(self, angle):
if angle != self._angle:
self._angle = angle
self.angleChanged.emit(angle)
self.update()
angle = QtCore.pyqtProperty(float, angle, setAngle)
@staticmethod
def mainLoopSpd():
while True:
app = QApplication(sys.argv)
window = QtWidgets.QWidget()
spd = Speedometer()
spinBox = QtWidgets.QSpinBox()
#spd.setAngle(100)
spinBox.setRange(0, 359)
spinBox.valueChanged.connect(spd.setAngle)
layout = QtWidgets.QVBoxLayout()
layout.addWidget(spd)
layout.addWidget(spinBox)
window.setLayout(layout)
window.show()
app.exec_()
#await asyncio.sleep(1)
sys.exit(app.exec_())
Below is an implementation of a UDP socket end which also is printing the values in the console
import socket
class UDPserver:
def __init__(self, parent= None):
self.localIP = "127.0.0.1"
self.localPort = 20002
self.bufferSize = 1024
self.UDPServerSocket = socket.socket(family= socket.AF_INET, type=socket.SOCK_DGRAM) # Create a socket object
self.UDPServerSocket.bind((self.localIP, self.localPort))
print("UDP server up and listening")
self.counter= 1
@staticmethod
def mainLoopUDPserver():
serv= UDPserver()
#while(True):
bytesAddressPair = serv.UDPServerSocket.recvfrom(serv.bufferSize) # Receive data from the socket
message = bytesAddressPair[0] # The output of the recvfrom() function is a 2-element array
# First element is the message
address = bytesAddressPair[1] # Second element is the address of the sender
newMsg= "{}".format(message)
serv.counter=serv.counter+1
NumMssgReceived = "#Num of Mssg Received:{}".format(serv.counter)
newMsg= newMsg.replace("'","")
newMsg= newMsg.replace("b","")
newMsg= newMsg.split("/")
eastCoord= float(newMsg[0])
northCoord= float(newMsg[1])
vehSpeed= float(newMsg[2])
agYaw= float(newMsg[3])
eastCoordStr="East Coordinate:{}".format(newMsg[0])
northCoordStr="North Coordinate:{}".format(newMsg[1])
vehSpeedStr= "Vehicle Speed:{}".format(newMsg[2])
agYawStr="Yaw Angle:{}".format(newMsg[3])
print(NumMssgReceived)
print(vehSpeedStr)
and below is the main function which is calling them both
from speedometer import Speedometer
import asyncio
from pyServer import UDPserver
class mainApp:
#vel = 0
def __init__(self):
self.velo = 0
self.queue= asyncio.Queue(0)
async def server(self):
while True:
self.velo= UDPserver.mainLoopUDPserver()
print("THIS IS VELO{}",self.velo)
#await self.queue.put(self.velo)
#vel= await self.queue.get()
#return vel
#print("ASSDASDSADSD{}",vel)
await asyncio.sleep(0)
#print("HI, vel Received={}",self.veloc)
#return velo
async def widget(self):
while True:
#vel = await self.queue.get()
#print("Hola xDDDDDDD", vel)
print(">>>>>>>>>>>>>>>NextIteration>>>>>>>>>>>>>>")
await Speedometer.mainLoopSpd()
await asyncio.sleep(0)
loop= asyncio.get_event_loop()
mApp= mainApp()
loop.create_task(mApp.server())
loop.create_task(mApp.widget())
loop.run_forever()
So, when I run it, it listens to the server and once I start sending data over UDP, it receives the first piece of data and open the widget which is runs just fine but it makes the server to stop, it does not receive any data anymore.
As you can see in the comments, I have also been playing around with Asyncio queues, but I haven't got anything really.
My ideal scenario would be the server receiving the data and passing it to the widget so it gets updated with the incoming data but for now I just want them both working independently.
Thanks