source: trunk/LocationDo/LocationDo.py @ 198

Last change on this file since 198 was 198, checked in by Nicholas Riley, 14 years ago

LocationDo?.py: ssh to yt in 4111; 1320 AP works for 1310/1320

action.py: fix killall on vpnc to actually work

props: ignore build, dist directories

File size: 7.8 KB
Line 
1#!/usr/bin/pythonw
2# -*- coding: utf-8 -*-
3
4from AppKit import NSApplication, NSBeep, NSSystemDefined, NSURL, NSWorkspace
5from Foundation import NSDistributedNotificationCenter, NSLog
6from PyObjCTools import AppHelper
7from Carbon.CarbonEvt import RegisterEventHotKey, GetApplicationEventTarget
8from SystemConfiguration import *
9from appscript import app
10import re
11import sets
12
13import action
14
15GROWL_APP_NAME = 'LocationDo'
16NOTIFICATION_LOCATION = 'Location'
17NOTIFICATION_ARRIVE = 'Arrive'
18NOTIFICATION_DEPART = 'Depart'
19NOTIFICATION_CURRENT = 'Current location'
20NOTIFICATION_UNKNOWN = 'Unknown location'
21NOTIFICATION_READY = 'Ready'
22NOTIFICATIONS_ALL = [NOTIFICATION_LOCATION, NOTIFICATION_ARRIVE,
23                     NOTIFICATION_DEPART, NOTIFICATION_CURRENT,
24                     NOTIFICATION_UNKNOWN, NOTIFICATION_READY]
25
26DEBUG = True
27
28kEventHotKeyPressedSubtype = 6
29kEventHotKeyReleasedSubtype = 9
30
31RE_AIRPORT_STATUS = '/'.join([kSCDynamicStoreDomainState, kSCCompNetwork, kSCCompInterface, kSCCompAnyRegex, kSCEntNetAirPort])
32
33growl = app('GrowlHelperApp')
34
35growl.register(
36    as_application=GROWL_APP_NAME,
37    all_notifications=NOTIFICATIONS_ALL,
38    default_notifications=NOTIFICATIONS_ALL)
39
40def growlNotify(name, title, description, **kw):
41    params = dict(with_name=name,
42                  title=title,
43                  description=unicode(description),
44                  application_name=GROWL_APP_NAME,
45                  image_from_location='/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/GenericNetworkIcon.icns')
46    params.update(kw)
47    if not params.get('sticky', False):
48        params['identifier'] = name
49    if DEBUG:
50        NSLog("%s: %s" % (title, description))
51    growl.notify(**params)
52
53class Location(sets.Set):
54    def __str__(self):
55        if not self: return '(unknown)'
56        return ', '.join(self)
57
58currentLocation = Location()
59
60def arriveAtLocation(location):
61    growlNotify(NOTIFICATION_ARRIVE, 'Arriving at location', location)
62    if 'Siebel' in location:
63        action.ensureKerberosPrincipalsValid(['njriley@ACM.UIUC.EDU',
64                                              'njriley@AD.UIUC.EDU'])
65        action.setVolumePercent(0.15)
66    if '1115 SC' in location:
67        action.openInBackground('~/Documents/CS 423/CS 423 to do.oo3')
68        action.setDisplayBrightnessPercent(0.2)
69        action.setAdiumStatus('Working in 1115 SC')
70    if '4111 SC' in location:
71        action.openInBackground('~/Documents/MSSP/MSSP progress.oo3')
72        action.terminalDo('kswitch -p njriley@ACM.UIUC.EDU;(sleep 10;kswitch -p njriley@AD.UIUC.EDU)&!;clear;ssh yt')
73        action.setDisplayBrightnessPercent(0.9)
74        action.setAdiumStatus('Working in 4111 SC')
75    if 'ACM office' in location:
76        action.setDisplayBrightnessPercent(0.2)
77        action.setAdiumStatus('At ACM')
78    if 'Champaign' in location:
79        action.openInBackground('~/Documents/To do.oo3')
80        action.setDisplayBrightnessPercent(0.2)
81        action.setVolumePercent(0.5)
82        action.setAdiumStatus('At home')
83    if '13[12]0 DCL' in location:
84        action.setDisplayBrightnessPercent(0.2)
85        action.setVolumePercent(0)
86        action.setAdiumStatus('In 13[12]0 DCL')
87    if 'UIUCnet' in location:
88        action.startVPNC('UIUCnet-oncampus')
89    if 'CSL' in location:
90        action.setDisplayBrightnessPercent(0.1)
91        action.setVolumePercent(0)
92        action.setAdiumStatus('At CSL')
93        action.openURL('http://wireless.csl.uiuc.edu/authenticate.html')
94    growlNotify(NOTIFICATION_ARRIVE, 'Arrived at location',
95                location)
96
97def departLocation(location):
98    growlNotify(NOTIFICATION_DEPART, 'Departing location', location)
99    if 'UIUCnet' in location:
100        # XXX should handle this more symmetrically
101        action.stopVPNC()
102    growlNotify(NOTIFICATION_DEPART, 'Departed location', location)
103
104def locationChanged(location):
105    if not location: return # unknown
106    global currentLocation
107    oldLocation = currentLocation - location
108    newLocation = location - currentLocation
109    if DEBUG:
110        NSLog("new %s | was %s | departing %s | arriving %s" % \
111              (location, currentLocation, oldLocation, newLocation))
112    if oldLocation:
113        departLocation(oldLocation)
114        currentLocation = location
115    if newLocation:
116        currentLocation = location
117        arriveAtLocation(newLocation)
118
119def formatMACAddress(data):
120    return ':'.join(re.findall('..', data.bytes()[:].encode('hex')))
121
122# XXX watch battery status, too, for display brightness
123
124airPortStatus = {'BSSID': None, 'SSID': None}
125
126class SCWatcher(NSObject):
127    def keysChanged_inDynamicStore_(self, changed, store):
128        location = Location()
129        for key in changed:
130            if re.match(RE_AIRPORT_STATUS, key):
131                st = store.valueForKey_(key)
132                bssid = formatMACAddress(st['BSSID'])
133                if airPortStatus['BSSID'] != bssid:
134                    airPortStatus['BSSID'] = bssid
135                    if bssid in ['00:0e:83:05:77:22', '00:0e:83:05:77:20',
136                                 '00:0e:83:05:75:d2']:
137                        location.add('4111 SC')
138                    elif bssid in ['00:0e:83:05:76:82', '00:0e:83:05:76:80']:
139                        location.add('ACM office')
140                    elif bssid == '00:11:24:0f:23:69':
141                        location.add('Champaign')
142                    elif bssid == '00:13:c4:ce:66:a0':
143                        location.add('13[12]0 DCL')
144                    elif bssid in ['00:14:1c:ad:5c:80', '00:14:1c:ad:64:50']:
145                        location.add('MEB')
146                    elif bssid == '00:02:2d:2c:cb:34':
147                        location.add('B02 CSL')
148                    elif bssid == '44:44:44:44:44:44':
149                        location.add('No AirPort network')
150                    else:
151                        growlNotify(NOTIFICATION_UNKNOWN, 'Unknown BSSID', bssid,
152                                    sticky=True)
153                        NSLog('Unknown BSSID %s' % bssid)
154                ssid = st['SSID']
155                if airPortStatus['SSID'] != ssid:
156                    airPortStatus['SSID'] = ssid
157                    if ssid == '':
158                        pass
159                    elif ssid == 'dcs-wpa':
160                        location.add('Siebel')
161                    elif ssid == 'DCSnet':
162                        location.add('Siebel')
163                        location.add('UIUCnet')
164                    elif ssid == 'UIUCnet':
165                        location.add('UIUCnet')
166                    elif ssid == 'ACME Acres':
167                        location.add('Champaign')
168                    elif ssid == 'CSL Wireless':
169                        location.add('CSL')
170                    else:
171                        growlNotify(NOTIFICATION_UNKNOWN, 'Unknown SSID', ssid,
172                                    sticky=True)
173                locationChanged(location)
174
175class LocationDo(NSApplication):
176
177    hotKeyRef = None
178
179    def displayLocation(self):
180        growlNotify(NOTIFICATION_CURRENT, 'Current location', currentLocation)
181
182    def finishLaunching(self):
183        super(LocationDo, self).finishLaunching()
184        hotKeyRef = RegisterEventHotKey(98, 0, (0, 0),
185                                        GetApplicationEventTarget(), 0) # F7
186        growlNotify(NOTIFICATION_READY, 'LocationDo ready', '')
187
188    def sendEvent_(self, theEvent):
189        if theEvent.type() == NSSystemDefined and \
190               theEvent.subtype() == kEventHotKeyPressedSubtype:
191            self.displayLocation()
192        super(LocationDo, self).sendEvent_(theEvent)
193
194store = None
195
196if __name__ == "__main__":
197    store = UNSystemConfigurationDynamicStore.alloc().initWithName_('LocationDo')
198    watcher = SCWatcher.alloc().init()
199    store.setDelegate_(watcher)
200    store.notifyValuesForKeys_matchingPatterns_(None, [RE_AIRPORT_STATUS])
201    store.addToCurrentRunLoop()
202    AppHelper.runEventLoop()
Note: See TracBrowser for help on using the repository browser.