Sending files over bluetooth using PyBluez and PyOBEX - python

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

Related

Can I send python script outputs to a Raspberry Pi over SSH/WiFi?

I'm putting a drone together and I have a Python script running on a Raspberry Pi taking Xbox controller inputs and turning them into a Python output I can use like:
if (event.code == 'ABS_Y'):
if event.state in range(25001,32768):
print("Full Throttle Reverse Left")
kit.motor1.throttle = -1
The controller however needs to be connected to the Raspberry Pi and that limits my range. Can I connect the controller to a laptop and send those outputs to the Raspberry Pi over a router to execute Python commands?
I'm new to programming as a whole and I'm certain there are smarter ways of doing this so any assistance or alternate suggestions are welcome.
I recommend using a socket for your application.
The client (running on the laptop) could take the xbox controller inputs and send it to the server (running on raspberry pi).
Here is a simple socket application:
Client:
import socket
ip = "192.168.xxx.yyy" # IP of Raspberry Pi
# connect to server
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((ip, 8080))
print("CLIENT: connected")
# send a message
msg = "I am CLIENT"
client.send(msg.encode())
# recive a message and print it
from_server = client.recv(4096).decode()
print("Recieved: " + from_server)
# exit
client.close()
Server:
import socket
ip = "192.168.xxx.yyy" # IP of Raspberry Pi
# start server
serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serv.bind((ip, 8080))
serv.listen(5)
print("SERVER: started")
while True:
# establish connection
conn, addr = serv.accept()
from_client = ''
print("SERVER: connection to Client established")
while True:
# receive data and print
data = conn.recv(4096).decode()
if not data: break
from_client += data
print("Recieved: " + from_client)
# send message back to client
msg = "I am SERVER"
conn.send(msg.encode())
# close connection and exit
conn.close()
break
More information can be found here.
Here's how to do it:
In the Raspberry Pi, make sure you have OpenSSH (you probably do, try running apt install openssh-server if you cannot connect), and you also need the OpenSSH client on your computer(the 'ssh' command).
First, let's look at your script. On your Python Script, you can write something like this to output JSON:
print(json.dumps(your message here....))
On your Raspberry Pi, find out your private IP. You can do something like:ifconfig | grep 192
On your computer, type:
ssh pi#<your private IP> 'python <your script path, example: /home/pi/Desktop/script.py>'
You may need to change pi to the username that you use on your Raspberry Pi.
The script will run on your Raspberry Pi, and you will get the JSON output on your computer! You can easily automate this using subprocess and json.loads . This way is also secure, because SSH uses encryption.

Writing an external program to interface with wpa_supplicant

I need to interact directly with wpa_supplicant from Python. As I understand it one can connect to wpa_supplicant using Unix sockets and wpa_supplicant control interface (https://w1.fi/wpa_supplicant/devel/ctrl_iface_page.html).
I wrote a simple program that sends a PING command:
import socket
CTRL_SOCKETS = "/home/victor/Research/wpa_supplicant_python/supplicant_conf"
INTERFACE = "wlx84c9b281aa80"
SOCKETFILE = "{}/{}".format(CTRL_SOCKETS, INTERFACE)
s = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
s.connect(SOCKETFILE)
s.send(b'PING')
while 1:
data = s.recv(1024)
if data:
print(repr(data))
But when I run it, wpa_supplicant reports an error:
wlx84c9b281aa80: ctrl_iface sendto failed: 107 - Transport endpoint is not connected
Could someone please provide an example, how you would do a 'scan' and then print 'scan_results'.
Apparently, the type of socket that wpa_supplicant uses (UNIX datagram) does not provide any way for the server to reply. There are a few ways to get around that. wpa_supplicant in particular seems to support replies through a separate socket (found at a path appended at the end of each message).
Weirdly enough, this seems to be a relatively common practice in Linux: /dev/log seems to work in the same way.
Here's a program that does what you asked for:
import socket, os
from time import sleep
def sendAndReceive(outmsg, csock, ssock_filename):
'''Sends outmsg to wpa_supplicant and returns the reply'''
# the return socket object can be used to send the data
# as long as the address is provided
csock.sendto(str.encode(outmsg), ssock_filename)
(bytes, address) = csock.recvfrom(4096)
inmsg = bytes.decode('utf-8')
return inmsg
wpasock_file = '/var/run/wpa_supplicant/wlp3s0'
retsock_file = '/tmp/return_socket'
if os.path.exists(retsock_file):
os.remove(retsock_file)
retsock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
retsock.bind(retsock_file)
replyToScan = sendAndReceive('SCAN', retsock, wpasock_file)
print(f'SCAN: {replyToScan}')
sleep(5)
replyToScanResults = sendAndReceive('SCAN_RESULTS', retsock, wpasock_file)
print(f'SCAN_RESULTS: {replyToScanResults}')
retsock.close()
os.remove(retsock_file)

Matlab Server with python client on raspberry pi BrokenPipeError: [Errno 32] Broken pipe

I am trying to gather data from sensors connected to a raspberry pi and send them over to my laptop for some processing. I have written a very basic matlab server (for on my laptop)
t = tcpip('127.0.0.1', 42069, 'NetworkRole', 'server');
fopen(t);
flag = true;
while flag
if t.BytesAvailable > 0
t.BytesAvailable
raw_data = fread(t, t.BytesAvailable);
data = typecast(uint8(raw_data), 'double');
current_x = data(1);
current_y = a.cell_size*a.rows - data(2);
current_th = -data(3);
flag = false;
end
end
.
.
.
fclose(t)
On my PI I have written the following class to handle sending the data over.
class LocalizationClient():
#TCP_IP = '127.0.0.1'
TCP_IP = '192.168.1.5'
TCP_PORT = 42069
BUFFER_SIZE = 1000
# MESSAGE = "Hello, World!"
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
def __init__(self):
self.s.connect((self.TCP_IP, self.TCP_PORT))
print("connected to server")
def sendData(self,MESSAGE):
try:
self.s.send(MESSAGE)
except BrokenPipeError as e:
print(e)
self.close()
raise RuntimeError()
In my driver code I create an object and try to send a message like so:
lo_c = lc.LocalizationClient()
lo_c.sendData(np.array([float(x), float(y), float(th)]))
.
.
.
for x in range(50):
measures = lidar.measures
measures = np.append([float(dx), float(dy), float(dth)], measures)
lo_c.sendData(measures)
time.sleep(.2)
All of this was working fine and dandy while I was just testing with loopback on my laptop, but when I tried to put it on the pi I get the following error on the python client side:
connected to server
[Errno 32] Broken pipe
Traceback (most recent call last):
File "/home/pi/Desktop/EXAMPLES/LocalizationClient.py", line 21, in sendData
self.s.send(MESSAGE)
BrokenPipeError: [Errno 32] Broken pipe
It seems that connecting still works but when I try to send to the server the client throws an error. The server seems fine and Im not trying to send any data back over to the client yet. I have been banging my head into this one for a while now and any help would be appreciated.
ps some details about the network setup if it helps, I have put the pi in ad-hoc mode with IP statically assigned as 192.168.1.1 and connected my macbook to the network it created. My Mac is assigned static IP 192.168.1.5.
So I figured out the issue. While I could see the port was open the way the matlab TCPIP object works is that it will silently refuse any connection that does not come from the IP passed into the constructor. So I was able to construct the object which would listen for a connection on the port. On the python side my client would see this "connect" but really the server was refusing the connection causing broken pipe. (this is also why it was working fine on local host but not remote)
Fix is easy just change:
t = tcpip('127.0.0.1', 42069, 'NetworkRole', 'server');
fopen(t);
to:
t = tcpip('0.0.0.0', 42069, 'NetworkRole', 'server');
fopen(t);
This will allow matlab server to accept a connection from any ip on LAN on specified port. Alternatively one could supply matlab server with clients IP to only accept connections from the one device but if IP is not static then it might change on you. Also is important to disable firewalls on devices.

testing client- server on the same computer

I am trying to test socket communication on my laptop using python. However, I'm not sure why the connection is not being established? I keep getting error that the target machine is actively refusing connection. I am trying to use the same computer to run both the client and the server portion. The server is running fine but the client is the one not connecting. I think I have the hostname wrong (127.0.0.1) but not sure what Im supposed to be using? I also tried changing the server hostname to (0.0.0.0) and the IPV4 address for the hostname the client was to connect to but that didn't work either. Any help would be appreciated!
My code(server portion):
import socket
comms_socket =socket.socket()
comms_socket.bind(('127.0.0.1', 50000))
comms_socket.listen(10)
connection, address = comms_socket.accept()
while True:
print(connection.recv(4096).decode("UTF-8"))
send_data = input("Reply: ")
connection.send(bytes(send_data, "UTF-8"))
Client portion:
import socket
comms_socket = socket.socket()
comms_socket.connect(('127.0.0.1',50000))
while True:
send_data = input("Message: ")
comms_socket.send(bytes(send_data, "UTF-8"))
print(comms_socket.recv(4096).decode("UTF-8"))
Your code won't work with python 2.* , because of the differences in input(), raw_input(), bytes, etc. in python 3.* vs python 2.* . You'd have to minimally make the following changes to get it working with python 2.*. Otherwise, use python 3 to run your code:
Server program:
import socket
comms_socket =socket.socket()
comms_socket.bind(('127.0.0.1', 7000))
comms_socket.listen(10)
connection, address = comms_socket.accept()
while True:
print(connection.recv(4096).decode("UTF-8"))
send_data = raw_input("Reply: ") # Use raw_input() instead of input()
connection.send(send_data.encode("UTF-8"))
Client program:
import socket
comms_socket = socket.socket()
comms_socket.connect(('127.0.0.1',7000))
while True:
send_data = raw_input("Message: ")
comms_socket.send(send_data.encode("UTF-8"))
print(comms_socket.recv(4096).decode("UTF-8"))
If you want to use bytes as intended in your specific usecase, you should use bytesarray instead in python 2.6 or higher. Check this: the bytes type in python 2.7 and PEP-358

Unable to telnet to Windows using socket module in python

Im using python3.3 version. I have Windows7 machine, I'm trying to write a program using socket module in python. I'm not to able get login prompt if I use socket module.
import socket
host = '10.155.208.33'
port= 23
s= socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host,port))
data=s.recv(1024)
print(data)
>>> b"\xff\xfd%\xff\xfb\x01\xff\xfb\x03\xff\xfd'\xff\xfd\x1f\xff\xfd\x00\xff\xfb\x00"
s.sendall(b'\xff\xfe\x01\xff\xfd\x03\xff\xfc\x18\xff\xfc\x1f') >>> Im not sure whether this correct IAC client reply
data =s.recv(1024)
print(data)
>>>b'' <<< server response is empty.
Im not familar with IAC commands. Can somebody point to correct handshake used for communicating between client and server?
I tried using telnetlib module for python3.3, module doesnt works properly on my windows machine.
Thanks,
Anand
You may safely respond negatively to each IAC negotiation request. That is, for each IAC-DO, reply IAC-WONT. For each IAC-WILL, reply IAC-DONT.
You may find this code helpful:
def read(s):
while True:
data = s.recv(10240)
for do in re.findall('\xff\xfd.', data): # IAC DO cmd
s.send('\xff\xfc'+do[2]) # IAC WONT cmd
for will in re.findall('\xff\xfb.', data): # IAC WILL cmd
s.send('\xff\xfe'+will[2]) # IAC DONT cmd
data = re.sub('\xff[\xfb-\xfe].', '', data)
if data != '':
return data

Categories

Resources