I am facing a problem when i tried to run the python code. The error is " Name error:global name 'receive' is not defined". May I know how can I solve the problem? I am using this code in my mobile phone to communicate with microcontroller to control ON/OFF ports on the board. Anyone can help me check what is going wrong? And if I delete the ‘def receive()' will it affect my whole program? Actually what is the purpose of the 'receive()'? If I just want to ON/OFF ports, is it necessary to have the 'receive()' in the code? Thank for helping me :$

import appuifw
# import the module socket
import socket
import e32

# function that handles the bluetooth connection:
def bt_connect():
    global sock
    # create a bluetooth socket
    sock=socket.socket(socket.AF_BT,socket.SOCK_STREAM)
    target=''# here you can give the bt address of the other mobile if you know it
    if not target:
        # scan for bluetooth devices
        address,services=socket.bt_discover()
        print "Discovered: %s, %s"%(address,services)
        if len(services)>1:
            choices=services.keys()
            choices.sort()
            # bring up a popup menu and show the available bt devices for selection
            choice=appuifw.popup_menu([unicode(services[x])+": "+x
                                        for x in choices],u'Choose port:')
            target=(address,services[choices[choice]])
        else:
            target=(address,services.values()[0])
    print "Connecting to "+str(target)
    # connect to the serial port of the PC
    sock.connect(target)
    return sock
    print "OK."

def recieve():
    data=sock.recv(1)
    if data=="1":
        appuifw.note(u"LED on","info")
    elif data=="0":
	appuifw.note(u"LED off","info")

def recieve():
    data=sock.recv(2)
    if data=="1":
        appuifw.note(u"Light on","info")
    elif data=="0":
	appuifw.note(u"Light off","info")


def bt_send_data1():
    bt_connect()
    sock.send("1")
    receive()

def bt_send_data2():
    bt_connect()
    sock.send("0")
    receive()

def bt_send_data3():
    bt_connect()
    sock.send("3")
    receive()

def bt_send_data4():
    bt_connect()
    sock.send("4")
    receive()


def quit():
    print"socket closed"
    sock.close()
    app_lock.signal()

app_lock=e32.Ao_lock()

appuifw.app.menu=[(u"LED on",bt_send_data1),
		  (u"LED off",bt_send_data2),
                  (u"Light on",bt_send_data3),
		  (u"Light off",bt_send_data4),
		  (u"Exit", quit]
		  
appuifw.app.exit_key_handler = quit
app_lock.wait()


def exit_key_handler():
    script_lock.signal()
    appuifw.app.set_exit()

appuifw.app.title = u"Smart home"

script_lock = e32.Ao_lock()

appuifw.app.exit_key_handler = exit_key_handler()


script_lock.wait()

Recommended Answers

All 12 Replies

I think the problem is that you misspelled the def receive , so that you defined a recieve function.

I think the problem is that you misspelled the def receive , so that you defined a recieve function.

Oh ya, thank you very much. May I know what is the purpose of the def receive code? If I not misunderstood, it should be receive data from microcontroller to confirm the status of the port. Am I right? If I remove the def receive from the code will it affect my whole program? Thank again ^^

I noticed you have defined receive() twice. This means the first definition is discarded and only the second one counts.

Do you need receive() at all? It depends on what you're doing. Normally you'd do a connect() then exchange many (possibly very many) messages via send() / recv(), then close() when all done, say upon exit. Your code doesn't work that way. It does a connect() for every send() and receive(). But it only does a close() when exiting. So if someone does say 100 LED-on/LED-off commands you're going to create a new socket for each of those commands, but not close() any of them except for the last. Do this enough times and one side or the other will run out of space for open (i.e., not close()d) connections. This is not right, there should be a close() for every connect().

You might get away with changing the calls to receive() to calls to close(), dropping the close() inside the quit(). That would make the sequence connect() / send() / close() which would discard any response data. Problem there is, since you're not doing a recv() you're not waiting for a response, so the close() might actually be invoked before the network has had a chance to finish the send(), so potentially an immediate close() might cancel the send()...it all depends on when your particular O/S decides the send() is done and returns control to you. A hacky way around this would be connect() / send() / time.sleep(0.050) / close() which would work 99.9%+ of the time ... I predict.

Really, the right thing to do is do the recv() and deal with the errors and exceptions that can happen if the microcontroller does not respond.

On an unrelated point, your statement appuifw.app.exit_key_handler = exit_key_handler() should probably read appuifw.app.exit_key_handler = exit_key_handler (function name, not function call) just like the use of = quit a few lines above.

Also, target should probably be a parameter to bt_connect() instead of hard-coded inside the routine.

Can you teach me what should I do now, If I wanna connect the bluetooth module once but can turn ON/OFF LEDs several times. Because I don't wish to connect to bluetooth for every connect. Thanks for helping ^^

You'd put the bt_connect() before you put up the app menu, so the user first sees a list of bt devices and chooses one. You connect to that, carefully checking that the connect() succeeded. I think it's best if bt_connect() were rewritten to separate the functions of (1) selecting a target and (2) connecting to the target, but that can wait until other problems are solved.

Then you enter a loop displaying the app menu and accepting commands. For function commands (everything except quit) you'd call the corresponding send_data() routine, which would send the command and then do a receive() appropriate to the command. You either need two different receive()s (just like you have four different send()s) or one receive() with a parameter that tells it what to look for. Theoreticians can tell you which option is preferable but right now just do the one that feels right to you.

Also take note of my comment on using exit_key_handler instead of exit_key_handler()

Sir, Is it change in this way?

import appuifw
# import the module socket
import socket
import e32

# function that handles the bluetooth connection:
def bt_connect():
    global sock
    # create a bluetooth socket
    sock=socket.socket(socket.AF_BT,socket.SOCK_STREAM)
    target=''# here you can give the bt address of the other mobile if you know it
    if not target:
        # scan for bluetooth devices
        address,services=socket.bt_discover()
        print "Discovered: %s, %s"%(address,services)
        if len(services)>1:
            choices=services.keys()
            choices.sort()
            # bring up a popup menu and show the available bt devices for selection
            choice=appuifw.popup_menu([unicode(services[x])+": "+x
                                        for x in choices],u'Choose port:')
            target=(address,services[choices[choice]])
        else:
            target=(address,services.values()[0])
    print "Connecting to "+str(target)
    # connect to the serial port of the PC
    sock.connect(target)
    return sock
    print "OK."

#def receive():
#    data=sock.recv(1)
#    if data=="1":
#        appuifw.note(u"LED on","info")
#    elif data=="0":
#	appuifw.note(u"LED off","info")

#def receive():
#    data=sock.recv(2)
#    if data=="1":
#        appuifw.note(u"Light on","info")
#    elif data=="0":
#	appuifw.note(u"Light off","info")


def bt_send_data1():
    sock.send("1")
#    receive()

def bt_send_data2():
    sock.send("0")
#    receive()

def bt_send_data3():
#    bt_connect()
    sock.send("3")
#    receive()

def bt_send_data4():
#    bt_connect()
    sock.send("4")
#    receive()


def quit():
    print"socket closed"
    sock.close()
    app_lock.signal()

app_lock=e32.Ao_lock()

bt_connect()
bt_send_data1()
bt_send_data2()
bt_send_data3()
bt_send_data4()

appuifw.app.menu=[(u"LED on",bt_send_data1),
		   (u"LED off",bt_send_data2),
                  (u"Light on",bt_send_data3),
		   (u"Light off",bt_send_data4),
		   (u"Exit", quit]
		  
appuifw.app.exit_key_handler = quit
app_lock.wait()


def exit_key_handler():
    script_lock.signal()
    appuifw.app.set_exit()

appuifw.app.title = u"Smart home"

script_lock = e32.Ao_lock()

appuifw.app.exit_key_handler = exit_key_handler()


script_lock.wait()

Do I need to add global sock below every bt_send_data()?

I have tried the code, it was not workable >.<
Sir, can you help me to rearrange the code?
I am totally no idea how and where to edit it to make it workable. I already struggle on it few months, but no one can help me out :'(

Reasonable people of good will can disagree on such matters, but it is pretty well recognized that parameters and return values are superior to global variables. I'd take out the global sock and pass the socket as a parameter as ff:

def bt_send_data1(sock): # Add the "sock" for all 4 send routines
    sock.send("1")
[...]

# Replace the standalone
bt_connect()
# with
bt_socket = bt_connect()
# When bt_connect() returns "sock", that value gets assigned to "bt_socket" here.
# You could call it "sock" instead of bt_socket, but let's not so as to
# demonstrate return value usage and (later) parameter usage.



# Why are there 4 calls in a row here? Shouldn't just one of them be executed depending on the user's choice? But let's leave that for later.
bt_send_data1(bt_socket)  # Pass in the socket to callee
bt_send_data2(bt_socket)
bt_send_data3(bt_socket)
bt_send_data4(bt_socket)

So the body of routine bt_send_data1() has its own variable called sock that takes on the value of bt_socket in the mainline, which itself came from the return sock in bt_connect(). You may not believe it, but this is actually better than having a single global variable sock. For example, you might have cause to connect to two or more bt devices. You could connect to the first device and call it bt_socket_1 and, while still connected to the first device, also connect to the second device and call that (different) socket bt_socket_2, or maybe use names like headset and microphone, both bt sockets returned from bt_connect(). Something like this:

headset = bt_connect()
microphone = bt_connect()

You do not need that right here but you will soon, and for the rest of your life. (With apologies to Rick Blaine).

When you call bt_send_data1(bt_socket) then inside routine bt_send_data(sock) the variable sock, which is strictly local to bt_send_data, takes on the value assigned to bt_socket in the calling program. You could also have written it:

def bt_send_data1(mySocket):
    mySocket.send("1")

... and it would work identically. So a call to bt_send_data1(microphone) would send a "1" to the device represented by the socket connected to microphone even though inside bt_send_data1() it's called something else. Again, very useful if you have multiple sockets.

By the way, the print "OK." inside bt_connect() is never going to be executed because the return sock statement is going to complete the execution of bt_connect() and return the value of sock to the caller. That's how bt_socket picks up the value of sock.

Don't forget to drop the parentheses off of appuifw.app.exit_key_handler = exit_key_handler() .

I don't expect we're done yet.

Thanks for helping me sir ^^
I will try to change accordingly to what you mentioned above.
May I know what we not done yet?

sir,
it still got error when i try to run the code
It can't even search for devices too >.<

Sir,
after i changed the code, my mobile cant even search for devices >.<

Sir, this is my new code.
It now able to connect to device, but I have not try out is it able to control the port. will let you once i tried out.
thanks for your helping hand sir ^^

import appuifw
# import the module socket
import socket
import e32

# function that handles the bluetooth connection:
def bt_connect():
    global sock
    # create a bluetooth socket
    sock=socket.socket(socket.AF_BT,socket.SOCK_STREAM)
    target=''# here you can give the bt address of the other mobile if you know it
    if not target:
        # scan for bluetooth devices
        address,services=socket.bt_discover()
        print "Discovered: %s, %s"%(address,services)
        if len(services)>1:
            choices=services.keys()
            choices.sort()
            # bring up a popup menu and show the available bt devices for selection
            choice=appuifw.popup_menu([unicode(services[x])+": "+x
                                        for x in choices],u'Choose port:')
            target=(address,services[choices[choice]])
        else:
            target=(address,services.values()[0])
    print "Connecting to "+str(target)
    # connect to the serial port of the PC
    sock.connect(target)
    print "OK."

def bt_send_data1(sock):
    sock.send("1")
    receive()

def bt_send_data2(sock):
    sock.send("0")
    receive()

# call the function that handles the bluetooth connection
bt_socket = bt_connect()

def quit():
    print"socket closed"
    sock.close()
    app_lock.signal()

app_lock=e32.Ao_lock()

appuifw.app.menu=[(u"LED on",bt_send_data1),
		  (u"LED off",bt_send_data2)]
		  
appuifw.app.exit_key_handler = quit
app_lock.wait()


def exit_key_handler():
    script_lock.signal()
    appuifw.app.set_exit()

appuifw.app.title = u"Smart home"

script_lock = e32.Ao_lock()

appuifw.app.exit_key_handler = exit_key_handler

script_lock.wait()
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.