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