I put together a Kivy App that gets the coordinates from a user touch and sends them over bluetooth to an arduino
I am following the steps on how to handle bluetooth on android listed in the link below: https://developer.android.com/guide/topics/connectivity/bluetooth#ManageAConnection
Fct ConnectBluetooth() is called when pressing a "connect to bluetooth" button. This is where I look for the arduino HC-05 bluetooth receiver and setup a socket as well as the input and output streams.
I then use the fct SendCoordinates() to use the output stream and send data over bluetooth. However, when this function is called, I get the following error: error while sending bluetooth data on Android
I thought the argument you pass over to the write() function of the outputstream has to be a byte array. I guess its not. Does anyone know what I have to pass instead? I am doing something wrong while converting the string to byte array?( "ByteString = bytes(StrPositionData,'utf-8')")
While I'm on the subject, how does one use the inPutStream to read bluetooth data from my Kivy on android? The guide states read(byte[]) "should be called in a separate thread" because it blocks until it receives data. How does one add this separate thread in python?
Code is listed below:
main.py:
import kivy
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.textinput import TextInput
from kivy.uix.button import Button
from kivy.uix.widget import Widget
from kivy.uix.anchorlayout import AnchorLayout
#from subprocess import Popen,PIPE
from kivy.core.window import Window
from kivy.clock import Clock
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.properties import StringProperty, ObjectProperty
from kivy.uix.image import Image
from kivy.utils import get_color_from_hex
from kivy.graphics import Color, Rectangle
from kivy.lang import Builder
from kivy.base import runTouchApp
from kivy.core.text import LabelBase
from jnius import autoclass
UUID = autoclass('java.util.UUID')
LabelBase.register(name="Nobile",
fn_bolditalic="fonts/Nobile/Nobile-BoldItalic.ttf",
fn_regular="fonts/Nobile/Nobile-Regular.ttf")
class HomeScreen(Screen):
mvoltage = ObjectProperty(None)
print('Start')
port = "COM4"
BluetoothAdapter = autoclass('android.bluetooth.BluetoothAdapter')
#init input & output streams
SendSerialData = None
ReceiveSerialData = None
#flag to signal initialized bluetooth
BluetoothInit = 0
def __init__(self, **kwargs):
super(HomeScreen, self).__init__(**kwargs)
#Clock.schedule_interval(self.ReceiveSerialData, 2)
try:
print("Looking for Bluetooth On Windows")
#bluetooth_device = serial.Serial(self.port, 9600, timeout=1)
print("Connected to HC-05")
except Exception as e:
print("Looking for Bluetooth On Android")
def SendCoordinates(self, XCoordinate, YCoordinate):
#conver positionData to string
StrPositionData = str(XCoordinate)+','+' '+str(YCoordinate)
ByteString = bytes(StrPositionData,'utf-8')
self.SendSerialData.write('{}\n'.format(ByteString))
self.SendSerialData.flush()
def on_touch_down(self, touch):
if self.BluetoothInit == 1:
self.SendCoordinates(touch.sx, touch.sy)
return super(HomeScreen,self).on_touch_down(touch)
def on_touch_up(self,touch):
try:
self.bluetooth_device.write(b"STOP")
print('STOP'.encode())
except:
pass
def on_touch_move(self, touch):
pass
def ReceiveSerialData(self,dt):
Serial_Data=[124]
ReceivedBytes = 0
try:
Serial_Data = self.bluetooth_device.readline().decode()
except:
if self.BluetoothInit == 1:
ReceivedBytes = self.ReceiveSerialData.read(Serial_Data)
print(Serial_Data)
#Number = int(Serial_Data)
#if Number >= 10000:
#NR = Serial_Data[0:2]
#Decimals = Serial_Data[2:4]
#else:
#NR = Serial_Data[0]
#Decimals = Serial_Data[1:3]
#self.mvoltage.text = NR + '.' + Decimals + ' ' + 'Volts'
def ConnectBluetooth(self):
#try to connect on windows
try:
print("Connecting to Bluetooth" )
self.port = "COM4"
self.bluetooth_device = serial.Serial(self.port, 9600, timeout=1)
print("Connected to HC-05")
#windows failed, try connecting on Android
except Exception as e1:
paired_devices = self.BluetoothAdapter.getDefaultAdapter().getBondedDevices().toArray()
socket = None
for device in paired_devices:
if device.getName() == 'HC-05':
socket = device.createRfcommSocketToServiceRecord(
UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"))
self.ReceiveSerialData = socket.getInputStream()
self.SendSerialData = socket.getOutputStream()
break
socket.connect()
#signal that bluetooth connection established
self.BluetoothInit = 1
except Exception as e2:
raise Exception('Cant Connect Bluetooth on Windows or Android')
class SecondScreen(Screen):
pass
class WindowManager(ScreenManager):
pass
kv=Builder.load_file('Crane.kv')
class MainApp(App):
def build(self):
return kv
if __name__ == "__main__":
TestApp = MainApp()
TestApp.run()
.kv file:
#:import utils kivy.utils
WindowManager:
HomeScreen:
SecondScreen:
<HomeScreen>:
name: "Crane App"
mvoltage:MotorVoltage
FloatLayout:
canvas.before:
Color:
rgb: utils.get_color_from_hex("#ffffff")
Rectangle:
size: self.size
pos: self.pos
GridLayout:
canvas.before:
Color:
rgb: utils.get_color_from_hex("#ffffff")
Rectangle:
size: self.size
pos: self.pos
rows: 1
cols: 3
padding:10
FloatLayout:
GridLayout:
canvas.before:
Color:
rgb: utils.get_color_from_hex("#ffffff")
Rectangle:
size: self.size
pos: self.pos
rows: 2
cols: 1
spacing:5
padding:5
pos_hint:{"top": 1, "left": 1}
Image:
source: "icons/extend_boom.PNG"
allow_stretch: True
keep_ratio: False
Image:
source: "icons/lift_boom.PNG"
allow_stretch: True
keep_ratio: False
AnchorLayout:
id:Anchor_Left
pos_hint:{"left": 0.60, "top": 1}
size_hint: 1, 1
GridLayout:
id:LeftButtons
rows:2
Button:
id:extend_boom
background_color:(255,255,255,0)
Button:
id:lift_boom
background_color:(255,255,255,0)
GridLayout:
canvas.before:
Color:
rgb: utils.get_color_from_hex("#ffff00")
Rectangle:
size: self.size
pos: self.pos
rows: 5
cols: 1
padding:5
spacing:5
size_hint: .54, 1
Label:
text:"Motor Voltage"
color: 0,0,0,1
font_name:"Nobile"
bold:True
TextInput:
id:MotorVoltage
Label:
text:"Controller Voltage"
color: 0,0,0,1
font_name:"Nobile"
TextInput:
id: ControllerVoltage
Button:
id:connect_bluetooth
text:"Connect to Bluetooth"
background_color:(0,0,0,0.9)
on_press:
root.ConnectBluetooth()
FloatLayout:
GridLayout:
canvas.before:
Color:
rgb: utils.get_color_from_hex("#ffffff")
Rectangle:
size: self.size
pos: self.pos
rows: 2
cols: 1
spacing:5
padding:5
pos_hint:{"top": 1, "right": 1}
Image:
source: "icons/lift_hook.PNG"
allow_stretch: True
keep_ratio: False
Image:
source: "icons/rotate.PNG"
allow_stretch: True
keep_ratio: False
AnchorLayout:
id:Anchor_Right
pos_hint:{"right": 1, "top": 1}
size_hint: 1, 1
GridLayout:
id:LeftButtons
rows:2
Button:
id:lift_hook
background_color:(255,255,255,0)
Button:
id:rotate
background_color:(255,255,255,0)
<SecondScreen>:
name: "Passenger Contact Info"
Button:
text: "Go Back"
on_press:
app.root.current="Bus Map"
root.manager.transition.direction="left"
Thanks in advance for your help.
Alex