Tuesday, December 29, 2020

Raspberry Pi/Python as Bluetooth classic client, bi-direction communication with ESP32

Raspberry Pi/Python act as GUI Bluetooth classic client, using tkinter/pybluez:
Connect to bluetooth classic server with hard-coded MAC.
User enter text to sent on bottom Text Frame, send to server.
Display the data received from server on upper Text frame.

The server side, run on ESP32 (NodeMCU ESP-32S), with SPI ST7735 IPS screen. It echo back received data. ESP32 (Arduino framework) code: Arduino-er: ESP-32S as Bluetooth classic Server, bi-direction communication with Raspberry Pi/Python.

Python code, pySPPClient.py.

import sys
from tkinter import *
from bluetooth import *
from threading import Thread
import time

rqsStopBtHandler = False

buf_size = 255

def btHandler():
    global rqsStopBtHandler
    rqsStopBtHandler = False
    
    print("btHandler Started")
    
    #Set sock.settimeout(),
    #to prevent program blocked by sock.recv()
    #and cannot end btHandler
    sock.settimeout(1.0)
    while rqsStopBtHandler!=True:
        try:
            datarx = sock.recv(buf_size)
            datarxToStr = datarx.decode("utf-8")
            print(datarxToStr)
            textCenter.insert(INSERT, datarxToStr)
        except Exception:
            continue
        
    print("btHandler End")
    
def startBtHandler():
    btThread = Thread(target=btHandler)
    btThread.start()
    
def close_window():
    global rqsStopBtHandler
    rqsStopBtHandler = True
    sock.close()
    print("Socket closed")
    print("Window closed")
    root.destroy()

def cmdSend():
    stringSent = textBottom.get(1.0, END)
    print(stringSent)
    sock.send(stringSent)
    #sock.send("\n")
    print("- Sent")
    
#===============================================
#Prepare Bluetooth Classic
print("Python version: ")
print(sys.version)
print("tkinter version: ", TkVersion)
print("=============================")
print("Connect to ESP32 Bluetooth Classic SPP Server")
#addr = "24:0A:C4:E8:0F:9A"
addr = "3C:71:BF:0D:DD:6A"
print(addr)
service_matches = find_service( address = addr )

if len(service_matches) == 0:
    print("couldn't find the ESP32 Bluetooth Classic SPP 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))

# Create the client socket
sock=BluetoothSocket(RFCOMM)
sock.connect((host, port))

print("connected")

#===============================================
#Prepare GUI
root = Tk()
root.configure(bg="darkgray") 
root.wm_title("SPP Client")
root.protocol("WM_DELETE_WINDOW", close_window)

rootFrame = Frame(root)
rootFrame.pack()

labelTitle = Label(root,
                   text="helloraspberrypi.blogspot.com",
                   font=("Helvetica", 18),
                   fg="White", bg="darkgray")
labelTitle.pack()

frameCenter = Frame(root, bg="lightgray")
frameCenter.pack()

textCenter= Text(frameCenter, width=26, height=10, font=("Helvetica", 18))
textCenter.pack(padx=10,pady=5)

frameBottom = Frame(root, bg="gray")
frameBottom.pack(expand=True, fill='both')

textBottom = Text(frameBottom, width=26, height=10, font=("Helvetica", 18))
textBottom.insert(INSERT, "Enter text here")
textBottom.pack(padx=10,pady=5)

buttonSend = Button(frameBottom, text="Send", command=cmdSend)
buttonSend.pack(padx=10,pady=5)

startBtHandler()

root.mainloop()

print("--- bye ---")

Related:

Friday, December 25, 2020

Raspberry Pi/Python remote control ESP32/Servos via Bluetooth Classic

Last exercise show how Python (on Raspberry Pi) Bluetooth communicate with ESP32 SerialToSerialBT, using pybluez. This exercise extended to send simple single character command to ESP32 via Bluetooth Classic, to control remote servos; with GUI using Tkinter.


pyBTServoClient_20201226.py, for Python3.
import sys
from tkinter import *
from bluetooth import *

print("Python version: ")
print(sys.version)
print("tkinter version: ", TkVersion)
print("=============================");
print("Connect to ESP BT Servo Server")
addr = "24:0A:C4:E8:0F:9A"
print(addr)
service_matches = find_service( address = addr )

if len(service_matches) == 0:
    print("couldn't find the ESP32 BT Servo 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))

# Create the client socket
sock=BluetoothSocket(RFCOMM)
sock.connect((host, port))

print("connected")

def close_window():
    sock.close()
    print("Socket closed")
    print("Window closed")
    root.destroy()

#prepare GUI
root = Tk()
root.geometry("380x200")
root.configure(bg="lightgray") 
root.wm_title("Bluetooth Servo Client")
root.protocol("WM_DELETE_WINDOW", close_window)

CMD_ORG = 'O'
CMD_XDEC = 'A'
CMD_XDEC10 = 'B'
CMD_XINC = 'C'
CMD_XINC10 = 'D'
CMD_YDEC = 'E'
CMD_YDEC10 = 'F'
CMD_YINC = 'G'
CMD_YINC10 = 'H'

def cmdO():
    sock.send(CMD_ORG)
    print("0, 0")

def cmdXdec():
    sock.send(CMD_XDEC)
    print("X-")
    
def cmdXdec10():
    sock.send(CMD_XDEC10)
    print("X-10")

def cmdXinc():
    sock.send(CMD_XINC)
    print("X+")
    
def cmdXinc10():
    sock.send(CMD_XINC10)
    print("X+10")
    
def cmdYdec():
    sock.send(CMD_YDEC)
    print("Y-")
    
def cmdYdec10():
    sock.send(CMD_YDEC10)
    print("Y-10")

def cmdYinc():
    sock.send(CMD_YINC)
    print("Y+")
    
def cmdYinc10():
    sock.send(CMD_YINC10)
    print("Y+10")


ButtonO = Button(root, text="0", command = cmdO, width=6)
ButtonXdec = Button(root, text="X-", command = cmdXdec, width=6)
ButtonXinc = Button(root, text="X+", command = cmdXinc, width=6)
ButtonYdec = Button(root, text="Y-", command = cmdYdec, width=6)
ButtonYinc = Button(root, text="Y+", command = cmdYinc, width=6)
ButtonXdec10 = Button(root, text="X-10", command = cmdXdec10, width=6)
ButtonXinc10 = Button(root, text="X+10", command = cmdXinc10, width=6)
ButtonYdec10 = Button(root, text="Y-10", command = cmdYdec10, width=6)
ButtonYinc10 = Button(root, text="Y+10", command = cmdYinc10, width=6)

ButtonO.grid(row=2, column=2)
ButtonXdec.grid(row=2, column=1)
ButtonXinc.grid(row=2, column=3)
ButtonYdec.grid(row=3, column=2)
ButtonYinc.grid(row=1, column=2)
ButtonXdec10.grid(row=2, column=0)
ButtonXinc10.grid(row=2, column=4)
ButtonYdec10.grid(row=4, column=2)
ButtonYinc10.grid(row=0, column=2)

root.mainloop()

print("\n--- bye ---\n")
The ESP32 code (run on Arduino framework) is in my another blog's post: Arduino-er - ESP32 receive Bluetooth Classic command from Raspberry Pi/Python, to control Servos.

Next:

Saturday, December 19, 2020

Python (on Raspberry Pi) Bluetooth communicate with ESP32 SerialToSerialBT, using pybluez

It's a simple Python example using pybluez extension module, run on Raspberry Pi 4/Raspberry Pi OS, to communicate with ESP32 SerialToSerialBT example.

pybluez (or https://github.com/pybluez/pybluez)is a Python extension module allowing access to system Bluetooth resources.

Install pybluez for Python3, enter the command in Terminal:

$ sudo pip3 install pybluez

Copy and modify pybluez/examples/simple/rfcomm-client.py in Raspberry Pi Thonny.

It's my modified version, pyBTSimpleClient.py

from bluetooth import *

def input_and_send():
    print("\nType something\n")
    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)
            sock.send(data)
            
#MAC address of ESP32
addr = "24:0A:C4:E8:0F:9A"
#uuid = "94f39d29-7d6d-437d-973b-fba39e49d4ee"
#service_matches = find_service( uuid = uuid, address = addr )
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))

# Create the client socket
sock=BluetoothSocket(RFCOMM)
sock.connect((host, port))

print("connected")

#input_and_send()
rx_and_echo()

sock.close()
print("\n--- bye ---\n")


How it run on Raspberry Pi 4/Raspberry Pi OS, communicate with ESP32 (ESP32-DevKitC V4) SerialToSerialBT example. The code in ESP32 side is in my another blog Arduino-er: ESP32 Bluetooth serial example.
 

Next:


ImportError: libbluetooth.so.3


If you reported with error of:
ImportError: libbluetooth.so.3: cannot open shared object file: No such file or directory

Install required library by entering the command in Terminal:
$ sudo apt install bluetooth bluez libbluetooth-dev


Wednesday, December 9, 2020

Install GIMP on Raspberry Pi OS

GIMP is a cross-platform image editor available for GNU/Linux, OS X, Windows and more operating systems.

To install GIMP on Raspberry Pi OS, simple enter the command in Terminal:

$ sudo apt-get install gimp


After installed, it's listed in System MENU > Graphics > GNU Image Manipulation Program




Display system info with neofetch

neofetch is a Terminal-based tools to displays information about your operating system, software and hardware in visual way.

To install neofetch to Raspberry Pi OS, enter the command:

$ sudo apt install neofetch



Tuesday, December 8, 2020

Raspberry Pi OS now support FAN control

With Raspberry Pi OS released December 2020, fan control is itroduced.


In Raspberry Pi Configuration, select Performance tab, there is a option of FAN. you can select the GPIO pin to which it is connected and set the temperature at which it turns on and off.  To control the new Raspberry Pi Case Fan.



Friday, December 4, 2020

Test network speed between Raspberry Pi using iPerf3

iPerf3 is a tool for active measurements of the maximum achievable bandwidth on IP networks. It supports tuning of various parameters related to timing, buffers and protocols (TCP, UDP, SCTP with IPv4 and IPv6). For each test it reports the bandwidth, loss, and other parameters.

This post show how to run iPerf3 on two Raspberry Pi to check the network speed between.

On both Raspberry Pi, install iPerf3 by entering command in Terminal:

$ sudo apt install iperf3
After installed.

In the service side, enter the command:
$ iperf3 -s
In the client side, enter command:
$ iperf3 -c <server ip>




Thursday, December 3, 2020

Raspberry Pi link to Bluetooth 5.0 headphones, using Blueman

Blueman is a lightweight, easy to use, Python based, and GPL licensed, GTK+ Bluetooth Manager.

Blueman is designed to provide a simple yet effective means for controlling the BlueZ API and simplifying Bluetooth tasks, such as:

  • Connecting to 3G/EDGE/GPRS via dial-up
  • Connecting to / Creating Bluetooth networks
  • Connecting to input devices
  • Connecting to audio devices
  • Sending / Receiving files via OBEX
  • Pairing

To install Blueman on Raspberry Pi/Raspberry Pi OS, enter the command in Terminal:

$ sudo apt install bluetooth pi-bluetooth bluez blueman

After installed, reboot.

$ sudo reboot

After reboot, it's a shortcut on menu bar, and on MENU > Preferences > Bluetooth Manager.


This video show how to pair Bluetooth 5.0 headphones to Raspberry Pi/Raspberry Pi OS (32 bit) using Blueman. The devices tested are JBL TUNE 215BT + Raspberry Pi 4B/4 inch HDMI IPS Touch Display.



Tuesday, December 1, 2020

Check installed package in Raspberry Pi OS, using dpkg/dpkg-query

To list all installed packages, enter the command in Terminal:

$ dpkg -l

or

$ dpkg-query -l

To list about a specified package:

$ dpkg -l package-name-pattern

or

$ dpkg-query -l package-name-pattern



dpkg is a tool to install, build, remove and manage Debian packages. It can also be used as a front-end to dpkg-deb and dpkg-query. 

dpkg-query is a tool to show information about packages listed in the dpkg database.

With command "-l [package-name-pattern...]" list all known packages matching one or more patterns. If no package-name-pattern is given, list all packages in /usr/local/var/lib/dpkg/status, excluding the ones marked as not-installed (i.e.  those which have been previously purged).

The first three columns of the output show the desired action, the package status, and errors, in that order.

              Desired action:
                u = Unknown
                i = Install
                h = Hold
                r = Remove
                p = Purge

              Package status:
                n = Not-installed
                c = Config-files
                H = Half-installed
                U = Unpacked
                F = Half-configured
                W = Triggers-awaiting
                t = Triggers-pending
                i = Installed

              Error flags:
                <empty> = (none)
                R = Reinst-required