kar kar - 1 year ago 71
Python Question

multiple python UDP socket & UI

I am very new to python and still in reading phase. I have two question here to discuss. I need to develop an python base user interface using

which should run on Raspberry Pi2. On the background process I need to create multiple UDP socket server & clients which is also python based.

I need to send data to a c++ application when the user press any button and select any value from combo box. Similarly I need to update the UI with the messages received from the C++ application.

I have create the basic UI and UDP socket in python which works as expected. Now I need to extend it so that I could send UI data to UDP Socket script and from there to C++ application.

  1. How to instantiate multiple UDP socket? is there something similar to FD_SET, select() in python?

  2. how to start both UI and background UDP socket script from a main.py script?

  3. How to specify c# region like implementation like canvas as region one, combobox as region two, buttons as region three and label(labelframe) as region four and position then with different size.

This is my python code:

from tkinter import *
from tkinter import ttk

class MainWindow(Frame):
def __init__(self):
self.master.minsize(330, 400)

modeFrame = Frame(self)
actionFrame = Frame(self)
msgframe = Frame(self)
modeFrame.pack(side="top", fill="x")
actionFrame.pack(side="top", fill="x")
msgframe.pack(side="top", fill="x")

# Mode Frame
Label(modeFrame, text="Mode :", font="bold").pack(side="left")

modeFrame.canvas1 = Canvas(modeFrame, height=25, width=25)
modeFrame.setupled = modeFrame.canvas1.create_oval(5, 5, 20, 20, fill="green")
Label(modeFrame, text="Setup Mode").pack(side="left")

modeFrame.canvas2 = Canvas(modeFrame, height=25, width=25)
modeFrame.setupled = modeFrame.canvas2.create_oval(5, 5, 20, 20, fill="black")
Label(modeFrame, text="Run Mode").pack(side="left")

# Action Frame
Label(self, text="Select Coupon").pack(side="left")
self.value_of_combo = 'X'
Button(self, text="Accept", command=acceptCallback).pack(side="left")
Button(self, text="Reject", command=rejectCallback).pack(side="left")
Button(self, text="EndSession", command=endSessionCallback).pack(fill="both", expand="yes", side="bottom")

# Message Frame
self.label0frame = LabelFrame(msgframe, text="ID")
self.label0frame.pack(fill="both", expand="yes")
Label(self.label0frame, text="Waiting for Client ...").pack(side="left")

self.label1frame = LabelFrame(msgframe, text="Available Coupons")
self.label1frame.pack(fill="both", expand="yes")
Label(self.label1frame, text="Waiting for Client ...").pack(side="left")

self.label2frame = LabelFrame(msgframe, text="Scanned Code")
self.label2frame.pack(fill="both", expand="yes")
Label(self.label2frame, text="Scanned Code ...").pack(side="left")

self.label3frame = LabelFrame(msgframe, text="Status")
self.label3frame.pack(fill="both", expand="yes")
Label(self.label3frame, text="Status Message ...").pack(side="left")

def newselection(self, event):
self.value_of_combo = self.comboBox.get()

def combo(self,Values):
self.box_value = StringVar()
self.comboBox = ttk.Combobox(self, state="readonly", values=("a", "b", "c"))
self.comboBox.bind("<<ComboboxSelected>>", self.newselection)

def acceptCallback():
print("send Accept Message to C++")

def rejectCallback():
print("send Reject Message to C++")

def endSessionCallback():
print("send EndSession Message to C++")

if __name__ == "__main__":
app = MainWindow()

UDP socket code:

import time
import struct
import socket
import sys

MYPORT = 51506
MYGROUP_4 = ''

MYTTL = 1 # Increase to reach other networks

def UDPmain():
udpApp = udpsocket()

class udpsocket():
def __init__(self):
print('UDP Socket started')
group = MYGROUP_4

def sender(group):
addrinfo = socket.getaddrinfo(group, None)[0]

s = socket.socket(addrinfo[0], socket.SOCK_DGRAM)

# Set Time-to-live (optional)
ttl_bin = struct.pack('@i', MYTTL)
if addrinfo[0] == socket.AF_INET: # IPv4
s.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, ttl_bin)
s.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_MULTICAST_HOPS, ttl_bin)

while True:
data = repr(time.time())
s.sendto(data + '\0', (addrinfo[4][0], MYPORT))

def receiver(self,group):
# Look up multicast group address in name server and find out IP version
addrinfo = socket.getaddrinfo(group, None)[0]

# Create a socket
s = socket.socket(addrinfo[0], socket.SOCK_DGRAM)

# Allow multiple copies of this program on one machine
# (not strictly needed)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

# Bind it to the port
s.bind(('', MYPORT))

group_bin = socket.inet_pton(addrinfo[0], addrinfo[4][0])
# Join group
if addrinfo[0] == socket.AF_INET: # IPv4
mreq = group_bin + struct.pack('=I', socket.INADDR_ANY)
s.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
mreq = group_bin + struct.pack('@I', 0)
s.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_JOIN_GROUP, mreq)

# Loop, printing any data we receive
while True:
data, sender = s.recvfrom(1500)
while data[-1:] == '\0': data = data[:-1] # Strip trailing \0's
print (str(sender) + ' ' + repr(data))

Kindly look the UI and the comments that I have mentioned

enter image description here

I appreciate people who goes through the entire question. Sorry for keeping it long

Answer Source
  1. Python can use select too: see https://docs.python.org/3.4/library/select.html?highlight=select.select#select.select The FD_SET stuff is handled for you; you just provide lists of file descriptors (or file objects).

  2. Several options here. One is to simply incorporate the other scripts directly into your main code and use multiprocessing to invoke their entry points. https://docs.python.org/3.4/library/multiprocessing.html?highlight=multiprocess#the-process-class There are other options if you wish to invoke them separately, depending on your operating system (os.spawn, os.fork + os.execl, subprocess)

Leaving (3) to someone else who knows tkinter stuff.