1

I have a Blender code which takes sets of data from a csv file and uses them to rotate a robot arm and a human model in the Game Engine. This code works fine, but now I want to send data across a wireless connection to Blender.

I have a server code set up in Blender (which runs on Python 3)

# Server Program
# Make sure the client is being run on the data generation computer

SERVER_LOOP = True

import socket
import sys
import json
import bge

cont = bge.logic.getCurrentController()
owner = cont.owner

print ('INFO: Starting up')


# Create a TCP/IP socket to listen on
print ('INFO: Creating TCP/IP Socket')
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# Prevent from 'ADDRESS ALREADY IN USE' upon restart
print ('INFO: Housekeeping...')
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

# Bind the socket to port 8081 on all interfaces
server_address = ('localhost', 8081)
print ('INFO: Binding and starting up on %s port %s' % server_address)
server.bind(server_address)
print ('INFO: Server bound')

def send_welcome(cont):
    cont.send('SERVER: Welcome'.encode('utf8'))

# Listen for connectons for 5 seconds
server.listen(5)

# Connection is the SOCKET OBJECT for the connection
# Client_address is the connected peer(the client)
connection, client_address = server.accept()
print ('INFO: Connection from', connection.getpeername())
print ('INFO: Sending welcome msg')
send_welcome(connection)
print ()

while SERVER_LOOP:

    # Receive data
    try:
        data = connection.recv(10000)

    # Unless there's an error
    except OSError:
        print (connection)

    # Decode the data into usable lists
    if type(data) != type(''): 
        data = data.decode()

    # If we want to end the client stream but keep the server running    
    if data=='end' or data=='End' or data=='END':
        print ('INFO: Closing connection with ',connection.getpeername())
        connection.shutdown(socket.SHUT_RD | socket.SHUT_WR)
        print ()
        connection.close()
        connection, client_address = server.accept()
        print ('INFO: Connection from', connection.getpeername())
        print ('INFO: Sending welcome msg')
        send_welcome(connection)
        print ()

    # If we want to stop running the server
    elif data=='end server' or data=='End server' or data=='End Server':
        print ()
        print ('SERVER SHUT DOWN')
        SERVER_LOOP = False

    # Display when data is loaded back on the client side
    else:
            # gives feedback in server command line
            data = json.loads(data)
            owner['test'] = data
            print ('CLIENT: %s' % data)
            message = 'ping'
            connection.send(('SERVER: %s' % message).encode('utf-8'))
            print ('SERVER: %s' % message)

And the client code to run with it (this one runs on Python 2.7)

# Client Program
# Make sure the server is being run in Blender

import socket
import time
import json

print 'INFO: Creating Socket'
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

ip_addr = raw_input('IP: ')
port_addr = raw_input('PORT: ')

# Type 'localhost' in the IP field
# Type '8081' in the PORT field

print 'INFO: Connecting to server'
s.settimeout(5) # Times out if 5 seconds without connecting to client
s.connect((ip_addr, int(port_addr)))

# Listen for welcome
data = s.recv(10000)
print data
print ''
while 1:
    message = raw_input('CLIENT: ')
    if message=='end' or message=='End' or message=='END':
            print ''
            print 'SHUTTING DOWN CLIENT, SERVER STILL RUNNING'
            s.send(message)
            break
    elif message=='end server' or message=='End server' or message=='End Server':
            print ''
            print 'SHUTTING DOWN SERVER'
            s.send(message)
            break
    else:
            s.send(message)
            data = s.recv(10000)
            print data

print 'INFO: Closing socket'
s.close()
print 'INFO: Quitting'

Now, obviously this doesn't do the rotations; it's just a test script to make sure that the data transfer between the two works. And it does - in Blender's system console, the data is displayed just as I want it. However, I have a string debug property in Blender titled "test", which is supposed to display the current number just typed in the client, and it's not until I close the whole program down.

For example:

  • I run the server script in Blender
  • I run the client script in IDLE
  • I type in numbers on the client side
  • They appear in the system console on the server side, but they do NOT appear in the Game Engine
  • I close the server from the client side
  • Now, the last number I typed finally appears on the server side

So the problem is that Blender runs my script and then the Game Engine after it's done, but I want them to run concurrently.

Let me know if my explanation doesn't make sense; I can provide downloads to my stuff if need be.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
bshoemak
  • 11
  • 3

1 Answers1

1

I don't know if this is still a problem - you posted in February and it's now August, but I was just searching for the answer of a similar problem. Your problem is that Blender doesn't update its frames until a script has finished running. Your game is literally stuck on the first frame it plays because it starts a script as soon as that frame hits, and because of the nature of your script, never ends.

Currently, you use server.listen(5) to mean that it listens to five seconds, but the number 5 in that function refers to the backlog instead of the length of time [source]. socket.listen() will stall your game indefinitely (as far as I understand) just like an infinite loop would.

This may not be the answer you were looking for, but it's definitely an answer.

Chris
  • 11
  • 1