Bidirectional communication between python and godot
Asked Answered
V

10

0

Hello! I am trying to make a game controlled by a custom controller. For this, I use an arduino to give input to a python script which gives the data to a godot script using UDP. With a lot of help I have scrambled together a script that accomplishes that, but I would like to be able to send data from godot to python and then to the arduino too (for example the player's character died, so the player can't shoot until they respawn). Whatever I tried didn't work, so here is the scripts so far, in case anyone can help me.
gdscript:


 extends Node
 
 # Configure the UDP socket for receiving data from Python
 var python_address : String = "127.0.0.1"
 var python_port : int = 12345
 var python_socket := PacketPeerUDP.new()
 var data_list
 var begin = false
 
 func _ready():
 	# Bind the socket to the specified address and port
 	python_socket.bind(python_port, python_address)
 
 func _process(delta):
 	# Check for incoming data
 	if python_socket.get_available_packet_count() > 0:
 		# Receive data from Python
 		#var data : PacketPeerUDP = python_socket.get_packet()
 		var data = python_socket.get_packet()
 		print(data)
 		# Process the received data as needed
 		var decoded_data : String = data.get_string_from_utf8()
 		
 		data_list = decoded_data.split(",")
 		#print(data_list)
 		begin = true

python:


import serial
from serial import Serial
from pynput.mouse import Button, Controller
from socket import socket, AF_INET, SOCK_DGRAM
m_left = False
m_right = False
godot_address = ('127.0.0.1', 12345)  # Adjust the IP and port as needed
godot_socket = socket(AF_INET, SOCK_DGRAM)
try:
       # Setting Serial port number and baudrate
	ser = serial.Serial('COM4', 9600)
except:
	print("Mouse not found or disconnected.")
	k=input("Press any key to exit.")
mouse = Controller()
while True:
	try:
		dump = ser.readline()                           # Reading Serial port
		dump = str(dump)                                # Converting byte data into string
		dump = dump[2:-5]                               # Cleaning up the raw data recieved from serial port
		data = dump.split(',')                          # Spliting up the data to individual items in a list. the first item being the data identifier
		print(data)   
		data_bytes = ','.join(data).encode('utf-8')        
		godot_socket.sendto(data_bytes, godot_address)            
	except (ValueError, IndexError):
		pass

P.S.: I know there are better ways to do this (with gdnative for example), but this is the simplest one. I use godot 4.1

Vintner answered 26/11, 2023 at 21:11 Comment(0)
F
0

Is this the simplest way? A GDExtension (GDNative's successor) would be straightforward. I'd be surprised if someone hasn't already even made one to enable arbitrary Python execution. Sorry, but you're probably going to have a hard time finding someone who has done specifically what you're trying to do here on this forum.

Ferity answered 26/11, 2023 at 22:33 Comment(0)
F
0

Looking at your scripts more closely, I don't see anything even trying to communicate from Godot to Python?

Ferity answered 26/11, 2023 at 22:52 Comment(0)
V
0

Ferity I didnt have much luck finding straightforward tutorials about gdextension, but maybe I didn't search a lot. Also, yes there is no code for sending data from godot to python, since non of my attempts even remotely work. I guess if there is a way to send messages from a godot client to a godot server, it would work for my case (put_packet() didnt work)

Vintner answered 26/11, 2023 at 23:4 Comment(0)
A
0

Vintner didn't work

What do you mean didn't work? What happened? Any errors? What's preventing you from just sending data through the socket?

Anu answered 26/11, 2023 at 23:23 Comment(0)
V
0

Anu
godot:

extends Node

# Configure the UDP socket for receiving data from Python
var python_address : String = "127.0.0.1"
var python_port : int = 12345
var python_socket := PacketPeerUDP.new()
var data_list
var begin = false

func _ready():
	# Bind the socket to the specified address and port
	python_socket.bind(python_port, python_address)

func _process(delta):
	# Check for incoming data
	if python_socket.get_available_packet_count() > 0:
		# Receive data from Python
		#var data : PacketPeerUDP = python_socket.get_packet()
		var data = python_socket.get_packet()
		print(data)
	if Input.is_action_just_pressed("enter"):
		var a : PackedByteArray = [1]
	
		python_socket.put_packet(a)

python:

import socket
import time
# Server configuration
server_address = ('127.0.0.1', 12345)

# Create a socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# Bind the socket to a specific address and port
server_socket.bind(server_address)

# Listen for incoming connections
server_socket.listen()
# Handle incoming data
print(f"Server listening on {server_address}")

# Accept a connection from the client
client_socket, client_address = server_socket.accept()
print(f"Connection established with {client_address}")

while True:
        # Receive data from the client
        data = client_socket.recv(1024)
        if not data:
            break
        print(f"Received from client: {data.decode('utf-8')}")

        # Send a response back to the client
        response = "Hello from server!"
        client_socket.send(response.encode('utf-8'))

I tried the python code with a python client and it work. The error from godot's side is this:
E 0:01:25:0032 global.gd:24 @ _process(): Condition "!peer_addr.is_valid()" is true. Returning: ERR_UNCONFIGURED
<C++ Source> core/io/packet_peer_udp.cpp:123 @ put_packet()
<Stack Trace> global.gd:24 @ _process()

Vintner answered 26/11, 2023 at 23:49 Comment(0)
A
0

Vintner Have you tried connect_to_host() instead of bind()?

Anu answered 27/11, 2023 at 0:24 Comment(0)
V
0

Anu I just tried, godot doesn't even get the message from python

Vintner answered 27/11, 2023 at 8:41 Comment(0)
A
0

Vintner Does it return an error? What's the error code? What's the error code returned by put_packed(). Check all the error codes returned by functions you use.

Anu answered 27/11, 2023 at 13:43 Comment(0)
V
0

Anu connect_to_host doesnt return an error code, it just doesnt connect. i tried it at code i knew was working and it didnt work. The pu_packet() return this error:
E 0:01:25:0032 global.gd:24 @ _process(): Condition "!peer_addr.is_valid()" is true. Returning: ERR_UNCONFIGURED
<C++ Source> core/io/packet_peer_udp.cpp:123 @ put_packet()
<Stack Trace> global.gd:24 @ _process()

Vintner answered 27/11, 2023 at 16:32 Comment(0)
A
0

Vintner connect_to_host doesnt return an error code, it just doesnt connect

Doesn't return or doesn't print? Do you explicitly test the return value? Let's see the exact code. Also try it with set_dest_address()

Anu answered 27/11, 2023 at 16:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.