How to send python command from maya to UE5(via it's remote execution api)

I want to send a python script from maya to UE5. Need help with how to configure the sender script to connect to UE5.
the reason I need to send the python script directly from maya to UE5 rather than run the script directly in UE5 is I need to pass multiple variables to the script for each asset I’m processing in maya(also a python script), and to run the UE5 script directly in UE5 without communicating with maya would mean I need to hard code the different variables for each asset’s’ import and build process in the UE5 script. to do that would defy the purpose of automation with python.

Here is how far I got, trying to set up the sender script and connect to UE5, to send a simple print(‘hello world’)

import socket

def main():
    MCAST_GRP = '239.0.0.1'
    MCAST_PORT = 6766
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
    sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 32)
    sock.sendto(b"print('hellow world!')", (MCAST_GRP, MCAST_PORT))

if __name__ == '__main__':
    main()

here is the UE5 python remote execution api setting:
Screenshot 2023-09-05 113106

when I run this script in maya, I got an error in UE5:
LogPythonRemoteExecution: Error: Failed to read remote execution message ‘print(‘hellow world!’)’: Failed to deserialize json object! Invalid Json Token. Line: 1 Ch: 1

document or discussion on this is scaringly little, if someone can help with this I will be extremely grateful!!

Your payload that you send with sendto must be a JSON string with a specific format to it.
I cannot remember what the expected format should be but you can take a look at the source code for this blender plugin to try and figure it out:
https://github.com/EpicGames/BlenderTools

1 Like

Hi, thanks for replying, but the link you posted is empty 404

Weird - link seems to work for me.
Here is a link directly to the code:
https://github.com/EpicGames/BlenderTools/tree/main/send2ue

I tried to login to my github account first then click the link, still got “404 this is not the web page you are looking for” from github. This is weird, I’m in Singapore, and I can look at other github project but not the one you post.
But I manage to download that blender plugins from elsewhere, and will be looking into it soon, there are a lot of file in it, do you know where I can find what I’m looking for?

Hmmm - maybe you need to be apart of the epic organisation on GitHub.
I went through that plugin about a year ago which is too long for me to remember any specifics. I would start by searching for a sendto in the codebase though

1 Like

How do I link my Unreal Engine account with my Github account?

JUMP

To link your Github and Unreal Engine/Epic Games accounts:

  1. Navigate to your Connected Accounts page.
  2. Click CONNECT under GITHUB.
  3. Log in to your GITHUB account in the new window that opens.
  4. Click Sign In.
  5. You will receive a confirmation email from Github with a verification link. Make sure to click the verification link to finish the account linking process.
1 Like

404s for me as well.

Hi, Are you also working on this problem? If so and you want the source code I can send it to you, maybe we can work this out together and share the finding. I look through some code on Saturday, and find myself lack some “fundamental programing understanding”, I do some python scripting, but never a project this big, it’s even confusing to look at all the source code.

Update on this thread.
After reading the blender plugins “blend2ue” source code, mainly the pythonremoteexcution.py file, and now I know how much I lack the fundamental knowledge on OOP developing. I couldn’t figure it out just based on the implemented source code alone, and so I found the C++ source file for handling python remote execution, that’s where UE declare how the json byte should be configure, the C++ file is located on where you install your engine: engineInstallLocation\Epic Games\UE_5.1\Engine\Plugins\Experimental\PythonScriptPlugin\Source\PythonScriptPlugin\Private\PythonScriptRemoteExecution.cpp

Below is the doc string in the C++ source code describe the remote execution protocol:

/**
 * Remote Execution protocol definition.
 *
 * Messages are a UTF-8 encoded JSON object with the following layout:
 *	{
 *		"version": 1,		// Required - Integer - Protocol version number (currently 1)
 *		"magic": "ue_py",	// Required - String  - Protocol magic identifier (currently "ue_py")
 * 		"type": "...",		// Required - String  - Identifier for the message type (see below)
 * 		"source": "...",	// Required - String  - Unique identifier of the node that sent the message (typically a GUID)
 * 		"dest": "...",		// Optional - String  - Unique identifier of the node that should receive the message (typically a GUID)
 * 		"data": "..."		// Optional - Any	  - Message specific payload data (see below)
 *	}
 *
 * Message types:
 *	"ping" (UDP) - Service discovery request
 *
 *	"pong" (UDP) - Service discovery response
 *		"dest" - Required - String - The node that requested the discovery
 *		"data" - Required - Object - Payload data:
 *			{
 *				"user": "...",				// Required - String - The name of the user that owns the engine instance
 *				"machine": "...",			// Required - String - The name of the machine that owns the engine instance
 *				"engine_version": "...",	// Required - String - The version number of the engine
 *				"engine_root": "...",		// Required - String - The absolute on-disk root of the engine
 *				"project_root: "...",		// Optional - String - The absolute on-disk root of the project (if a project is loaded)
 *				"project_name": "..."		// Optional - String - The name of the project (if a project is loaded)
 *			}
 *
 *	"open_connection" (UDP) - Open a TCP command connection with the requested server
 *		"dest" - Required - String - The node that should open a connection to the server
 *		"data" - Required - Object - Payload data:
 *			{
 *				"command_ip": "...",		// Required - String  - The IP address of the TCP command server
 *				"command_port": 0			// Required - Integer - The port of the TCP command server
 *			}
 *
 *	"close_connection" (UDP) - Close any active TCP command connection
 *		"dest" - Required - String - The node that should close its connection to the server
 *
 *	"command" (TCP) - Execute a remote Python command
 *		"dest" - Required - String - The node that should execute the command
 *		"data" - Required - Object - Payload data:
 *			{
 *				"command": "...",			// Required - String  - The command to execute
 *				"unattended": True,			// Required - Boolean - Whether to run the command in "unattended" mode (suppressing some UI)
 *				"exec_mode": "..."			// Required - String  - The execution mode to use as a string value (see EPythonCommandExecutionMode, and LexToString, LexFromString)
 *			}
 *
 *	"command_result" (TCP) - Result of executing a remote Python command
 *		"dest" - Required - String - The node that should receive the result
 *		"data" - Required - Object - Payload data:
 *			{
 *				"success": True,			// Required - Boolean - Whether the command executed successfully (without raising an uncaught exception)
 *				"command": "...",			// Required - String  - The command that was executed
 *				"result": "...",			// Required - String  - The result of running the command
 *				"output": [{				// Required - List    - The log output from running the command
 *					"type: "...",				// Required - String - The type of output (Info, Warning, or Error)
 *					"output": "..."				// Required - String - The actual log output
 *					}]
 *			}
 */

And now from what I gather from both side, it seems like the communication between “client” (blender using the “send2ue” plugin or maya which I’m trying to achieve the same thing ) and “server” UE5 happens at least 5 or 6 times:

  1. maya sending an UDP broadcast asking for every currently running UE5 instance;
  2. every running UE5 instance response to that broadcast and give it’s GUID, known as NODEID in the blender “send2ue” plugins?
  3. maya catch that response, and now sending an “open_connection” type json in UDP mode to the desire NODEID, asking UE5 to open a TCP/IP port(define by maya I suppose?) for the next move, and I guess UE5 just open a TCP/IP port waiting for data? Did UE5 just automatically broadcast it’s GUID to whoever is listening? How do I listen for that response to catch that very important GUID for all the “dest” key that’re required in later on json message?
  4. maya finally send a “command” type json(this time in TCP mode?) to the TCP/IP port maya told UE5 to open in previous move, the actual python command string is put into the data[‘command’] value?
  5. maya catch the result of UE5 executing the python script, like HOW?
  6. maya send a “close_connection” type json in UDP mode again to tell UE5 to close down any TCP/IP port that are open.

I got so so so many question…
I’m not good at socket programming in python, heck I’m not even good at large project developing in python, and completely new to C++, if someone can take a look at my assumption and answer whichever question in those steps it would be great, or maybe my assumption is completely wrong and to point out what it should be, just to narrow it down a little bit so I know where to start.
Thanks~