From 8c9d567850bcaef24df3ee8a01266bd708f283ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9B=D0=B5=D0=BD=D0=B0?= Date: Fri, 13 Dec 2013 02:50:54 +0600 Subject: Initial support of mac os x --- ParrotZikMac.py | 98 +++++++++++++++++++++++++ ParrotZikTrayMac | 214 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 312 insertions(+) create mode 100644 ParrotZikMac.py create mode 100644 ParrotZikTrayMac diff --git a/ParrotZikMac.py b/ParrotZikMac.py new file mode 100644 index 0000000..a4b536c --- /dev/null +++ b/ParrotZikMac.py @@ -0,0 +1,98 @@ +#!/usr/bin/env python + +import lightblue +import ParrotProtocol +import struct +from BeautifulSoup import BeautifulSoup + +class ParrotZik(object): + def __init__(self,addr=None): + uuid = "0ef0f502-f0ee-46c9-986c-54ed027807fb" + + service_matches = lightblue.findservices( name = "RFCOMM", addr = addr ) + + if len(service_matches) == 0: + print "Couldn't find Parrot Zik" + return + + 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=lightblue.lightblueSocket( lightblue.RFCOMM ) + self.sock.connect((host, port)) + + self.sock.send('\x00\x03\x00') + data = self.sock.recv(3) + + self.BatteryLevel = 100 + 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") + try: + if data.answer.system.battery["level"] <> '': + self.BatteryLevel = data.answer.system.battery["level"] + except: + pass + + try: + print "notification received" + data.notify["path"] + except: + pass + + return self.BatteryLevel + + def getVersion(self): + data = self.sendGetMessage("/api/software/version/get") + return data.answer.software["version"] + + def getFriendlyName(self): + data = self.sendGetMessage("/api/lightblue/friendlyname/get") + return data.answer.lightblue["friendlyname"] + + def getAutoConnection(self): + data = self.sendGetMessage("/api/system/auto_connection/enabled/get") + return data.answer.system.auto_connection["enabled"] + + def setAutoConnection(self,arg): + data = self.sendSetMessage("/api/system/auto_connection/enabled/set",arg) + return data + + 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(1024) + data=BeautifulSoup(data) + return data + + def Close(self): + self.sock.close() diff --git a/ParrotZikTrayMac b/ParrotZikTrayMac new file mode 100644 index 0000000..7179386 --- /dev/null +++ b/ParrotZikTrayMac @@ -0,0 +1,214 @@ +#!/usr/bin/env python + +import sys +import re +import os +import ParrotZikMac +import rumps +from binplist import binplist +import BluetoothPairedDevices + + +UPDATE_FREQUENCY = 30 # seconds + +class ParrotZikIndicator: + def __init__(self): + + self.menu_setup() + + self.connected=False + + self.p = re.compile('00\-88\-[0-9A-Fa-f]{2}\-[0-9A-Fa-f]{2}\-[0-9A-Fa-f]{2}\-[0-9A-Fa-f]{2}') + + if sys.platform=="darwin": + self.icon_directory = os.path.dirname(os.path.realpath(sys.argv[0])) + os.path.sep+ 'share' + os.path.sep+'icons' + os.path.sep+'zik'+ os.path.sep + self.app = rumps.App("Parrot Zik Tray", icon= self.icon_directory+ os.path.sep + "zik-audio-headset.png") + self.app.menu = self.menu + + return + + def pos(menu, ignore, icon): + return (Gtk.StatusIcon.position_menu(menu, icon)) + + def setIcon(self, name): + if sys.platform=="linux2": + self.statusicon.set_icon(name) + else: + self.statusicon.set_from_file(self.icon_directory+name+'.png') + + def gtk_right_click_event(self, icon, button, time): + if not self.menu_shown: + self.menu_shown=True + self.menu.popup(None, None, gtk.status_icon_position_menu, button, time, self.statusicon) + else: + self.menu_shown=False + self.menu.popdown() + + + def menu_setup(self): + self.menu = [] + + self.info_item = rumps.MenuItem("Parrot Zik Not connected..") + self.menu.append(self.info_item) + + self.check = rumps.MenuItem("Noise Cancellation") + self.menu.append(self.check) + + self.check2 = rumps.MenuItem("Auto Connection") + self.menu.append(self.check2) + + self.check3 = rumps.MenuItem("Lou Reed Mode") + self.menu.append(self.check3) + + self.check4 = rumps.MenuItem("Concert Hall Mode") + self.menu.append(self.check4) + + + def EstablishConnection(self): + if self.connected: + if not self.parrot.sock: + print "Lost connection" + self.connected = False + else: + print "Connection already established" + else: + mac=BluetoothPairedDevices.ParrotZikMac() + if mac: + self.parrot = ParrotZik.ParrotZik(mac) + if not self.parrot.sock: + print "Failed to connect to Parrot Zik %s" % mac + return False + + self.connected = True + self.name = self.parrot.getFriendlyName() + self.version = self.parrot.getVersion() + + self.check.set_sensitive(True) + self.check2.set_sensitive(True) + self.check3.set_sensitive(True) + self.check4.set_sensitive(True) + + if self.parrot.getNoiseCancel() == "true": + self.check.set_active(True) + else: + self.check.set_active(False) + + if self.parrot.getAutoConnection() == "true": + self.check2.set_active(True) + else: + self.check2.set_active(False) + + if self.parrot.getLouReedMode() == "true": + self.check3.set_active(True) + else: + self.check3.set_active(False) + + if self.parrot.getParrotConcertHall() == "true": + self.check4.set_active(True) + else: + self.check4.set_active(False) + + self.CheckBattery() + return True + + def toggleANC(self,widget): + if self.connected: + if self.check.get_active(): + self.parrot.setNoiseCancel("true") + else: + self.parrot.setNoiseCancel("false") + + def toggleAuto(self,widget): + if self.connected: + if self.check2.get_active(): + self.parrot.setAutoConnection("true") + else: + self.parrot.setAutoConnection("false") + + def toggleLouReedMode(self,widget): + if self.connected: + if self.check3.get_active(): + self.parrot.setLouReedMode("true") + else: + self.parrot.setLouReedMode("false") + if self.parrot.getLouReedMode() == "true": + self.check3.set_active(True) + else: + self.check3.set_active(False) + + if self.parrot.getParrotConcertHall() == "true": + self.check4.set_active(True) + else: + self.check4.set_active(False) + + def toggleParrotConcertHall(self,widget): + if self.connected: + if self.check4.get_active(): + self.parrot.setParrotConcertHall("true") + else: + self.parrot.setParrotConcertHall("false") + + if self.parrot.getLouReedMode() == "true": + self.check3.set_active(True) + else: + self.check3.set_active(False) + + if self.parrot.getParrotConcertHall() == "true": + self.check4.set_active(True) + else: + self.check4.set_active(False) + + def CheckBattery(self): + if self.connected: + print "Updating battery" + self.batteryLevel = int(self.parrot.getBatteryLevel()) + + if self.parrot.BatteryCharging: + self.batteryLevel = "Charging" + self.setIcon("zik-battery-charging") + self.batteryLevel="Unknown" + self.batteryState="Charging" + elif self.batteryLevel>80: + self.setIcon("zik-battery-100") + self.batteryState="In Use" + elif self.batteryLevel>60: + self.setIcon("zik-battery-080") + self.batteryState="In Use" + elif self.batteryLevel>40: + self.setIcon("zik-battery-060") + self.batteryState="In Use" + elif self.batteryLevel>20: + self.setIcon("zik-battery-040") + self.batteryState="In Use" + else: + self.setIcon("zik-battery-low") + self.batteryState="In Use" + + self.info_item.set_label("Connected to: "+self.name+ + "\nFirmware version: "+self.version+ + "\nState: "+self.batteryState+ + "\nBattery Level: "+str(self.batteryLevel)) + else: + self.setIcon("zik-audio-headset") + self.info_item.set_label("Parrot Zik Not connected..") + self.check.set_sensitive(False) + self.check2.set_sensitive(False) + self.check3.set_sensitive(False) + self.check4.set_sensitive(False) + return True + + # def show_about_dialog(self, widget): + # about_dialog = gtk.AboutDialog() + + # about_dialog.set_destroy_with_parent(True) + # about_dialog.set_name("Parrot Zik Tray") + # about_dialog.set_version("0.1") + # about_dialog.set_authors(["Dmitry Moiseev m0sia@m0sia.ru"]) + # about_dialog.run() + # about_dialog.destroy() + + +if __name__ == "__main__": + indicator = ParrotZikIndicator() + indicator.EstablishConnection() + indicator.app.run() \ No newline at end of file -- cgit v1.2.1