I'm trying to write a Python script to retrieve audio data from my IPhone to my Raspberry Pi over bluetooth. Currently, I'm able to get audio to come out of my Pi's speakers just by navigating to Settings > Bluetooth on my phone and selecting the Pi. (I paired it earlier). I've specified the Pi device type as Car Stereo, because I'm interested in later using an AVRCP type connection to retrieve metadata for the songs I'm playing.
I've been using PyBluez to retrieve a list of available bluetooth services with my phone. The code returns a list of dictionaries containing the service classes, profiles, name, description, provider, service id, protocol, port and host for each service, in the following format.
{'service-classes': ['110A'], 'profiles': [('110D', 259)], 'name': 'Audio Source', 'description': None, 'provider': None, 'service-id': None, 'protocol': 'RFCOMM', 'port': 13, 'host': 'FF:FF:FF:FF:FF:FF'}
Unfortunately, that's as far as my code gets. I've set it up to continuously request data, but after printing the available services the program ceases to log anything. I've tried the code with most of the available services, including 'Audio Source', 'Wireless iAP', 'Wireless iAp v2', 'Phonebook' and two instances of 'AVRCP Device'.
Below is my code. It's important to note that it only works if you have your phone open to Settings > Bluetooth, which is evidently the IPhone equivalent of entering into pairing mode. Thanks in advance!
import bluetooth as bt
from bluetooth import BluetoothSocket
if __name__ == "__main__":
services = bt.find_service()
print(sep='\n', *services)
for service in services:
if service['name'] == 'Audio Source':
socket = BluetoothSocket()
socket.bind((service['host'], service['port']))
print('\nListening...')
while True:
print(socket.recv(1024))
I've spent a lot of time on this project, and have found that while guidance for this kind of task is available out there, it can be hard to cross the barrier between useless fodder and helpful information. Below I'll detail the way I solved my most important problems, as well as deliver some quick pointers as to useful functionalities.
After receiving a helpful comment, I moved away from PyBluez. Turns out it's not useful for the streaming of audio data. Instead, I realised that because the Raspberry Pi had already established a connection with my IPhone that allowed me to stream music, I should just find a way to tap into that audio stream. I spent a while looking into various means of doing so, and came up with the Python library PyAudio, which provides bindings for the tool PortAudio. Below I have some example code that worked to read audio data from the stream. I found that using the default output device worked well; it didn't contain any audio data from other sources on the Pi that I could hear, although I believe it may have included other sounds such as notifications from the IPhone.
from pyaudio import PyAudio, paInt16
class AudioSource(object):
def __init__(self):
self.pa = PyAudio()
self.device = self.pa.get_default_output_device_info()
self.sample_format = paInt16
self.channels = 2
self.frames_per_buffer = 1024
self.rate = int(self.device['defaultSampleRate'])
self.stream = self.pa.open(
format = self.sample_format,
channels = self.channels,
rate = self.rate,
frames_per_buffer = self.frames_per_buffer,
input = True)
def read(self):
return self.stream.read(self.frames_per_buffer)
def kill(self):
self.stream.stop_stream()
self.stream.close()
self.pa.terminate()
After leaping that hurdle, I moved onto attempting to retrieve metadata from the music. For this I discovered dbus, a system used by applications to communicate with each other. In this case, we'll be using it to engage a dialogue between our program and the music player on the IPhone via the library pydbus, which provides a way to access dbus in Python. Finally, we will employ the PyGObject library, which provides a way of polling for emitted Bluetooth signals by way of GLib.MainLoop().
Firstly, let's retrieve the object that will provide us with an interface to the music player. Below, you'll see that I've created a class that iterates through all the available objects belonging to the service bluez, which is responsible for Bluetooth connections. Once it finds one ending with '/player0', it returns it. I do this because I don't want to include the Bluetooth address of the IPhone as an input. If you would rather hardcode the address, this can be achieved with the path '/org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/player0', modified to include your bluetooth address. (The 0 in 'player0' increases in count with multiple connections; I've yet to have more than one).
from pydbus import SystemBus
class MediaPlayer(object):
def __new__(self):
bus = SystemBus()
manager = bus.get('org.bluez', '/')
for obj in manager.GetManagedObjects():
if obj.endswith('/player0'):
return bus.get('org.bluez', obj)
raise MediaPlayer.DeviceNotFoundError
class DeviceNotFoundError(Exception):
def __init__(self):
super().__init__('No bluetooth device was found')
handle = MediaPlayer()
Once you've retrieved the object, you can use it to retrieve various attributes, as well as send various commands. handle.Position, for example, will return the current position of the media player in milliseconds, and handle.Pause() will pause the current track. The full list of commands and attributes can be found in the documentation, under the section MediaPlayer1.
In order for this to work correctly, it's imperative that you employ GLib.MainLoop(), which will poll for Bluetooth signals.
from gi.repository import GLib
loop = GLib.MainLoop()
loop.run()
If you're like me and you need to poll for signals while at the same time running some other sort of mainloop, Glib.MainLoop().run() won't work outright, as it's a blocking function. I've developed a solution below.
from threading import Thread
from gi.repository import GLib
class Receiver(Thread):
def __init__(self):
super().__init__()
self.loop = GLib.MainLoop()
self.context = self.loop.get_context()
self._keep_going = True
def kill(self):
self._keep_going = False
def run(self):
while self._keep_going:
self.context.iteration()
self.context.release()
self.loop.quit()
Something extremely useful for me was the ability to register a callback with the MediaPlayer object. The callback will be called any time an attribute of the MediaPlayer object changes. I found the two most useful properties to be handle.Status, which delivers the current status of the media player, and handle.Track, which can alert you to when the current track finishes, as well as provide metadata.
def callback(self, interface, changed_properties, invalidated_properties):
for change in changed_properties:
pass
subscription = handle.PropertiesChanged.connect(callback)
# To avoid continuing interactions after the program ends:
#subscription.disconnect()
Finally, you're probably going to want the ability to set the value of certain properties of the MediaPlayer object. For this you require the Variant object. ('s' evidently stands for string; I haven't yet had to try this with any other type).
from gi.repository import Variant
def set_property(prop, val):
handle.Set('org.bluez.MediaPlayer1', prop, Variant('s', val))
set_property('Shuffle', 'off')
That's all the advice I have to give. I hope that somebody eventually finds some help here, although I know it's more likely I'll just end up having rambled endlessly to myself. Regardless, if somebody's actually taken the time to read through all this, then good luck with whatever it is you're working on.
Related
I am struggling with a problem of reading through two PCAN adaptors for CAN messages. Both the PCAN adapters are connected to the USB Ports of the windows laptop.
One CAN adaptor is trying to read the CAN messages and other is reading the DID through UDS. When i run the code, both UDS and CAN code use the same USB port, making my application not work.CAN Library: https://python-can.readthedocs.io/en/master/ UDS Library: https://udsoncan.readthedocs.io/en/latest/
import can
import time
import sys
bus = can.interface.Bus(bustype = 'pcan', channel ='PCAN_USBBUS1', bitrate = 500000) # Windows
bus1= PcanBus(channel='PCAN_USBBUS2', bitrate=500000) # udsoncan library
class changeState:
def Receive_Can_Message(self):
message = bus.recv(1)
print(message)
class UDS:
def ReadingUDSMessage()
// Detail UDS message
if __name__ == "__main__":
obj= changeState()
obj2.UDS()
while True:
obj.Receive_Can_Message()
obj2.ReadingUDSMessage()
If you using two Peak CAN adaptors to an application related to python can library, you have use channel='PCAN_USBBUS1' for first and channel='PCAN_USBBUS2' for other. Also, take care to put the peak CAN adaptor to a laptop in correct sequence. The first connected USB to a laptop is considered channel='PCAN_USB1' and next one is considered 'PCAN_USB2'.
I have the task at hand to program all of the commands from a laser GUI to python so that we can use python instead of the GUI to control the laser. The problem: I don't really know where to start. I don't have any socket programming experience nor do I have knowledge of networking but I do know a bit of programming. To give you an idea of what I need to do, here is the PDF of what I have to program. PDF (p.s. if you don't have a Dropbox, you can just download the pdf)
That's the entire agenda. I have to define a class and use the commands there to make everything available in python.
My advisor started the program already but I am not sure what the code really means. I asked him where to go from here but he insists everything is covered in the pdf. The code is below.
I was hoping someone could point me in the right direction of what I should read/watch to understand how to code the rest. I read through some socket intros and TCP/IP intros and I understand the gist. The thing is, socket programming is a huge area and I don't know where to cut the wheat from the chaff. Note: the if statement at the end is already done, meaning there is nothing else to add (so says my supervisor). I only need to work on the class. The code is not really cemented in. If I find a/an better/easier way to work with the commands, then I could revamp the code. Any help is greatly appreciated.
Here is the code:
#!/usr/bin/env python
import PySide.QtNetwork as Network
import PySide.QtCore as Core
import configparser
class Spitlight():
"""The classe spitlight provides an interface so that we can the Innolas Spitlight Laser from python parameterize and operate.
"""
def __init__(self, *args, **kwargs):
"""constructor"""
pass
def ReadConfig(self, ConfigFile):
"""The parameters to operate the laser will come from the configurations file with the file ending *.ini"""
self.config = configparser.ConfigParser()
self.config.read(ConfigFile)
""" here the single parameters will be read and the parameters thoroughly checked. Later we will add parameter value limits so the laser will not function without being within the value limits.
Initial relevant options are:
flashbulb voltage, Repetition rate, pump duration, pockels cell control (Balance, Holdoff), delays
Futhermore the communication information is in the IP/Port of the laser server
return 0 """
def Start(self):
"""
Open socket with information from configuration
Send parameters to the laser and confirm that everything is in order e.g:
send SET_OSCILLATOR_AMPLITUDE with FLHighvoltage aus Config
"""
self.initSocket()
self.set_oscillator_amplitude()
def set_oscillator_amplitude(self):
self.tcpSocket.write("SET_OSCILLATOR_AMPLITUDE={}".format(self.Config['Laser parameter']['FLHighvoltage ']))
def set_oscillator_delay(self):
self.tcpSocket.write("SET_OSCILLATOR_DELAY={}".format(self.Config['Laser parameter']['FLDelay']))
def initSocket(self):
""" Socket initialize"""
self.tcpSocket = Network.QTcpSocket()
self.tcpSocket.disconnected.connect(self.connectSocket)
self.tcpSocket.readyRead.connect(self.readData)
self.connectSocket()
# regularly reconnect is stabilerregelmäßiger reconnect is more stable as leaving the socket the entire time open
self.reconnectTimer = Core.QTimer()
self.reconnectTimer.setInterval(120000) # 2 minutes
self.reconnectTimer.timeout.connect(self.reconnectSocket)
self.reconnectTimer.start()
return 0
#Core.Slot()
def connectSocket(self):
"""Socket connect"""
return self.tcpSocket.connectToHost(self.proxyAddress, self.proxyPort)
#Core.Slot()
def reconnectSocket(self):
"""Socket Status verify and again connect"""
""" Available states of tcpSocket.state() are:
QAbstractSocket.UnconnectedState The socket is not connected.
QAbstractSocket.HostLookupState The socket is performing a host name lookup.
QAbstractSocket.ConnectingState The socket has started establishing a connection.
QAbstractSocket.ConnectedState A connection is established.
QAbstractSocket.BoundState The socket is bound to an address and port (for servers).
QAbstractSocket.ClosingState The socket is about to close (data may still be waiting to be written).
QAbstractSocket.ListeningState For internal use only.
"""
if self.tcpSocket.state() in [ Network.QAbstractSocket.HostLookupState, Network.QAbstractSocket.ConnectingState, Network.QAbstractSocket.ListeningState ]:
return 0
if self.tcpSocket.state() == Network.QAbstractSocket.ConnectedState:
return self.tcpSocket.disconnectFromHost()
#Core.Slot()
def readData(self):
data = self.tcpSocket.readAll()
if str(data).startswith("ERROR="):
pass
elif str(data).startswith("WARNING="):
pass
elif:
pass
def FlOn(self):
"""send FLASHLAMP ON
verify with GET_LASER_STATE"""
return 0
"""testing framework:
laser start, parametrierize, flashbulb on, shutter off, shutter closed, flashbulb off, every of the functions gives a 0 when they were successful and a error message when not
"""
if __name__ == "__main__":
SpitligthControl = Spitlight()
SpitligthControl.ReadConfig('SpitlightConfig.ini')
SpitligthControl.Start()
SpitligthControl.FlOn()
SpitligthControl.StartEmission()
SpitligthControl.StopEmission()
SpitligthControl.FlOff()
I'm a bit new at Python and I am working on a robotics project. The short form of my question is that I am trying to find the best way (for my situation) to run multiple python programs at once.
A little bit of context, my robot is a platform for a service robot that is capable of following markers and paths using image algorithms and also receive commands from a remote computer. I want to have separate programs for the image processing, the driving, and so on, and then manage all of them through a main program. I know I can't use anything basic like functions or classes, because each of these processes must be looping continuously, and I don't want to combine all the code to run in a single while loop, because it runs very slowly and it is significantly harder to manage.
So, in short, how do I make two separate, looping programs "talk"? Like I want the imaging program to send information about what it sees to the driving and steering program, etc.
I did some research and I found some information on multithreading and API's and stuff like that, though I can't really tell which one is actually the thing I'm looking for.
To clarify, I just need to be pointed in the right direction. This doesn't seem like a very high-level thing, and I know there are definitely tutorials out there, I'm just really confused as to where to start as I am teaching myself this as I go.
After some sniffing around, I found that using IPC was a good solution. The process I used wasn't too difficult, I just made some very simple server and client classes and had them communicate over the Localhost IP. There's undoubtedly a better way to do this, but for a beginner like myself, it was a simple way to make two programs talk without modifying code too much. For those who are trying to do a similar thing as I did, here's the classes I made for myself. Fair warning, they're not exactly pristine or even very complex, but they got the job done.
Here's the class I made for the server:
import socket
from random import random
from time import sleep
class ServerObject:
def __init__(self,host_address,port):
self._host_address = host_address
self._s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self._s.bind((self._host_address,port))
def handshake(self):
print "Server Started. Awaiting Connection"
while True:
_data, _addr = self._s.recvfrom(1024)
if str(self._s.recvfrom(1024)[0]) == 'marco':
break
print 'marco recieved. sending polo...'
while True:
self._s.sendto('polo',_addr)
if str(self._s.recvfrom(1024)[0]) == 'confirm':
break
sleep(.5)
print 'connection verified'
self._addr = _addr
return True
def send(self,data):
self._s.sendto(str(data),self._addr)
def recieve(self,mode = 0):
_data, _addr = self._s.recvfrom(1024)
if mode == 0:
return str(_data)
if mode == 1:
return int(_data)
if mode == 2:
return float(_data)
if mode == 3:
return tuple(_data)
def change_port(self,port):
self._s.bind((self._host_address,port))
def close(self):
self._s.close()
print '_socket closed_'
if __name__ == '__main__':
host = '127.0.0.1'
talk = ServerObject(host,6003)
talk.handshake()
And here's the class I made for the client:
import socket
from time import sleep
class ClientObject:
def __init__(self,host_address,server_port,port = 0):
self._server = (host_address,server_port)
self._s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self._s.bind((host_address,port))
def handshake(self):
print ' sending marco'
self._s.sendto('marco',self._server)
sleep(.1)
self._s.sendto('marco',self._server)
while True:
if str(self._s.recvfrom(1024)[0]) == 'polo':
break
#self._s.sendto('marco',self._server)
#self._s.sendto('marco',self._server)
print ' connection verified'
self._s.sendto('confirm',self._server)
self._s.setblocking(0)
return True
def recieve(self,mode = 0):
_data, _addr = self._s.recvfrom(1024)
if mode == 0:
return str(_data)
if mode == 1:
return int(_data)
if mode == 2:
return float(_data)
if mode == 3:
return tuple(_data)
def send(self,data):
self._s.sendto(str(data),self._server)
def close(self):
self._s.close()
print '_socket closed_'
if __name__ == '__main__':
host = '127.0.0.1'
port = 0
talk = ClientObject(host,24603,port)
talk.handshake()
#while True:
#print talk.recieve()
Use the ServerObject class on the program that will primarily send data and the ClientObject class on the program that will primarily recieve data. These can be flipped around in many situations, but I found it's best to do it this way to take advantage of UDP. The client class has an optional port variable that is set to 0 by default. This is because for UDP the client needs another port to establish itself on. 0 means it will pick an available port, but if you specify one, it's possible to re-establish a connection if the client goes offline without needing to restart both programs.
Use the handshake first on both programs being sure to use the same IP and port (not referring to the last variable on the client) and then use the send and receive functions to pass data back and forth.
again, these aren't that good, in fact there's many problems that cab arise with using this method, but for a simple task, they got the job done. I set up the handshake to print verifications of what is happening, but if those get annoying, you can just remove those lines.
Hope this helps!
I think multiproccessing library could be a solution.
You will be able to run several processes in parallel when each process could perform it specific work, while sending data to each other.
You can check this example
This is generic directory walker, which have process that scans directory tree and passes the data to other process, which scans files in already discovered folders. All this done in parallel.
This is probably a little bit outside the scope of your project, but have you considered using ROS? It lets you run a bunch of different nodes (can be Python scripts) at the same time that communicate by publishing and subscribing to topics. They can be on the same system (i.e. one or more nodes on the robot) or different systems (i.e. one node on the robot, multiple nodes on the PC). ROS also has a lot of awesome built in tools and libraries that are specifically made for robotic systems such as visualization, mapping, odometry, etc. Here's a bit of starting info:
https://en.wikipedia.org/wiki/Robot_Operating_System
http://wiki.ros.org/ROS/StartGuide
It's usually used for much larger frameworks than you seem to be describing, and beware that it takes quite a bit of time (in my experience) to implement, but it is very easy to expand once its up and running. Like I said, it all depends on the scope of your project!
Good luck!
I'm making a program that (at least right now) retrives stream information from TwitchTV (streaming platform). This program is to self educate myself but when i run it, it's taking 2 minutes to print just the name of the streamer.
I'm using Python 2.7.3 64bit on Windows7 if that is important in anyway.
classes.py:
#imports:
import urllib
import re
#classes:
class Streamer:
#constructor:
def __init__(self, name, mode, link):
self.name = name
self.mode = mode
self.link = link
class Information:
#constructor:
def __init__(self, TWITCH_STREAMS, GAME, STREAMER_INFO):
self.TWITCH_STREAMS = TWITCH_STREAMS
self.GAME = GAME
self.STREAMER_INFO = STREAMER_INFO
def get_game_streamer_names(self):
"Connects to Twitch.TV API, extracts and returns all streams for a spesific game."
#start connection
self.con = urllib2.urlopen(self.TWITCH_STREAMS + self.GAME)
self.info = self.con.read()
self.con.close()
#regular expressions to get all the stream names
self.info = re.sub(r'"teams":\[\{.+?"\}\]', '', self.info) #remove all team names (they have the same name: parameter as streamer names)
self.streamers_names = re.findall('"name":"(.+?)"', self.info) #looks for the name of each streamer in the pile of info
#run in a for to reduce all "live_user_NAME" values
for name in self.streamers_names:
if name.startswith("live_user_"):
self.streamers_names.remove(name)
#end method
return self.streamers_names
def get_streamer_mode(self, name):
"Returns a streamers mode (on/off)"
#start connection
self.con = urllib2.urlopen(self.STREAMER_INFO + name)
self.info = self.con.read()
self.con.close()
#check if stream is online or offline ("stream":null indicates offline stream)
if self.info.count('"stream":null') > 0:
return "offline"
else:
return "online"
main.py:
#imports:
from classes import *
#consts:
TWITCH_STREAMS = "https://api.twitch.tv/kraken/streams/?game=" #add the game name at the end of the link (space = "+", eg: Game+Name)
STREAMER_INFO = "https://api.twitch.tv/kraken/streams/" #add streamer name at the end of the link
GAME = "League+of+Legends"
def main():
#create an information object
info = Information(TWITCH_STREAMS, GAME, STREAMER_INFO)
streamer_list = [] #create a streamer list
for name in info.get_game_streamer_names():
#run for every streamer name, create a streamer object and place it in the list
mode = info.get_streamer_mode(name)
streamer_name = Streamer(name, mode, 'http://twitch.tv/' + name)
streamer_list.append(streamer_name)
#this line is just to try and print something
print streamer_list[0].name, streamer_list[0].mode
if __name__ == '__main__':
main()
the program itself works perfectly, just really slow
any ideas?
Program efficiency typically falls under the 80/20 rule (or what some people call the 90/10 rule, or even the 95/5 rule). That is, 80% of the time the program is actually running in 20% of the code. In other words, there is a good shot that your code has a "bottleneck": a small area of the code that is running slow, while the rest runs very fast. Your goal is to identify that bottleneck (or bottlenecks), then fix it (them) to run faster.
The best way to do this is to profile your code. This means you are logging the time of when a specific action occurs with the logging module, use timeit like a commenter suggested, use some of the built-in profilers, or simply print out the current time at very points of the program. Eventually, you will find one part of the code that seems to be taking the most amount of time.
Experience will tell you that I/O (stuff like reading from a disk, or accessing resources over the internet) will take longer than in-memory calculations. My guess as to the problem is that you're using 1 HTTP connection to get a list of streamers, and then one HTTP connection to get the status of that streamer. Let's say that there are 10000 streamers: your program will need to make 10001 HTTP connections before it finishes.
There would be a few ways to fix this if this is indeed the case:
See if Twitch.TV has some alternatives in their API that allows you to retrieve a list of users WITH their streaming mode so that you don't need to call an API for each streamer.
Cache results. This won't actually help your program run faster the first time it runs, but you might be able to make it so that if it runs a second time within a minute, it can reuse results.
Limit your application to only dealing with a few streamers at a time. If there are 10000 streamers, what exactly does your application do that it really needs to look at the mode of all 10000 of them? Perhaps it's better to just grab the top 20, at which point the user can press a key to get the next 20, or close the application. Often times, programming is not just about writing code, but managing expectations of what your users want. This seems to be a pet project, so there might not be "users", meaning you have free reign to change what the app does.
Use multiple connections. Right now, your app makes one connection to the server, waits for the results to come back, parses the results, saves it, then starts on the next connection. This process might take an entire half a second. If there were 250 streamers, running this process for each of them would take a little over two minutes total. However, if you could run four of them at a time, you could potentially reduce your time to just under 30 seconds total. Check out the multiprocessing module. Keep in mind that some APIs might have limits to how many connections you can make at a certain time, so hitting them with 50 connections at a time might irk them and cause them to forbid you from accessing their API. Use caution here.
You are using the wrong tool here to parse the json data returned by your URL. You need to use json library provided by default rather than parsing the data using regex.
This will give you a boost in your program's performance
Change the regex parser
#regular expressions to get all the stream names
self.info = re.sub(r'"teams":\[\{.+?"\}\]', '', self.info) #remove all team names (they have the same name: parameter as streamer names)
self.streamers_names = re.findall('"name":"(.+?)"', self.info) #looks for the name of each streamer in the pile of info
To json parser
self.info = json.loads(self.info) #This will parse the json data as a Python Object
#Parse the name and return a generator
return (stream['name'] for stream in data[u'streams'])
I made some kind of answering machine for pidgin client that uses Linuxes DBus to make connection with pidgin. the code is this:
class DBus_Answer():
def __init__(self, text = "No text"):
self.answer = text
bus_loop = DBusQtMainLoop(set_as_default=True)
self.bus = dbus.SessionBus()
self.bus.add_signal_receiver(self.pidgin_control_func,
dbus_interface="im.pidgin.purple.PurpleInterface",
signal_name="ReceivedImMsg")
def pidgin_control_func(self, account, sender, message, conversation, flags):
obj = self.bus.get_object("im.pidgin.purple.PurpleService", "/im/pidgin/purple/PurpleObject")
purple = dbus.Interface(obj, "im.pidgin.purple.PurpleInterface")
purple.PurpleConvImSend(purple.PurpleConvIm(conversation), self.answer)
now I want to use it as a module in another program. I called it like this:
answering_machine.DBus_Answer(message)
the problem is, when I stop the second program (the program that has this one as a module) and then start it again, I'll get a segmentation fault because it want to make another connection to the DBus and it seams it's not regular!
Other wise I want to give the chance of disabling this module to user. I tried to use an if statement. It will work for the first time. but if user run the module for once, he can't disable it any more.
segmentation faults occur because in a python module (written in C) a pointer is NULL, or because it points to random memory (probably never initialized to anything), or because it points to memory that has been freed/deallocated/"deleted".so your problem is probably with your memory.try trace the segfault using methods described here