- 
                Notifications
    
You must be signed in to change notification settings  - Fork 53
 
Description
Hi all,
I am having difficulties integrating asyncio with Pyside for the following use case.
I have read through numerous docs and articles but still struggle to assemble the pieces of the puzzle.
I figured I should ask here directly. Sorry in advance if is not the appropriate channel. I didn't see any Discussions channel.
What I want to acheive:
I have several emitters (up to 30) sending messages independently every few milliseconds (200ms) in multicast.
I have a python PySide app that needs to listen to these incoming messages, process them, and update a map plot accordingly (move shapes, change colors of markers, etc...).
Because I cannot share what I am working on for confidentialy purposes, I have devised a proxy example that is simpler and close enough to my actual need that I can share here.
In this proxy example:
I have an emitter script that sends messages indefinitely on two ports, at a rate that can be modified (here the sleep time is of 1s). This simulates my sensors that emit messages. In this script, messages are sent each time one after the other. To be close to reality I guess we ought to have two separate scripts run in two different consoles. But I think this one can do the trick here. The messages consist in random numbers in this example.
On the receiving side, I want to create an app with PySide that receives those messages, processes them (multiply the numbers by 100) and displays them in two text boxes, each associated with a different port.
enter image description here
I am looking at using an asynchronous approach with asyncio here because I think my problem is mainly I/O-bound. The processing stage is minimal. In my real example it would amount to updating shapes on a satellite view map (leaflet via javascript), maybe doing a few calculations on the received data before that, but nothing too CPU-intensive. I also chose to embed my plot in a PySide app to be able to add more buttons and features later on. Please feel free to indicate any other solution that would be more suitable (multiple threads? multiple processes?).
Anyway, I have tried the following qt doc minimal example but it does not work.
And now I am calling for your help.
Below are the emitter script as well as the code base for the PySide app, without the asynchronous listening and processing stages (I asked Le Chat to generate the full Pyside app but it never works that's why I am giving you only the base code to fill in here):
EMITTER.py
import socket
import time
import struct
import random
def send_multicast_messages(port1, port2, multicast_group='224.1.1.1'):
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    ttl = struct.pack('b', 1)
    sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, ttl)
    try:
        while True:
            # Generate a random value for port1
            value1 = random.randint(1, 100)
            message1 = f"{value1}"
            sock.sendto(message1.encode(), (multicast_group, port1))
            print(f"Sent to port {port1}: {message1}")
            # Generate a random value for port2
            value2 = random.randint(1, 100)
            message2 = f"{value2}"
            sock.sendto(message2.encode(), (multicast_group, port2))
            print(f"Sent to port {port2}: {message2}")
            time.sleep(1)
    except KeyboardInterrupt:
        print("\nExiting the program.")
    finally:
        sock.close()
if __name__ == "__main__":
    port1 = 5000
    port2 = 6000
    send_multicast_messages(port1, port2)
APP.py
import sys
from PySide6.QtWidgets import (
    QApplication, QMainWindow, QVBoxLayout, QTextEdit, QLabel, QWidget
)
class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Port Monitor")
        self.setGeometry(100, 100, 400, 300)
        # Create widgets
        self.label1 = QLabel("Port 5000:")
        self.text_edit1 = QTextEdit()
        self.text_edit1.setReadOnly(True)
        self.label2 = QLabel("Port 6000:")
        self.text_edit2 = QTextEdit()
        self.text_edit2.setReadOnly(True)
        # Layout
        layout = QVBoxLayout()
        layout.addWidget(self.label1)
        layout.addWidget(self.text_edit1)
        layout.addWidget(self.label2)
        layout.addWidget(self.text_edit2)
        # Central widget
        container = QWidget()
        container.setLayout(layout)
        self.setCentralWidget(container)
if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec())
Thank you very much in advance for your help.