From 627316a25d0990a1b6c2a0b2fd8aebbb97546c40 Mon Sep 17 00:00:00 2001 From: Dmitry Moiseev Date: Thu, 31 Oct 2013 14:17:03 +0600 Subject: initial commit --- ParrotProtocol.py | 19 ++++++++++ ParrotZik.py | 81 +++++++++++++++++++++++++++++++++++++++++ ParrotZikTray.py | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ README | 16 +++++++++ 4 files changed, 222 insertions(+) create mode 100644 ParrotProtocol.py create mode 100644 ParrotZik.py create mode 100644 ParrotZikTray.py create mode 100644 README diff --git a/ParrotProtocol.py b/ParrotProtocol.py new file mode 100644 index 0000000..9324b8b --- /dev/null +++ b/ParrotProtocol.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python + +def generateRequest(requestString): + message=bytearray() + message.extend(generateHeader(requestString)) + message.extend(bytearray(requestString)) + return message + +def generateHeader(requestString): + header = bytearray([0]) + header.append(len(requestString)+3) + header.append("\x80") + return header + +def getRequest(apiString): + return generateRequest("GET "+apiString) + +def setRequest(apiString,args): + return generateRequest("SET "+apiString+"?arg="+args) \ No newline at end of file diff --git a/ParrotZik.py b/ParrotZik.py new file mode 100644 index 0000000..bf2eb25 --- /dev/null +++ b/ParrotZik.py @@ -0,0 +1,81 @@ +#!/usr/bin/env python + +import bluetooth +import ParrotProtocol +import struct +from BeautifulSoup import BeautifulSoup + +class ParrotZik(object): + def __init__(self,addr=None): + uuid = "0ef0f502-f0ee-46c9-986c-54ed027807fb" + + service_matches = bluetooth.find_service( uuid = uuid, address = addr ) + + if len(service_matches) == 0: + print "Couldn't find Parrot Zik" + return False + + first_match = service_matches[0] + port = first_match["port"] + name = first_match["name"] + host = first_match["host"] + + print "Connecting to \"%s\" on %s" % (name, host) + + self.sock=bluetooth.BluetoothSocket( bluetooth.RFCOMM ) + self.sock.connect((host, port)) + + self.sock.send('\x00\x03\x00') + data = self.sock.recv(3) + print "Connected" + + def getBatteryState(self): + data = self.sendGetMessage("/api/system/battery/get") + return data.answer.system.battery["state"] + + def getBatteryLevel(self): + data = self.sendGetMessage("/api/system/battery/get") + return data.answer.system.battery["level"] + + def getVersion(self): + data = self.sendGetMessage("/api/software/version/get") + return data.answer.software["version"] + + def getFriendlyName(self): + data = self.sendGetMessage("/api/bluetooth/friendlyname/get") + return data.answer.bluetooth["friendlyname"] + + def getAutoConnection(self): + data = self.sendGetMessage("/api/system/auto_connection/enabled/get") + return data.answer.system.auto_connection["enabled"] + + def getAncPhoneMode(self): + data = self.sendGetMessage("/api/system/anc_phone_mode/enabled/get") + return data.answer.system.anc_phone_mode["enabled"] + + def getNoiseCancel(self): + data = self.sendGetMessage("/api/audio/noise_cancellation/enabled/get") + return data.answer.audio.noise_cancellation["enabled"] + + def setNoiseCancel(self,arg): + data = self.sendSetMessage("/api/audio/noise_cancellation/enabled/set",arg) + return data + + def sendGetMessage(self,message): + message = ParrotProtocol.getRequest(message) + return self.sendMessage(message) + + def sendSetMessage(self,message,arg): + message = ParrotProtocol.setRequest(message,arg) + return self.sendMessage(message) + + def sendMessage(self,message): + self.sock.send(str(message)) + data = self.sock.recv(7) + len = struct.unpack('B', data[1])[0] + data = self.sock.recv(len) + data=BeautifulSoup(data) + return data + + def Close(self): + self.sock.close() diff --git a/ParrotZikTray.py b/ParrotZikTray.py new file mode 100644 index 0000000..c342a53 --- /dev/null +++ b/ParrotZikTray.py @@ -0,0 +1,106 @@ +#!/usr/bin/env python + +import sys +import gtk +import appindicator +import imaplib +import re +import os +import ParrotZik + +UPDATE_FREQUENCY = 10 # seconds + +class ParrotZikIndicator: + def __init__(self): + self.ind = appindicator.Indicator("new-parrotzik-indicator", + "indicator-messages", + appindicator.CATEGORY_APPLICATION_STATUS) + self.ind.set_status(appindicator.STATUS_ACTIVE) + self.ind.set_icon("gtk-info") + self.menu_setup() + self.ind.set_menu(self.menu) + self.connected=False + + def menu_setup(self): + self.menu = gtk.Menu() + + self.info_item = gtk.MenuItem("Parrot Zik Not connected..") + self.info_item.set_sensitive(False) + self.info_item.show() + self.menu.append(self.info_item) + + self.check = gtk.CheckMenuItem("Noise Cancellation") + self.check.connect("activate", self.toggleANC) + self.check.set_sensitive(False) + self.check.show() + self.menu.append(self.check) + + self.quit_item = gtk.MenuItem("Quit") + self.quit_item.connect("activate", self.quit) + self.quit_item.show() + self.menu.append(self.quit_item) + + def findParrotZikMac(self): + out = os.popen("hcitool con").read() + p = re.compile('90:03:[0-9A-F]{2}:[0-9A-F]{2}:[0-9A-F]{2}:[0-9A-F]{2}') + res = p.findall(out) + if len(res)>0: + return res[0] + else: + return '' + + def EstablishConnection(self): + if self.connected: + return + else: + mac=self.findParrotZikMac() + if mac: + self.parrot = ParrotZik.ParrotZik(mac) + self.connected = True + self.check.set_sensitive(True) + if self.parrot.getNoiseCancel() == "true": + self.check.set_active(True) + else: + self.check.set_active(False) + self.CheckBattery() + else: + return + + def toggleANC(self,widget): + if self.connected: + if self.check.get_active(): + self.parrot.setNoiseCancel("true") + else: + self.parrot.setNoiseCancel("false") + + def CheckBattery(self): + if self.connected: + self.batteryLevel = self.parrot.getBatteryLevel() + self.info_item.set_label("Battery "+self.batteryLevel+"%") + if self.batteryLevel==100: + self.ind.set_icon("battery-100") + elif self.batteryLevel>80: + self.ind.set_icon("battery-80") + elif self.batteryLevel>60: + self.ind.set_icon("battery-80") + elif self.batteryLevel>40: + self.ind.set_icon("battery-40") + else: + self.ind.set_icon("battery-low") + else: + self.ind.set_icon("gtk-info") + self.info_item.set_label("Parrot Zik Not connected..") + self.check.set_sensitive(False) + + def main(self): + self.EstablishConnection() + gtk.timeout_add(UPDATE_FREQUENCY * 1000, self.EstablishConnection) + gtk.timeout_add(UPDATE_FREQUENCY * 1000, self.CheckBattery) + gtk.main() + + def quit(self, widget): + sys.exit(0) + +if __name__ == "__main__": + indicator = ParrotZikIndicator() + indicator.main() \ No newline at end of file diff --git a/README b/README new file mode 100644 index 0000000..1698595 --- /dev/null +++ b/README @@ -0,0 +1,16 @@ +Parrot Zik Api +======== + +## Overview + +Parrot Zik is one of the most advanced headphones in the market. +http://www.parrot.com/zik/usa/technology + + +Python Parrot Zik and simple unity app indicator applet. + +## Tray Indicator Applet Usage + +1) Connect Parrot Zik with standard bluetooth connection +2) Run applet ./ParrotZikTray.py + -- cgit v1.2.1