annotate service/tomatoWifi/tomatoWifi.py @ 279:57c9dbd2fdd0

immediate mode needs a PUT request Ignore-this: 48c3b5d2c25440a43000b53079d0bd68
author drewp@bigasterisk.com
date Fri, 06 May 2016 17:32:18 -0700
parents fc184ea1416d
children 68c2a5f1d563
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
1 #!/usr/bin/python
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
2 """
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
3 scrape the tomato router status pages to see who's connected to the
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
4 wifi access points. Includes leases that aren't currently connected.
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
5
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
6 Returns:
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
7 json listing (for magma page)
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
8 rdf graph (for reasoning)
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
9 activity stream, when we start saving history
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
10
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
11 Todo: this should be the one polling and writing to mongo, not entrancemusic
162
bb70eaa45666 whitespace
drewp@bigasterisk.com
parents: 161
diff changeset
12
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
13 """
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
14 from __future__ import division
51
d2842eedd56d rewrite tomatowifi from restkit to cyclone httpclient
drewp@bigasterisk.com
parents: 50
diff changeset
15 import sys, cyclone.web, json, traceback, time, pystache, datetime, logging
62
f8cc3d1baa85 redo wifi scraper to work with zyxel router report page too. add last connected time (from mongo) to web table
drewp@bigasterisk.com
parents: 52
diff changeset
16 import web.utils
51
d2842eedd56d rewrite tomatowifi from restkit to cyclone httpclient
drewp@bigasterisk.com
parents: 50
diff changeset
17 from cyclone.httpclient import fetch
d2842eedd56d rewrite tomatowifi from restkit to cyclone httpclient
drewp@bigasterisk.com
parents: 50
diff changeset
18 sys.path.append("/home/drewp/projects/photo/lib/python2.7/site-packages")
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
19 from dateutil import tz
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
20 from twisted.internet import reactor, task
62
f8cc3d1baa85 redo wifi scraper to work with zyxel router report page too. add last connected time (from mongo) to web table
drewp@bigasterisk.com
parents: 52
diff changeset
21 from twisted.internet.defer import inlineCallbacks
189
fc184ea1416d switch to docopt
drewp@bigasterisk.com
parents: 175
diff changeset
22 import docopt
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
23
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
24 from pymongo import Connection, DESCENDING
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
25 from rdflib import Namespace, Literal, URIRef
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
26 sys.path.append("/my/site/magma")
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
27 from stategraph import StateGraph
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
28 from wifi import Wifi
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
29
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
30 sys.path.append("/my/proj/homeauto/lib")
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
31 from cycloneerr import PrettyErrorHandler
1
26a6cf58743d entrancemusic improve logging
drewp@bigasterisk.com
parents: 0
diff changeset
32 from logsetup import log
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
33
36
0ab069867c64 rdflib and jsonlib api updates
drewp@bigasterisk.com
parents: 1
diff changeset
34
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
35 DEV = Namespace("http://projects.bigasterisk.com/device/")
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
36 ROOM = Namespace("http://projects.bigasterisk.com/room/")
51
d2842eedd56d rewrite tomatowifi from restkit to cyclone httpclient
drewp@bigasterisk.com
parents: 50
diff changeset
37 reasoning = "http://bang:9071/"
1
26a6cf58743d entrancemusic improve logging
drewp@bigasterisk.com
parents: 0
diff changeset
38
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
39 class Index(PrettyErrorHandler, cyclone.web.RequestHandler):
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
40 def get(self):
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
41
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
42 age = time.time() - self.settings.poller.lastPollTime
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
43 if age > 10:
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
44 raise ValueError("poll data is stale. age=%s" % age)
175
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
45
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
46 self.set_header("Content-Type", "text/html")
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
47 self.write(open("index.html").read())
51
d2842eedd56d rewrite tomatowifi from restkit to cyclone httpclient
drewp@bigasterisk.com
parents: 50
diff changeset
48
175
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
49 def whenConnected(mongo, macThatIsNowConnected):
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
50 lastArrive = None
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
51 for ev in mongo.find({'address': macThatIsNowConnected.upper()},
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
52 sort=[('created', -1)],
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
53 max_scan=100000):
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
54 if ev['action'] == 'arrive':
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
55 lastArrive = ev
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
56 if ev['action'] == 'leave':
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
57 break
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
58 if lastArrive is None:
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
59 raise ValueError("no past arrivals")
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
60
175
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
61 return lastArrive['created']
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
62
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
63 def connectedAgoString(conn):
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
64 return web.utils.datestr(
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
65 conn.astimezone(tz.tzutc()).replace(tzinfo=None))
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
66
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
67 class Table(PrettyErrorHandler, cyclone.web.RequestHandler):
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
68 def get(self):
62
f8cc3d1baa85 redo wifi scraper to work with zyxel router report page too. add last connected time (from mongo) to web table
drewp@bigasterisk.com
parents: 52
diff changeset
69 def rowDict(row):
f8cc3d1baa85 redo wifi scraper to work with zyxel router report page too. add last connected time (from mongo) to web table
drewp@bigasterisk.com
parents: 52
diff changeset
70 row['cls'] = "signal" if row.get('connected') else "nosignal"
f8cc3d1baa85 redo wifi scraper to work with zyxel router report page too. add last connected time (from mongo) to web table
drewp@bigasterisk.com
parents: 52
diff changeset
71 if 'name' not in row:
74
bca6d6c63bdc handle wifi users with no clientHostname
drewp@bigasterisk.com
parents: 62
diff changeset
72 row['name'] = row.get('clientHostname', '-')
62
f8cc3d1baa85 redo wifi scraper to work with zyxel router report page too. add last connected time (from mongo) to web table
drewp@bigasterisk.com
parents: 52
diff changeset
73 if 'signal' not in row:
175
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
74 row['signal'] = 'yes' if row.get('connected') else 'no'
62
f8cc3d1baa85 redo wifi scraper to work with zyxel router report page too. add last connected time (from mongo) to web table
drewp@bigasterisk.com
parents: 52
diff changeset
75
f8cc3d1baa85 redo wifi scraper to work with zyxel router report page too. add last connected time (from mongo) to web table
drewp@bigasterisk.com
parents: 52
diff changeset
76 try:
175
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
77 conn = whenConnected(self.settings.mongo, row.get('mac', '??'))
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
78 row['connectedAgo'] = connectedAgoString(conn)
62
f8cc3d1baa85 redo wifi scraper to work with zyxel router report page too. add last connected time (from mongo) to web table
drewp@bigasterisk.com
parents: 52
diff changeset
79 except ValueError:
175
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
80 row['connectedAgo'] = 'yes' if row.get('connected') else ''
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
81 row['router'] = row.get('ssid', '')
62
f8cc3d1baa85 redo wifi scraper to work with zyxel router report page too. add last connected time (from mongo) to web table
drewp@bigasterisk.com
parents: 52
diff changeset
82 return row
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
83
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
84 self.set_header("Content-Type", "application/xhtml+xml")
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
85 self.write(pystache.render(
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
86 open("table.mustache").read(),
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
87 dict(
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
88 rows=sorted(map(rowDict, self.settings.poller.lastAddrs),
62
f8cc3d1baa85 redo wifi scraper to work with zyxel router report page too. add last connected time (from mongo) to web table
drewp@bigasterisk.com
parents: 52
diff changeset
89 key=lambda a: (not a.get('connected'),
f8cc3d1baa85 redo wifi scraper to work with zyxel router report page too. add last connected time (from mongo) to web table
drewp@bigasterisk.com
parents: 52
diff changeset
90 a.get('name'))))))
175
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
91
51
d2842eedd56d rewrite tomatowifi from restkit to cyclone httpclient
drewp@bigasterisk.com
parents: 50
diff changeset
92
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
93 class Json(PrettyErrorHandler, cyclone.web.RequestHandler):
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
94 def get(self):
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
95 self.set_header("Content-Type", "application/json")
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
96 age = time.time() - self.settings.poller.lastPollTime
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
97 if age > 10:
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
98 raise ValueError("poll data is stale. age=%s" % age)
51
d2842eedd56d rewrite tomatowifi from restkit to cyclone httpclient
drewp@bigasterisk.com
parents: 50
diff changeset
99 self.write(json.dumps({"wifi" : self.settings.poller.lastAddrs,
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
100 "dataAge" : age}))
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
101
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
102 class GraphHandler(PrettyErrorHandler, cyclone.web.RequestHandler):
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
103 def get(self):
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
104 g = StateGraph(ctx=DEV['wifi'])
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
105
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
106 # someday i may also record specific AP and their strength,
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
107 # for positioning. But many users just want to know that the
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
108 # device is connected to some bigasterisk AP.
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
109 aps = URIRef("http://bigasterisk.com/wifiAccessPoints")
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
110 age = time.time() - self.settings.poller.lastPollTime
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
111 if age > 10:
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
112 raise ValueError("poll data is stale. age=%s" % age)
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
113
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
114 for dev in self.settings.poller.lastAddrs:
62
f8cc3d1baa85 redo wifi scraper to work with zyxel router report page too. add last connected time (from mongo) to web table
drewp@bigasterisk.com
parents: 52
diff changeset
115 if not dev.get('connected'):
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
116 continue
161
b0c168f562e8 scan dhcpd.leases to get more info about networked devices
drewp@bigasterisk.com
parents: 74
diff changeset
117 uri = URIRef("http://bigasterisk.com/mac/%s" % dev['mac'].lower())
b0c168f562e8 scan dhcpd.leases to get more info about networked devices
drewp@bigasterisk.com
parents: 74
diff changeset
118 g.add((uri, ROOM['macAddress'], Literal(dev['mac'].lower())))
62
f8cc3d1baa85 redo wifi scraper to work with zyxel router report page too. add last connected time (from mongo) to web table
drewp@bigasterisk.com
parents: 52
diff changeset
119
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
120 g.add((uri, ROOM['connected'], aps))
62
f8cc3d1baa85 redo wifi scraper to work with zyxel router report page too. add last connected time (from mongo) to web table
drewp@bigasterisk.com
parents: 52
diff changeset
121 if 'clientHostname' in dev:
f8cc3d1baa85 redo wifi scraper to work with zyxel router report page too. add last connected time (from mongo) to web table
drewp@bigasterisk.com
parents: 52
diff changeset
122 g.add((uri, ROOM['wifiNetworkName'], Literal(dev['clientHostname'])))
f8cc3d1baa85 redo wifi scraper to work with zyxel router report page too. add last connected time (from mongo) to web table
drewp@bigasterisk.com
parents: 52
diff changeset
123 if 'name' in dev:
f8cc3d1baa85 redo wifi scraper to work with zyxel router report page too. add last connected time (from mongo) to web table
drewp@bigasterisk.com
parents: 52
diff changeset
124 g.add((uri, ROOM['deviceName'], Literal(dev['name'])))
f8cc3d1baa85 redo wifi scraper to work with zyxel router report page too. add last connected time (from mongo) to web table
drewp@bigasterisk.com
parents: 52
diff changeset
125 if 'signal' in dev:
f8cc3d1baa85 redo wifi scraper to work with zyxel router report page too. add last connected time (from mongo) to web table
drewp@bigasterisk.com
parents: 52
diff changeset
126 g.add((uri, ROOM['signalStrength'], Literal(dev['signal'])))
175
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
127 try:
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
128 conn = whenConnected(self.settings.mongo, dev['mac'])
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
129 except ValueError:
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
130 pass
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
131 else:
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
132 g.add((uri, ROOM['connectedAgo'],
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
133 Literal(connectedAgoString(conn))))
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
134 g.add((uri, ROOM['connected'], Literal(conn)))
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
135
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
136 self.set_header('Content-type', 'application/x-trig')
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
137 self.write(g.asTrig())
51
d2842eedd56d rewrite tomatowifi from restkit to cyclone httpclient
drewp@bigasterisk.com
parents: 50
diff changeset
138
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
139 class Poller(object):
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
140 def __init__(self, wifi, mongo):
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
141 self.wifi = wifi
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
142 self.mongo = mongo
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
143 self.lastAddrs = []
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
144 self.lastWithSignal = []
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
145 self.lastPollTime = 0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
146
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
147 def assertCurrent(self):
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
148 dt = time.time() - self.lastPollTime
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
149 assert dt < 10, "last poll was %s sec ago" % dt
51
d2842eedd56d rewrite tomatowifi from restkit to cyclone httpclient
drewp@bigasterisk.com
parents: 50
diff changeset
150
d2842eedd56d rewrite tomatowifi from restkit to cyclone httpclient
drewp@bigasterisk.com
parents: 50
diff changeset
151 @inlineCallbacks
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
152 def poll(self):
175
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
153
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
154 connectedField = 'connected'
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
155
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
156 # UVA mode:
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
157 addDhcpData = lambda *args: None
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
158
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
159 try:
51
d2842eedd56d rewrite tomatowifi from restkit to cyclone httpclient
drewp@bigasterisk.com
parents: 50
diff changeset
160 newAddrs = yield self.wifi.getPresentMacAddrs()
62
f8cc3d1baa85 redo wifi scraper to work with zyxel router report page too. add last connected time (from mongo) to web table
drewp@bigasterisk.com
parents: 52
diff changeset
161 addDhcpData(newAddrs)
f8cc3d1baa85 redo wifi scraper to work with zyxel router report page too. add last connected time (from mongo) to web table
drewp@bigasterisk.com
parents: 52
diff changeset
162
f8cc3d1baa85 redo wifi scraper to work with zyxel router report page too. add last connected time (from mongo) to web table
drewp@bigasterisk.com
parents: 52
diff changeset
163 newWithSignal = [a for a in newAddrs if a.get('connected')]
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
164
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
165 actions = self.computeActions(newWithSignal)
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
166 for action in actions:
1
26a6cf58743d entrancemusic improve logging
drewp@bigasterisk.com
parents: 0
diff changeset
167 log.info("action: %s", action)
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
168 action['created'] = datetime.datetime.now(tz.gettz('UTC'))
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
169 mongo.save(action)
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
170 try:
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
171 self.doEntranceMusic(action)
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
172 except Exception, e:
1
26a6cf58743d entrancemusic improve logging
drewp@bigasterisk.com
parents: 0
diff changeset
173 log.error("entrancemusic error: %r", e)
51
d2842eedd56d rewrite tomatowifi from restkit to cyclone httpclient
drewp@bigasterisk.com
parents: 50
diff changeset
174
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
175 self.lastWithSignal = newWithSignal
50
56eeda98cac5 ping reasoning
drewp@bigasterisk.com
parents: 36
diff changeset
176 if actions: # this doesn't currently include signal strength changes
51
d2842eedd56d rewrite tomatowifi from restkit to cyclone httpclient
drewp@bigasterisk.com
parents: 50
diff changeset
177 fetch(reasoning + "immediateUpdate",
279
57c9dbd2fdd0 immediate mode needs a PUT request
drewp@bigasterisk.com
parents: 189
diff changeset
178 method='PUT',
52
875a37be1228 fix fetch calls in tomatowifi
drewp@bigasterisk.com
parents: 51
diff changeset
179 timeout=2,
875a37be1228 fix fetch calls in tomatowifi
drewp@bigasterisk.com
parents: 51
diff changeset
180 headers={'user-agent': ['tomatoWifi']}).addErrback(log.warn)
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
181 self.lastAddrs = newAddrs
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
182 self.lastPollTime = time.time()
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
183 except Exception, e:
175
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
184 log.error("poll error: %r\n%s", e, traceback.format_exc())
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
185
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
186 def computeActions(self, newWithSignal):
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
187 actions = []
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
188
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
189 def makeAction(addr, act):
62
f8cc3d1baa85 redo wifi scraper to work with zyxel router report page too. add last connected time (from mongo) to web table
drewp@bigasterisk.com
parents: 52
diff changeset
190 d = dict(sensor="wifi",
175
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
191 address=addr.get('mac').upper(), # mongo data is legacy uppercase
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
192 name=addr.get('name'),
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
193 networkName=addr.get('clientHostname'),
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
194 action=act)
62
f8cc3d1baa85 redo wifi scraper to work with zyxel router report page too. add last connected time (from mongo) to web table
drewp@bigasterisk.com
parents: 52
diff changeset
195 if act == 'arrive' and 'ip' in addr:
f8cc3d1baa85 redo wifi scraper to work with zyxel router report page too. add last connected time (from mongo) to web table
drewp@bigasterisk.com
parents: 52
diff changeset
196 # this won't cover the possible case that you get on
f8cc3d1baa85 redo wifi scraper to work with zyxel router report page too. add last connected time (from mongo) to web table
drewp@bigasterisk.com
parents: 52
diff changeset
197 # wifi but don't have an ip yet. We'll record an
f8cc3d1baa85 redo wifi scraper to work with zyxel router report page too. add last connected time (from mongo) to web table
drewp@bigasterisk.com
parents: 52
diff changeset
198 # action with no ip and then never record your ip.
f8cc3d1baa85 redo wifi scraper to work with zyxel router report page too. add last connected time (from mongo) to web table
drewp@bigasterisk.com
parents: 52
diff changeset
199 d['ip'] = addr['ip']
f8cc3d1baa85 redo wifi scraper to work with zyxel router report page too. add last connected time (from mongo) to web table
drewp@bigasterisk.com
parents: 52
diff changeset
200 return d
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
201
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
202 for addr in newWithSignal:
62
f8cc3d1baa85 redo wifi scraper to work with zyxel router report page too. add last connected time (from mongo) to web table
drewp@bigasterisk.com
parents: 52
diff changeset
203 if addr['mac'] not in [r['mac'] for r in self.lastWithSignal]:
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
204 actions.append(makeAction(addr, 'arrive'))
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
205
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
206 for addr in self.lastWithSignal:
62
f8cc3d1baa85 redo wifi scraper to work with zyxel router report page too. add last connected time (from mongo) to web table
drewp@bigasterisk.com
parents: 52
diff changeset
207 if addr['mac'] not in [r['mac'] for r in newWithSignal]:
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
208 actions.append(makeAction(addr, 'leave'))
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
209
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
210 return actions
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
211
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
212
1
26a6cf58743d entrancemusic improve logging
drewp@bigasterisk.com
parents: 0
diff changeset
213 # these need to move out to their own service
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
214 def doEntranceMusic(self, action):
1
26a6cf58743d entrancemusic improve logging
drewp@bigasterisk.com
parents: 0
diff changeset
215 import restkit, jsonlib
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
216 dt = self.deltaSinceLastArrive(action['name'])
1
26a6cf58743d entrancemusic improve logging
drewp@bigasterisk.com
parents: 0
diff changeset
217 log.debug("dt=%s", dt)
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
218 if dt > datetime.timedelta(hours=1):
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
219 hub = restkit.Resource(
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
220 # PSHB not working yet; "http://bang:9030/"
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
221 "http://slash:9049/"
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
222 )
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
223 action = action.copy()
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
224 del action['created']
1
26a6cf58743d entrancemusic improve logging
drewp@bigasterisk.com
parents: 0
diff changeset
225 del action['_id']
26a6cf58743d entrancemusic improve logging
drewp@bigasterisk.com
parents: 0
diff changeset
226 log.info("post to %s", hub)
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
227 hub.post("visitorNet", payload=jsonlib.dumps(action))
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
228
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
229 def deltaSinceLastArrive(self, name):
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
230 results = list(self.mongo.find({'name' : name}).sort('created',
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
231 DESCENDING).limit(1))
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
232 if not results:
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
233 return datetime.timedelta.max
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
234 now = datetime.datetime.now(tz.gettz('UTC'))
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
235 last = results[0]['created'].replace(tzinfo=tz.gettz('UTC'))
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
236 return now - last
51
d2842eedd56d rewrite tomatowifi from restkit to cyclone httpclient
drewp@bigasterisk.com
parents: 50
diff changeset
237
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
238
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
239 if __name__ == '__main__':
189
fc184ea1416d switch to docopt
drewp@bigasterisk.com
parents: 175
diff changeset
240 args = docopt.docopt('''
fc184ea1416d switch to docopt
drewp@bigasterisk.com
parents: 175
diff changeset
241 Usage:
fc184ea1416d switch to docopt
drewp@bigasterisk.com
parents: 175
diff changeset
242 tomatoWifi [options]
fc184ea1416d switch to docopt
drewp@bigasterisk.com
parents: 175
diff changeset
243
fc184ea1416d switch to docopt
drewp@bigasterisk.com
parents: 175
diff changeset
244 Options:
fc184ea1416d switch to docopt
drewp@bigasterisk.com
parents: 175
diff changeset
245 -v, --verbose more logging
fc184ea1416d switch to docopt
drewp@bigasterisk.com
parents: 175
diff changeset
246 --port=<n> serve on port [default: 9070]
fc184ea1416d switch to docopt
drewp@bigasterisk.com
parents: 175
diff changeset
247 --poll=<freq> poll frequency [default: .2]
fc184ea1416d switch to docopt
drewp@bigasterisk.com
parents: 175
diff changeset
248 ''')
fc184ea1416d switch to docopt
drewp@bigasterisk.com
parents: 175
diff changeset
249 if args['--verbose']:
fc184ea1416d switch to docopt
drewp@bigasterisk.com
parents: 175
diff changeset
250 from twisted.python import log as twlog
fc184ea1416d switch to docopt
drewp@bigasterisk.com
parents: 175
diff changeset
251 twlog.startLogging(sys.stdout)
fc184ea1416d switch to docopt
drewp@bigasterisk.com
parents: 175
diff changeset
252 log.setLevel(10)
fc184ea1416d switch to docopt
drewp@bigasterisk.com
parents: 175
diff changeset
253 log.setLevel(logging.DEBUG)
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
254
62
f8cc3d1baa85 redo wifi scraper to work with zyxel router report page too. add last connected time (from mongo) to web table
drewp@bigasterisk.com
parents: 52
diff changeset
255 mongo = Connection('bang', 27017, tz_aware=True)['visitor']['visitor']
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
256
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
257 wifi = Wifi()
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
258 poller = Poller(wifi, mongo)
189
fc184ea1416d switch to docopt
drewp@bigasterisk.com
parents: 175
diff changeset
259 task.LoopingCall(poller.poll).start(1/float(args['--poll']))
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
260
189
fc184ea1416d switch to docopt
drewp@bigasterisk.com
parents: 175
diff changeset
261 reactor.listenTCP(int(args['--port']),
62
f8cc3d1baa85 redo wifi scraper to work with zyxel router report page too. add last connected time (from mongo) to web table
drewp@bigasterisk.com
parents: 52
diff changeset
262 cyclone.web.Application(
f8cc3d1baa85 redo wifi scraper to work with zyxel router report page too. add last connected time (from mongo) to web table
drewp@bigasterisk.com
parents: 52
diff changeset
263 [
f8cc3d1baa85 redo wifi scraper to work with zyxel router report page too. add last connected time (from mongo) to web table
drewp@bigasterisk.com
parents: 52
diff changeset
264 (r"/", Index),
f8cc3d1baa85 redo wifi scraper to work with zyxel router report page too. add last connected time (from mongo) to web table
drewp@bigasterisk.com
parents: 52
diff changeset
265 (r'/json', Json),
f8cc3d1baa85 redo wifi scraper to work with zyxel router report page too. add last connected time (from mongo) to web table
drewp@bigasterisk.com
parents: 52
diff changeset
266 (r'/graph', GraphHandler),
f8cc3d1baa85 redo wifi scraper to work with zyxel router report page too. add last connected time (from mongo) to web table
drewp@bigasterisk.com
parents: 52
diff changeset
267 (r'/table', Table),
f8cc3d1baa85 redo wifi scraper to work with zyxel router report page too. add last connected time (from mongo) to web table
drewp@bigasterisk.com
parents: 52
diff changeset
268 #(r'/activity', Activity),
f8cc3d1baa85 redo wifi scraper to work with zyxel router report page too. add last connected time (from mongo) to web table
drewp@bigasterisk.com
parents: 52
diff changeset
269 ],
f8cc3d1baa85 redo wifi scraper to work with zyxel router report page too. add last connected time (from mongo) to web table
drewp@bigasterisk.com
parents: 52
diff changeset
270 wifi=wifi,
f8cc3d1baa85 redo wifi scraper to work with zyxel router report page too. add last connected time (from mongo) to web table
drewp@bigasterisk.com
parents: 52
diff changeset
271 poller=poller,
f8cc3d1baa85 redo wifi scraper to work with zyxel router report page too. add last connected time (from mongo) to web table
drewp@bigasterisk.com
parents: 52
diff changeset
272 mongo=mongo))
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
273 reactor.run()