Hope you´re fine! and really hope you can help me on this.
I have 2 ESP32 and 1 raspberry. Each ESP32 has a button, when I press any of the buttons a message must be sent over bluetooth of each ESP32.
ESP32_1 MESSAGE: "1L 100 100 200 200"
ESP32_2 MESSAGE: "2R 100 100 200 200"
I could connect ESP32 and raspberry over bluetooth successfully using the following command in 2 different terminals:
sudo rfcomm connect 1 XX:XX:XX:XX:XX (MAC1)
sudo rfcomm connect 2 XX:XX:XX:XX:XX (MAC2)
What I need is that if I press button_1 of ESP32_1 the message 1 must be received in raspberry. Otherwise, if I press button_2 of ESP32_2 the message 2 must be received and print in the raspberry.
The issue is that when I press button_2 dont send nothing and when I press button_1 after that, is sending information of button_2 + button_1, it seems like the port is waiting for receive the info in the other one.
Here my Python code for Raspberry:
#! /usr/bin/python
import serial
import time
Incoming_Data1 = ""
Incoming_Data2 = ""
bluetoothSerial1 = serial.Serial("/dev/rfcomm1", baudrate =115200) #Connecting to source 1
bluetoothSerial2 = serial.Serial("/dev/rfcomm2", baudrate =115200) #Connecting to source 1
print("Bluetooth Connected GBF")
def Flush_all():
bluetoothSerial1.flush()
bluetoothSerial2.flush()
while 1:
try:
Flush_all()
Incoming_Data1 = bluetoothSerial1.readline()
print(Incoming_Data1)
Flush_all()
except:
Flush_all()
try:
Flush_all()
Incoming_Data2 = bluetoothSerial2.readline()
print(Incoming_Data2)
Flush_all()
except:
Flush_all()
Thanks in advance!
It would be best to avoid using rfcomm as it was deprecated back in 2017
As outlined in http://blog.kevindoran.co/bluetooth-programming-with-python-3/, a Serial Port Profile (SPP) Bluetooth client connection can be done with Python3 standard socket library (after doing the pairing in bluetoothctl).
The example in Kevin's blog could be extended to work for connecting to two devices. Maybe something like:
import socket
serverMACAddress1 = 'XX:XX:XX:XX:XX:XX'
serverMACAddress2 = 'XX:XX:XX:XX:XX:XX'
port = 1 # Needs to match value used on the device you are connecting to
SIZE = 1024
s1 = socket.socket(socket.AF_BLUETOOTH, socket.SOCK_STREAM, socket.BTPROTO_RFCOMM)
s2 = socket.socket(socket.AF_BLUETOOTH, socket.SOCK_STREAM, socket.BTPROTO_RFCOMM)
s1.connect((serverMACAddress1, port))
s2.connect((serverMACAddress2, port))
while True:
data = s1.recv(size)
if data:
print(data)
data = s2.recv(size)
if data:
print(data)
s1.close()
s2.close()
There is also the Bluedot library that helps to abstract some of the detail away:
https://www.stuffaboutcode.com/2017/07/python-bluetooth-rfcomm-client-server.html
Related
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.
I want to set up serial Bluetooth communication between a Raspberry Pi 3 with integrated Bluetooth module and a Windows 10 machine. The raspi is the server and runs a python script, that handles the connection and the data transmission. I have set it all up, following several tutorials in the internet and its working really good on the server side. I have tested the server with a serial terminal on my android phone and it was working as expected: All the messages were transferred correctly and it stayed connected as long as i wanted. Testing with my windows machine, on the other hand, caused a lot of problems. I have solved most of them and now i can connect my windows machine, over a serial terminal, to the raspi. My problem now is, that, after a short while, the connection dies, usually after 10 to 40 seconds, and i could not find a fix for that. The error message on windows is: cannot open COM4 and the error message on the raspi is: bluetooth.btcommon.BluetoothError: [Errno 110] Connection timed out.
Here is my python script, id that is actually the problem:
import serial, bluetooth, subprocess, select
serialPort0 = serial.Serial(
port = '/dev/serial0',
baudrate = 115200,
parity = serial.PARITY_NONE,
stopbits = serial.STOPBITS_ONE,
bytesize = serial.EIGHTBITS,
timeout = 1
)
server_sock = bluetooth.BluetoothSocket(bluetooth.RFCOMM)
server_sock.bind(("", bluetooth.PORT_ANY))
server_sock.listen(1)
port = server_sock.getsockname()
uuid = "94f39d29-7d6d-437d-973b-fba39e49d4ee"
bluetooth.advertise_service(server_sock, "bluetoth_server", service_id=uuid,
service_classes=[uuid, bluetooth.SERIAL_PORT_CLASS],
profiles=[bluetooth.SERIAL_PORT_PROFILE],
# protocols=[bluetooth.OBEX_UUID]
)
print("Waiting for connection on RFCOMM channel", port[1], ", addr", port[0])
client_sock, client_info = server_sock.accept()
print("Accepted connection from", client_info)
client_sock.setblocking(0)
while True:
if not serialPort0.isOpen:
raise Exception("Serial port closed unexpected")
break
ready = select.select([client_sock], [], [], 0.5)
if ready[0]:
blu_data = client_sock.recv(4096)
if not blu_data:
break
serialPort0.write(blu_data)
ser_data = serialPort0.readline().decode("utf-8")
client_sock.send(ser_data)
client_sock.close()
server_sock.close()
It reads data from a serial port and from a serial Bluetooth port and sends it to the other one respectively.
I am at a point, where i don't know what else to try and I would really appreciate some help. Thank you in advance.
Your description related to timeout would be pointed to
/etc/bluetooth/main.conf
Bluetooth configuration file.
You will need to uncomment the pairabletimeout=0 that will prevent the timeout problems.
You may want to see Raspberry Bluetooth configuration (recent answer) for details.
Bluetooth Serial Configuration
I am currently building an automated trash bin using Raspberry Pi 3 B+ with Android application support where I would use a servo motor as an actuator for the lid and the Android application as a form of wireless remote control. Everything went on smoothly until I've encountered a problem that whenever I attempt to press a button on my Android application, the Python shell program has errors during testing. I've used a reference video (https://www.youtube.com/watch?v=t8THp3mhbdA&t=1s) and followed everything thoroughly until I've hit this roadblock.
The results to me that keeps appearing are:
Waiting for connection
...connected from :
Where the supposed result, according to the reference video, is:
Waiting for connection
...connected from : ('192.168.1.70', 11937)
Increase: 2.5
As you can see, the IP address, the port, and 'Increase' text doesn't appear, meaning there is something wrong with the code.
According to some comments that was made by the people who watched the video, this code is outdated, using Python 2, and the latest version we have now is Python 3, and that we need to use a ".encode()" line in a condition. However, as someone who is still new to Python, I'm afraid that I still don't have the knowledge to apply this on the code.
Here is the code that was used in the video:
import Servomotor
from socket import *
from time import ctime
import RPi.GPIO as GPIO
Servomotor.setup()
ctrCmd = ['Up','Down']
HOST = ''
PORT = 21567
BUFSIZE = 1024
ADDR = (HOST,PORT)
tcpSerSock = socket(AF_INET, SOCK_STREAM)
tcpSerSock.bind(ADDR)
tcpSerSock.listen(5)
while True:
print 'Waiting for connection'
tcpCliSock,addr = tcpSerSock.accept()
print '...connected from :', addr
try:
while True:
data = ''
data = tcpCliSock.recv(BUFSIZE)
if not data:
break
if data == ctrCmd[0]:
Servomotor.ServoUp()
print 'Increase: ',Servomotor.cur_X
if data == ctrCmd[1]:
Servomotor.ServoDown()
print 'Decrease: ',Servomotor.cur_X
except KeyboardInterrupt:
Servomotor.close()
GPIO.cleanup()
tcpSerSock.close();
I have already changed the text strings that used the ' ' format into the (" ") format since it also produced some errors in the code which I corrected immediately.
Any help will be greatly appreciated and thank you in advance!
Here's a Python3 version, edited a tiny bit for better clarity and good practice:
import Servomotor
import RPi.GPIO as GPIO
import socket
# Setup the motor
Servomotor.setup()
# Declare the host address constant - this will be used to connect to Raspberry Pi
# First values is IP - here localhost, second value is the port
HOST_ADDRESS = ('0.0.0.0', 21567)
# Declare the buffer constant to control receiving the data
BUFFER_SIZE = 4096
# Declare possible commands
commands = 'Up', 'Down'
# Create a socket (pair of IP and port) object and bind it to the Raspberry Pi address
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(HOST_ADDRESS)
# Set the socket to listen to an incoming connection (1 at a time)
server_socket.listen(1)
# Never stop the server once it's running
while True:
# Inform that the server is waiting for a connection
print("Waiting for connection to the following address: {}...".format(HOST_ADDRESS))
# Perform a blocking accept operation to wait for a client connection
client_socket, client_address = server_socket.accept()
# Inform that the client is connected
print("Client with an address {} connected".format(client_address))
# Keep exchanging data
while True:
try:
# Receive the data (blocking receive)
data = client_socket.recv(BUFFER_SIZE)
# If 0-byte was received, close the connection
if not data:
break
# Attempt to decode the data received (decode bytes into utf-8 formatted string)
try:
data = data.decode("utf-8").strip()
except UnicodeDecodeError:
# Ignore data that is not unicode-encoded
data = None
# At this stage data is correctly received and formatted, so check if a command was received
if data == commands[0]:
Servomotor.ServoUp()
print("Increase: {}".format(Servomotor.cur_X))
elif data == commands[1]:
Servomotor.ServoDown()
print("Decrease: {}".format(Servomotor.cur_X))
elif data:
print("Received invalid data: {}".format(data))
# Handle possible errors
except ConnectionResetError:
break
except ConnectionAbortedError:
break
except KeyboardInterrupt:
break
# Cleanup
Servomotor.close()
GPIO.cleanup()
client_socket.close()
# Inform that the connection is closed
print("Client with an address {} disconnected.".format(client_address))
To show you the code in action, I have hosted a local server on my machine and connected to it using Putty. Here are the commands I have entered:
Here is the output of the server (I have swapped the Servo-related functions to print statements):
Waiting for connection to the following address: ('0.0.0.0', 21567)...
Client with an address ('127.0.0.1', 61563) connected.
Received invalid data: Hello
Received invalid data: Let's try a command next
Running ServoUp
Increase: 2.5
Running ServoDown
Decrease: 2.5
Received invalid data: Nice!
Client with an address ('127.0.0.1', 61563) disconnected.
Waiting for connection to the following address: ('0.0.0.0', 21567)...
I have two Xbee Pro 900's, each attached to a Raspberry Pi. Both are updated to version 1061 and are set to API Enable with escapes. They also have the same Modem VID of 7FFF. Both Pi's have PySerial and the python-xbee library installed.
Xbee 1(Receiver) has a serial number of 0013A200409A1BB8
Xbee 2(Sender) has a serial number of 0013A200709A1BE9
I've included my code below, which is just sample code I've found online. My issue is that I'm not receiving anything on the appropriate Xbee. I have absolutely no idea what is wrong, I've triple checked the destination address, and both of the Xbee's configuration settings.
Xbee 2 Code(Sender):
#! /usr/bin/python
import time
from xbee import XBee
import serial
PORT = '/dev/ttyUSB0'
BAUD_RATE = 9600
# Open serial port
ser = serial.Serial(PORT, BAUD_RATE)
# Create API object
xbee = XBee(ser,escaped=True)
import pprint
pprint.pprint(xbee.api_commands)
DEST_ADDR_LONG = "\x00\x13\xA2\x00\x40\x9A\x1B\xB8"
# Continuously read and print packets
while True:
try:
print "send data"
xbee.tx_long_addr(frame='0x1', dest_addr=DEST_ADDR_LONG, data='AB')
time.sleep(1)
except KeyboardInterrupt:
break
ser.close()
Xbee 1 Code(Receiver):
#! /usr/bin/python
from xbee import XBee
import serial
PORT = '/dev/ttyUSB0'
BAUD_RATE = 9600
# Open serial port
ser = serial.Serial(PORT, BAUD_RATE)
# Create API object
xbee = XBee(ser,escaped=True)
# Continuously read and print packets
while True:
try:
print "waiting"
response = xbee.wait_read_frame()
print response
except KeyboardInterrupt:
break
ser.close()
When both programs are running, the Tx light on the sending Xbee blinks, but I receive nothing on the receiving Xbee. Is there something I'm missing? Thanks for your time!
Are you using XBee or XBeePro? I had the same problem and this post helped me a lot.
Try to modify the Receiver Code the following way:
import config
import serial
import time
from xbee import ZigBee
def toHex(s):
lst = []
for ch in s:
hv = hex(ord(ch)).replace('0x', '')
if len(hv) == 1:
hv = '0'+hv
hv = '0x' + hv
lst.append(hv)
def decodeReceivedFrame(data):
source_addr_long = toHex(data['source_addr_long'])
source_addr = toHex(data['source_addr'])
id = data['id']
samples = data['samples']
options = toHex(data['options'])
return [source_addr_long, source_addr, id, samples]
PORT = '/dev/ttyUSB0'
BAUD_RATE = 9600
# Open serial port
ser = serial.Serial(PORT, BAUD_RATE)
zb = ZigBee(ser, escaped = True)
while True:
try:
data = zb.wait_read_frame()
decodedData = decodeReceivedFrame(data)
print decodedData
except KeyboardInterrupt:
break
In my case the code above outputs the following:
[['0x00', '0x13', '0xa2', '0x00', '0x40', '0x9b', '0xaf', '0x4e'], ['0x68', '0x3f'], 'rx_io_data_long_addr', [{'adc-0': 524}]]
Here I shared configuration settings for Controller Node (compatible with X-CTU)
Are you sure the XBee modules are in escaped API mode (ATAP=2)? And 9600 baud?
Can you enable a mode in python-xbee to dump all characters in and out?
Have you confirmed the serial wiring is correct? (I see you're using USB, so that's not an issue.)
If you don't have hardware flow control hooked up, make sure the XBee modules have ATD6=0 and ATD7=0 set (disable RTS and CTS) and that python-xbee isn't expecting handshaking.
If you do have hardware flow control configured on the XBee, make sure you've told python-xbee to use it.
Can you use minicom or another serial terminal on the RaspPi to confirm that serial is working? Use minicom on the receiving end to see if you're getting anything at all?
Can you try sending and receiving with the radios connected to a PC instead of the Pi? Sending from the PC to the Pi, or vice-versa?
i tried to do client and server and look what i do
#Server
import socket
Host=''
Port=305
OK=socket.socket()
OK.bind((Host,Port))
OK.listn(1)
OK.accept()
and another one for client
#Client
impot socket
Host='192.168.1.4'
Port=305
OK=socket.socket()
OK.connect((Host,Port))
First thing : for now every thing is ok but i want when client connect to server :
server print "Hello Admin" in client screen
second thing : i want make like input command ! like
COM=raw_input('enter you command system:')
then client enter dir for example then server print the result in client screen
Look here, this is a simple echo server written in Python.
http://ilab.cs.byu.edu/python/socket/echoserver.html
When you create a connection, the story isn't over. Now it's time to send data over the connection. Create a simple "protocol" (*) and use it to transfer data from client to server and/or back. One simple example is a textual protocol of commands separated by newlines - this is similar to what HTTP does.
(*) Protocol: an agreement between two parties on the format of their communication.
I think you might want to do something like this:
client, addr = OK.accept()
client.send("Hello Admin")
And then use
data = client.recv(1024)
to get data from the client.
If you want to get command input from the client, you just need to execute the commands the client sends and send the output back back to the client.
from commands import getoutput
client.send(getoutput(client.recv(1024)))
Thats about the easiest solution possible.
For Client:
import os
import sys
impot socket
Host=raw_input ("Please enter ip : ")
Port=raw_input ("please Enter port :")
OK=socket.socket()
OK.connect((Host,Port))
print " Enter Command")
cmd = raw_input()
os.system(cmd)
I think that your codes has an issue:
you seem to have OK = socket.socket(), but I think it should be:
OK = socket.socket(socket.AF_INET, socket.STREAM), which would help if your making a connection. And your server has a problem: OK.listn(1) should be OK.listen(1). And, don't forget about send() and recv().
#Client
import socket
Host='192.168.1.4'
Port=305
OK=socket.socket(socket.AF_INET, socket.STREAM)
OK.connect((Host,Port))
while True:
com = raw_input("Enter your command: ")
OK.send(com)
data = OK.recv(5000) #Change the buffer if you need to, I have it setup to run 5000
print "Received:\n" + data
which should work for the client
#Server
import socket
import os
Host=''
Port=305
OK=socket.socket(socket.AF_INET, socket.STREAM)
OK.bind((Host,Port))
OK.listen(1)
conn, addr = OK.accept()
while True:
data = conn.recv(2048) #Change the buffer if needed
if data == "":
break
r = os.system(data)
conn.send(str(r)) #Note this will send 0 or 1, 0 = ran, 1 = error
Note: These fixes would work for Windows, I don't know about Unix systems.*