Receive data via bluetooth using python on android phone - python

I have an ESP32 board which sends data via bluetooth. I can receive data on PC using this python code:
from bluetooth import *
import sys
def input_and_send():
while True:
data = input()
if len(data) == 0: break
sock.send(data)
sock.send("\n")
def rx_and_echo():
sock.send("\nsend anything\n")
while True:
data = sock.recv(buf_size)
if data:
print(data.decode('utf-8'))
sock.send(data)
addr = "XX:XX:XX:XX:XX:XX"
service_matches = find_service( address = addr )
buf_size = 1024
if len(service_matches) == 0:
print("couldn't find the SampleServer service =(")
sys.exit(0)
for s in range(len(service_matches)):
print("\nservice_matches: [" + str(s) + "]:")
print(service_matches[s])
first_match = service_matches[0]
port = first_match["port"]
name = first_match["name"]
host = first_match["host"]
port = 1
print("connecting to \"%s\" on %s, port %s" % (name, host, port))
sock = BluetoothSocket(RFCOMM)
sock.connect((host, port))
print("connected")
# input_and_send()
rx_and_echo()
sock.close()
Data.append(data.decode('utf-8'))
Now, I want to get data on android phone. I wrote a python program using kivy, but bluetooth package does not work on android. I tried bleak and jnius packages, but they did not work. Is there another packages which can use bluetooth of phone properly? I see, some persons advise using jnius package for android, but I could not get data using "BluetoothReceive" function.
Any help is appreciated.

I understood how to receive data using python on android. I used jnius package, and tried to look errors using this code on android phone.
I found theBufferReader should be used instead of getInputStream(), and readLine() instead of readline(). You can receive data using the below code:
from jnius import autoclass
BluetoothAdapter = autoclass('android.bluetooth.BluetoothAdapter')
BluetoothDevice = autoclass('android.bluetooth.BluetoothDevice')
BluetoothSocket = autoclass('android.bluetooth.BluetoothSocket')
UUID = autoclass('java.util.UUID')
BufferReader = autoclass('java.io.BufferedReader')
InputStream = autoclass('java.io.InputStreamReader')
paired_devices = BluetoothAdapter.getDefaultAdapter().getBondedDevices().toArray()
socket = None
for device in paired_devices:
if device.getName() == 'ESP32':
socket = device.createRfcommSocketToServiceRecord(
UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"))
recv_stream = BufferReader(InputStream(socket.getInputStream()))
break
socket.connect()
Serial_Data = recv_stream.readLine()
Add this bluetooth permision to your buildozer.spec file.
android.permissions = BLUETOOTH, BLUETOOTH_ADMIN, ACCESS_FINE_LOCATION
Since jnius package does not work on PC (Windows or Linux), I hope there be another way to debug the python code directly, without making application and testing it on android phone.

Related

Sending files over bluetooth using PyBluez and PyOBEX

I'm trying to send a file from my laptop(win10) to my mobile(android) over bluetooth. I followed this answer and I'm doing the same with python 3.6
I'm using PyOBEX Python 3 Package and this is what I've tried.
import sys
from PyOBEX.client import Client
from bluetooth import *
addr = '60:7E:DD:A7:42:43'
print("Searching for OBEX service on {}".format(addr))
services = find_service(address=addr, name=b'OBEX Object Push\x00')
if len(services) == 0:
sys.exit()
first_match = services[0]
port = first_match["port"]
client = Client(addr, port)
client.connect()
client.put("test.txt", "Hello world\n")
client.disconnect()
When I run this, the device is discovered but it doesn't establish a connection or send files. This is the error it gives
I tried messing around with the PyOBEX package by changing the type of data returned by socket_.recv to str but it gives me another error,
I'm stuck and I have never worked with bluetooth or sockets before. Any help is appreciated

Python socket connection error: OSError: [Errno 9] Bad file descriptor

I am trying to write a client/server program in python that will accept multiple connections and manage them using threading. The server and client both run, and the client will receive the "welcome" message from the servers "processClient" function, which means the connection is being made and the thread is being started. However, any subsequent receive or send on the connection object after the welcome message fails with an "OSError: [Errno 9] Bad file descriptor" error. I've done some searching on the error, and most problems seem to result from someone trying to use a socket or connection that's been previously closed-which should not be the case here. Does anyone know what could be causing the error? Running python version 3.5.2
Server code:
#!/usr/bin/env python3
import socket
import sys
import os
import datetime
import threading
import random
PORT = 65432 # Port to listen on (non-privileged ports are > 1023)
def processClient(conn, id):
welcome = "Hello, you are client number " + str(id)
welcome = bytes(welcome, 'utf-8')
conn.sendall(welcome)
while True:
data = conn.recv(1024)
print(rpr(data))
time = str(datetime.datetime.now())
arr = bytes(time, 'utf-8')
if data == b'time':
conn.sendall(arr)
elif data == b'':
conn.close()
return
else:
temp = data.decode("utf-8")
temp = temp.upper()
temp = bytes(temp, 'utf-8')
conn.sendall(temp)
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except:
print("unable to create socket connection, shutting down.")
quit()
s.bind(('0.0.0.0', PORT))
s.listen()
sys.stdout.write("Server is running \n")
runningThreads = []
threadID = 0
while True:
conn, addr = s.accept()
with conn:
#conn.setblocking(False)
print('Connected by', addr)
threadID += 1
threadTemp = threading.Thread(target = processClient, args=(conn, threadID))
threadTemp.start()
runningThreads.append(threadTemp)
for t in runningThreads:
if not t.isAlive():
# get results from thtead
t.handled = True
threadID -= 1
else:
t.handled = False
runningThreads = [t for t in runningThreads if not t.handled]
Client code:
#!/usr/bin/env python3
import socket
import sys
import os
import datetime
HOST = 0
while HOST == 0 or HOST == "":
HOST = input("Please enter host IP: ")
PORT = 65432 # The port used by the server
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((HOST, PORT))
data = s.recv(1024)
print(repr(data))
while True:
inputString = input("Please input a string: ")
temp = bytes(inputString, 'utf-8')
s.sendall(temp)
if inputString == "":
quit()
data = s.recv(1024)
if data:
print(rpr(data))
for anyone else who stumbles across this: I did finally work out the problem. The server was not waiting on input from the client before it attempts to read data from the connection, which was triggering the error (the error message was particularly unhelpful in diagnosing this issue). I rewrote this to use python selectors rather than threads-selectors includes very handy polling functionality that can be used to "pause" until there is data to be read. I could have built this into the program myself, but why do so when there's already a language feature that does it for you?

Skype4Py will not attach to Skype on windows

i am using a 32 bit python to run it on my win 8 machine, when i run the program skype is responding with a message (seen in the top bar) : "Another application (python.exe) is attempting to access Skype , but we are unable to respond. Please try to restart the application"
Code:
import Skype4Py
import socket
import codecs
import sys
#setup
#sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#server_address = ('127.0.0.1', 65205)
#print 'starting up on '+ str(server_address[1])
#sock.bind(server_address)
#sock.listen(1)
#enableling different languages
UTF8Writer = codecs.getwriter('utf8')
sys.stdout = UTF8Writer(sys.stdout)
#skype setup
skype =Skype4Py.Skype()
availFriends = []
skype.Attach()
#block mode
def mstat(Message,status):
if(status == Skype4Py.cmsReceived ):#act on receive
Message.MarkAsSeen()
print Message.Body
skype.SendMessage(Message.Sender.Handle,"Did you send me :\n"+Message.Body+"\n good , Stop messaging me!")
def GetAllOnlinePeople():
availFriends = []
badStatusCodes = ['UNKNOWN', 'OFFLINE', 'DND', 'LOGGEDOUT']
for f in skype.Friends:
if not f.OnlineStatus in badStatusCodes:
availFriends.append(f)
###########################################3
#connection, client_address = sock.accept()
#print 'connection from'+ str(client_address[0])
# Receive the data in small chunks and retransmit it
#data = connection.recv(128)
#if data== 'bmode':
skype.OnMessageStatus = mstat
while(1==1):
i='p'
Not sure that this would help, but recently I've seen the similar message form skype while I was trying to start sevabot from Windows PowerShell.
Pls, see the screenshot below:
As soon as I launched it from windows cmd, that alert has gone.
My Skype version is 7.16.85.102 and Skype4Py version is 1.0.35.
Hope that helps.

Issues getting python 3 linux created script to run on Windows python 3

If anyone can help me, that would be great. I created a python server and client script on Linux with python version 2.6. To my understanding as long as I install the same version of python in Windows, I should be able to run the same script with out a problem. I did this and the script doesn't do anything except print out "Importerror: no module named fcntl". I'm adding the server code and the client. If any one can shed some light on what it is that I'm doing wrong, that would be great. As well, since I'm already here, how can I possibly also get the client side code to run automatically in windows with out having to install python in client side machines.
CLIENT
#!/usr/bin/env python
import socket
import fcntl
import struct
#############################
def get_ip_address(ifname):
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
return socket.inet_ntoa(fcntl.ioctl(
s.fileno(),
0x8915, # SIOCGIFADDR
struct.pack('256s', ifname[:15])
)[20:24])
def getHwAddr(ifname):
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
info = fcntl.ioctl(s.fileno(), 0x8927, struct.pack('256s', ifname[:15]))
return ''.join(['%02x:' % ord(char) for char in info[18:24]])[:-1]
host = socket.gethostname()
#print host
#print getHwAddr('eth0')
#print get_ip_address(enter code here'eth0')
info = "<"+get_ip_address('eth0')+">","{"+ getHwAddr('eth0')+"}","~"+host+"~"
############################
TCP_IP = 'IP'
TCP_PORT = xxxx
BUFFER_SIZE = 1024
MESSAGE = "Hello, World!"
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))
s.send(str(info))
data = s.recv(BUFFER_SIZE)
s.close()
#print "received data:", data
SERVER
import socket
import re
import subprocess
TCP_IP = ''
TCP_PORT = XXXX
BUFFER_SIZE = 2048 # Normally 1024, but we want fast response
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((TCP_IP, TCP_PORT))
s.listen(50)
conn, addr = s.accept()
print 'Connection address:', addr
while 1:
data = conn.recv(BUFFER_SIZE)
if not data: break
print "received data:", data
da = open("data.txt", "wb")
da.write(data);
conn.send(data) # echo
subprocess.Popen(["python", "ReadandInsert.py"])
conn.close()
Also, quick mention. The server side code will only run in Linux and the client code will be running in Windows. Thank you again for anyone that can lend a hand...!!
fcntl only exists on Unix platforms.
Try using the following to get the mac address on Windows in replace of your fcntl.ioctl() call:
import netifaces as nif
...
...
def getHwAddr(ip):
'Returns a list of MACs for interfaces that have given IP, returns None if not found'
for i in nif.interfaces():
addrs = nif.ifaddresses(i)
try:
if_mac = addrs[nif.AF_LINK][0]['addr']
if_ip = addrs[nif.AF_INET][0]['addr']
except IndexError:
if_mac = if_ip = None
except KeyError:
if_mac = if_ip = None
print if_ip, ip
if if_ip == ip:
return if_mac
return None
This is from a user name #kursancew, but I think it is very appropriate. I modified the name to match.
Then, just fix this line so you can configure by IP instead of by interface name across the board (interface names in Windows are a bit ... longer).
ip_address = '123.234.34.5' # from your configuration
...
...
info = "<"+ip_address+">","{"+ getHwAddr(ip_address)+"}","~"+host+"~"

RFCOMM without pairing using PyBluez on Debian?

I am trying to create an RFCOMM server process with Python that can be used without the need for pairing. Initially, I grabbed the two example scripts from the PyBluez documentation:
Server:
# file: rfcomm-server.py
# auth: Albert Huang <albert#csail.mit.edu>
# desc: simple demonstration of a server application that uses RFCOMM sockets
#
# $Id: rfcomm-server.py 518 2007-08-10 07:20:07Z albert $
from bluetooth import *
server_sock=BluetoothSocket( RFCOMM )
server_sock.bind(("",PORT_ANY))
server_sock.listen(1)
port = server_sock.getsockname()[1]
uuid = "94f39d29-7d6d-437d-973b-fba39e49d4ee"
advertise_service( server_sock, "SampleServer",
service_id = uuid,
service_classes = [ uuid, SERIAL_PORT_CLASS ],
profiles = [ SERIAL_PORT_PROFILE ],
# protocols = [ OBEX_UUID ]
)
print "Waiting for connection on RFCOMM channel %d" % port
client_sock, client_info = server_sock.accept()
print "Accepted connection from ", client_info
try:
while True:
data = client_sock.recv(1024)
if len(data) == 0: break
print "received [%s]" % data
except IOError:
pass
print "disconnected"
client_sock.close()
server_sock.close()
print "all done"
Client:
# file: rfcomm-client.py
# auth: Albert Huang <albert#csail.mit.edu>
# desc: simple demonstration of a client application that uses RFCOMM sockets
# intended for use with rfcomm-server
#
# $Id: rfcomm-client.py 424 2006-08-24 03:35:54Z albert $
from bluetooth import *
import sys
addr = None
if len(sys.argv) < 2:
print "no device specified. Searching all nearby bluetooth devices for"
print "the SampleServer service"
else:
addr = sys.argv[1]
print "Searching for SampleServer on %s" % addr
# search for the SampleServer service
uuid = "94f39d29-7d6d-437d-973b-fba39e49d4ee"
service_matches = find_service( uuid = uuid, address = addr )
if len(service_matches) == 0:
print "couldn't find the SampleServer service =("
sys.exit(0)
first_match = service_matches[0]
port = first_match["port"]
name = first_match["name"]
host = first_match["host"]
print "connecting to \"%s\" on %s" % (name, host)
# Create the client socket
sock=BluetoothSocket( RFCOMM )
sock.connect((host, port))
print "connected. type stuff"
while True:
data = raw_input()
if len(data) == 0: break
sock.send(data)
sock.close()
When I ran the server script on Windows everything worked just how I had hoped - no pairing was necessary. At this stage everything was looking very promising.
However, I need the server process to run under Debian Squeeze. When I test on Debian the client connection is refused. In the syslog there are messages from bluetoothd for a failed link key request and PIN request.
Version information:
PyBluez 0.18
Python 2.6
Bluez 4.66
Bluetooth v2.0 hardware on both ends of the connection
This discussion seems to suggest that if I can adjust the security level on the server socket then pairing will be disabled and everything will just work as expected. It is not apparent to me how to do this with PyBluez though, or even if it is possible.
I have experimented with calls to setsockopt() using various BT_SECURITY* constants, as well as grabbing the last PyBluez and calling setl2capsecurity() but have not been able to make any progress.
Is this going to be achievable with PyBluez?
This turned out to be a problem with the Debian Squeeze bluez default configuration.
If anyone else hits this problem, disable the pnat plugin by editing /etc/bluetooth/main.conf:
DisablePlugins = pnat
Then restart bluetoothd.
$ sudo invoke-rc.d bluetooth restart
No changes were required to the PyBluez code.

Categories

Resources