英文:
Attempting to pass values from GUI to another app with socket
问题
以下是您要的代码的翻译:
如标题所述,我试图创建两个独立的应用程序,一个是GUI/客户端,另一个是控制器/服务器。
GUI使用多个滑块从用户那里获取输入并通过套接字将值传输给控制器。
控制器接收数据并通过SPI连接将其传输到另一个外围设备。
程序传输第一个值然后崩溃。我得到的错误信息是这两个:
连接被对等方重置的错误和断开的管道错误。
GUI代码如下:
def Configure(e):
Command(0, 0, ch0, reg_X, group_0, ch_0, 1)
def dacCommand(bus, dev, dacVar, command, dacGroup, dacChannel, multFac):
Vref = 3
offsetCode = 0x1555
M = 65535
C = 32768
Iout = dacVar.get()
Vout = Iout * multFac
byte1 = command | dacGroup | dacChannel
dacCode = math.ceil(Vout * (2**16) / (4 * Vref) + 4 * offsetCode)
inputCode = math.floor((dacCode - C + (2**15)) * (2**16) / (M + 1))
d = struct.pack('<H', inputCode)
data = [0, 0, 0]
dataCommand = [byte1, d[1], d[0]]
byte1bin = f'{byte1:08b}'
byte2bin = f'{d[1]:08b}'
byte3bin = f'{d[0]:08b}'
dataString = byte1bin + byte2bin + byte3bin
client_socket.send(bytes(dataString, "utf-8"))
if __name__ == "__main__":
window = Tk()
window.title('DACs board control')
window.geometry('1920x900')
tab_control = ttk.Notebook(window)
tab2 = Frame(tab_control)
tab_control.add(tab2, text='dev1 control')
tab_control.pack(expand=1, fill="both")
ch0 = DoubleVar()
ttk.Label(tab2, text="ch0 (V)", font=("Calibri", 12)).grid(column=0, row=0, padx=10,
pady=5)
ch0Scale = Scale(tab2, from_=0, to=Vmax, resolution=0.05, state="normal", variable=
ch0, command=Configure, font='Helevetica 11', length=200, width=15).grid(row=1,
column=0, pady=5, padx=10, sticky='w')
mainloop()
控制器代码如下:
if __name__ == "__main__":
spi = spidev.SpiDev()
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((socket.gethostname(), 1234))
s.listen(5)
conn, address = s.accept()
print(f"Connection from {address} has been established.")
while True:
command = conn.recv(24)
if not command:
break
spi.open(0, 0)
spi.mode = 0b01
spi.max_speed_hz = 1000000
part1 = command[:8]
part2 = command[8: 16]
part3 = command[16:]
spi.xfer2([int(part1, 2), int(part2, 2), int(part3, 2)]
spi.close()
conn.close()
希望这些翻译对您有所帮助。如果您有任何其他问题,请随时提问。
英文:
As i state in the title i'm trying to create a 2 seperate applications, one being a GUI/client and the other being a controller/server.
The GUI uses several sliders to take an input from the user and transfers the value to the controller through a socket.
The controller receives the data and transfers it to another peripheral device, through a SPI connection.
The program transfers the first value and then proceeds to crash. The errors i get are these two :
error connection reset by peer and error broken pipe.
The gui code is
def Configure(e):
Command(0, 0, ch0, reg_X, group_0, ch_0, 1)
def dacCommand(bus,dev,dacVar,command,dacGroup,dacChannel,multFac):
Vref = 3
offsetCode = 0x1555
M = 65535
C= 32768
Iout=dacVar.get()
Vout=Iout*multFac
byte1 = command|dacGroup|dacChannel
dacCode=math.ceil(Vout*(2**16)/(4*Vref)+4*offsetCode)
inputCode=math.floor((dacCode-C+(2**15))*(2**16)/(M+1))
d = struct.pack('<H', inputCode)
data= [0, 0, 0 ]
dataCommand = [byte1, d[1], d[0]]
byte1bin=f'{byte1:08b}'
byte2bin=f'{d[1]:08b}'
byte3bin=f'{d[0]:08b}'
dataString=byte1bin+byte2bin+byte3bin
client_socket.send(bytes(dataString,"utf-8"))
if __name__ == "__main__":
window = Tk()
window.title('DACs board control')
window.geometry('1920x900')
tab_control = ttk.Notebook( window)
tab2 = Frame( tab_control)
tab_control.add(tab2, text= 'dev1 control')
tab_control.pack(expand= 1, fill= "both")
ch0 = DoubleVar()
ttk.Label(tab2, text= "ch0 (V)", font= ("Calibri", 12)).grid(column= 0, row= 0, padx= 10,
pady= 5)
ch0Scale = Scale(tab2, from_= 0, to = Vmax, resolution = 0.05, state = "normal", variable=
ch0, command= Configure, font='Helevetica 11', length = 200, width = 15).grid(row = 1,
column = 0, pady = 5, padx = 10, sticky = 'w')
mainloop()
The controller code is :
if __name__ == "__main__":
spi=spidev.SpiDev()
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((socket.gethostname(), 1234))
s.listen(5)
conn, address = s.accept()
print(f"Connection from {address} has been established.")
while True:
command = conn.recv(24)
if not command:
break
spi.open(0,0)
spi.mode = 0b01
spi.max_speed_hz = 1000000
part1=command[:8]
part2=command[8: 16]
part3=command[16:]
spi.xfer2([int(part1,2),int(part2,2),int(part3,2)])
spi.close()
conn.close()
答案1
得分: 1
客户端和服务器正在执行单个发送和接收操作,为了解决您的问题,您应该使客户端和服务器通过持续通信来维护连接。
首先,在服务器端,您应该修改您的代码如下:
if __name__ == "__main__":
# ...
while True:
conn, address = s.accept()
print(f"Connection from {address} has been established.")
while True:
command = conn.recv(24)
if not command:
break
# ...
conn.close()
然后在客户端端:
from tkinter import filedialog
def Configure(e):
# ...
if __name__ == "__main__":
# ...
window.createfilehandler(client_socket, tkinter.READABLE, Configure)
# ...
mainloop()
window.deletefilehandler(client_socket)
它应该可以工作,但由于 recv
可能会出现更多问题,您应该考虑异步编程或多线程。
英文:
The client and server are doing a single send and receive operation, to fix your problem you should make the client and server maintain the connection by a continuous communication.
first on the server side you should modify your code like this:
if __name__ == "__main__":
# ...
while True:
conn, address = s.accept()
print(f"Connection from {address} has been established.")
while True:
command = conn.recv(24)
if not command:
break
# ...
conn.close()
then on the client side:
from tkinter import filedialog
def Configure(e):
# ...
if __name__ == "__main__":
# ...
window.createfilehandler(client_socket, tkinter.READABLE, Configure)
# ...
mainloop()
window.deletefilehandler(client_socket)
it should work but you might have more issues because of recv
you should look into asynchronous programming or multithreading.
答案2
得分: 1
Send the bytes. It appears you need to send the input code big-endian, so use >
instead of <
in the format string and include the command byte. Use sendall
to ensure all 3 bytes are sent (very likely even with send()
but send()
can send less under the right conditions).
data = struct.pack('>BH', byte1, inputCode)
client_socket.sendall(data)
On the client, read the 3 bytes. Note you should check the return value of conn.recv
to make sure it actually receives 3 bytes. The value is a maximum to receive.
data = conn.recv(3)
if len(data) != 3:
# deal with it
spi.xfer2(list(data)) # list on bytes data will return the values,
# e.g., b'\x01\x02\x03' returns [1, 2, 3].
# May not be needed if the function accepts
# byte strings...
英文:
No need to send actual ones and zeros. Send the bytes. It appears you need to send the input code big-endian, so use >
instead of <
in the format string and include the command byte. Use sendall
to ensure all 3 bytes are sent (very likely even with send()
but send()
can send less under the right conditions.
data = struct.pack('>BH', byte1, inputCode)
client_socket.sendall(data)
On the client, read the 3 bytes. Note you should check the return value of conn.recv
to make sure it actually receives 3 bytes. The value is a maximum to receive.
data = conn.recv(3)
if len(data) != 3:
# deal with it
spi.xfer2(list(data)) # list on bytes data will return the values,
# e.g., b'\x01\x02\x03' returns [1, 2, 3].
# May not be needed if the function accepts
# byte strings...
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论