annotate service/tomatoWifi/tomatoWifi.py @ 417:10ec2744fe8a

mongodb api upgrade Ignore-this: 2a09182f26109a2744f98d6babc64293
author drewp@bigasterisk.com
date Sat, 30 Mar 2019 16:56:31 -0700
parents 8f5a16a55f64
children b3935eac90e1
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
383
8f5a16a55f64 various docker setups and build fixes
drewp@bigasterisk.com
parents: 340
diff changeset
18
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
309
68c2a5f1d563 wifi write to influxdb
drewp@bigasterisk.com
parents: 279
diff changeset
23 from influxdb import InfluxDBClient
417
10ec2744fe8a mongodb api upgrade
drewp@bigasterisk.com
parents: 383
diff changeset
24 from pymongo import MongoClient as Connection, DESCENDING
340
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
25 from rdflib import Namespace, Literal, URIRef, ConjunctiveGraph
383
8f5a16a55f64 various docker setups and build fixes
drewp@bigasterisk.com
parents: 340
diff changeset
26
0
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
383
8f5a16a55f64 various docker setups and build fixes
drewp@bigasterisk.com
parents: 340
diff changeset
29
340
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
30 from patchablegraph import PatchableGraph, CycloneGraphEventsHandler, CycloneGraphHandler
383
8f5a16a55f64 various docker setups and build fixes
drewp@bigasterisk.com
parents: 340
diff changeset
31
340
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
32 from rdfdb.patch import Patch
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
33
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
34 from cycloneerr import PrettyErrorHandler
1
26a6cf58743d entrancemusic improve logging
drewp@bigasterisk.com
parents: 0
diff changeset
35 from logsetup import log
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
36
36
0ab069867c64 rdflib and jsonlib api updates
drewp@bigasterisk.com
parents: 1
diff changeset
37
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
38 DEV = Namespace("http://projects.bigasterisk.com/device/")
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
39 ROOM = Namespace("http://projects.bigasterisk.com/room/")
51
d2842eedd56d rewrite tomatowifi from restkit to cyclone httpclient
drewp@bigasterisk.com
parents: 50
diff changeset
40 reasoning = "http://bang:9071/"
1
26a6cf58743d entrancemusic improve logging
drewp@bigasterisk.com
parents: 0
diff changeset
41
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
42 class Index(PrettyErrorHandler, cyclone.web.RequestHandler):
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
43 def get(self):
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
44
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
45 age = time.time() - self.settings.poller.lastPollTime
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
46 if age > 10:
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
47 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
48
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
49 self.set_header("Content-Type", "text/html")
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
50 self.write(open("index.html").read())
51
d2842eedd56d rewrite tomatowifi from restkit to cyclone httpclient
drewp@bigasterisk.com
parents: 50
diff changeset
51
175
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
52 def whenConnected(mongo, macThatIsNowConnected):
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
53 lastArrive = None
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
54 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
55 sort=[('created', -1)],
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
56 max_scan=100000):
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
57 if ev['action'] == 'arrive':
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
58 lastArrive = ev
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
59 if ev['action'] == 'leave':
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
60 break
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
61 if lastArrive is None:
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
62 raise ValueError("no past arrivals")
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
63
175
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
64 return lastArrive['created']
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
65
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
66 def connectedAgoString(conn):
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
67 return web.utils.datestr(
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
68 conn.astimezone(tz.tzutc()).replace(tzinfo=None))
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
69
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
70 class Table(PrettyErrorHandler, cyclone.web.RequestHandler):
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
71 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
72 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
73 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
74 if 'name' not in row:
74
bca6d6c63bdc handle wifi users with no clientHostname
drewp@bigasterisk.com
parents: 62
diff changeset
75 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
76 if 'signal' not in row:
175
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
77 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
78
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 try:
175
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
80 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
81 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
82 except ValueError:
175
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
83 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
84 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
85 return row
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
86
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
87 self.set_header("Content-Type", "application/xhtml+xml")
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
88 self.write(pystache.render(
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
89 open("table.mustache").read(),
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
90 dict(
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
91 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
92 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
93 a.get('name'))))))
175
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
94
51
d2842eedd56d rewrite tomatowifi from restkit to cyclone httpclient
drewp@bigasterisk.com
parents: 50
diff changeset
95
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
96 class Json(PrettyErrorHandler, cyclone.web.RequestHandler):
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
97 def get(self):
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
98 self.set_header("Content-Type", "application/json")
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
99 age = time.time() - self.settings.poller.lastPollTime
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
100 if age > 10:
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
101 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
102 self.write(json.dumps({"wifi" : self.settings.poller.lastAddrs,
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
103 "dataAge" : age}))
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
104
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
105 class Poller(object):
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
106 def __init__(self, wifi, mongo):
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
107 self.wifi = wifi
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
108 self.mongo = mongo
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
109 self.lastAddrs = []
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
110 self.lastWithSignal = []
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
111 self.lastPollTime = 0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
112
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
113 def assertCurrent(self):
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
114 dt = time.time() - self.lastPollTime
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
115 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
116
d2842eedd56d rewrite tomatowifi from restkit to cyclone httpclient
drewp@bigasterisk.com
parents: 50
diff changeset
117 @inlineCallbacks
340
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
118 def poll(self):
175
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
119 connectedField = 'connected'
309
68c2a5f1d563 wifi write to influxdb
drewp@bigasterisk.com
parents: 279
diff changeset
120 now = int(time.time())
175
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
121
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
122 # UVA mode:
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
123 addDhcpData = lambda *args: None
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
124
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
125 try:
51
d2842eedd56d rewrite tomatowifi from restkit to cyclone httpclient
drewp@bigasterisk.com
parents: 50
diff changeset
126 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
127 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
128
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
129 newWithSignal = [a for a in newAddrs if a.get('connected')]
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
130
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
131 actions = self.computeActions(newWithSignal)
309
68c2a5f1d563 wifi write to influxdb
drewp@bigasterisk.com
parents: 279
diff changeset
132 points = []
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
133 for action in actions:
1
26a6cf58743d entrancemusic improve logging
drewp@bigasterisk.com
parents: 0
diff changeset
134 log.info("action: %s", action)
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
135 action['created'] = datetime.datetime.now(tz.gettz('UTC'))
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
136 mongo.save(action)
309
68c2a5f1d563 wifi write to influxdb
drewp@bigasterisk.com
parents: 279
diff changeset
137 points.append(
68c2a5f1d563 wifi write to influxdb
drewp@bigasterisk.com
parents: 279
diff changeset
138 self.influxPoint(now, action['address'].lower(),
68c2a5f1d563 wifi write to influxdb
drewp@bigasterisk.com
parents: 279
diff changeset
139 1 if action['action'] == 'arrive' else 0))
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
140 try:
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
141 self.doEntranceMusic(action)
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
142 except Exception, e:
1
26a6cf58743d entrancemusic improve logging
drewp@bigasterisk.com
parents: 0
diff changeset
143 log.error("entrancemusic error: %r", e)
51
d2842eedd56d rewrite tomatowifi from restkit to cyclone httpclient
drewp@bigasterisk.com
parents: 50
diff changeset
144
309
68c2a5f1d563 wifi write to influxdb
drewp@bigasterisk.com
parents: 279
diff changeset
145 if now // 3600 > self.lastPollTime // 3600:
68c2a5f1d563 wifi write to influxdb
drewp@bigasterisk.com
parents: 279
diff changeset
146 log.info('hourly writes')
68c2a5f1d563 wifi write to influxdb
drewp@bigasterisk.com
parents: 279
diff changeset
147 for addr in newWithSignal:
68c2a5f1d563 wifi write to influxdb
drewp@bigasterisk.com
parents: 279
diff changeset
148 points.append(self.influxPoint(now, addr['mac'].lower(), 1))
68c2a5f1d563 wifi write to influxdb
drewp@bigasterisk.com
parents: 279
diff changeset
149
68c2a5f1d563 wifi write to influxdb
drewp@bigasterisk.com
parents: 279
diff changeset
150 influx.write_points(points, time_precision='s')
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
151 self.lastWithSignal = newWithSignal
50
56eeda98cac5 ping reasoning
drewp@bigasterisk.com
parents: 36
diff changeset
152 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
153 fetch(reasoning + "immediateUpdate",
279
57c9dbd2fdd0 immediate mode needs a PUT request
drewp@bigasterisk.com
parents: 189
diff changeset
154 method='PUT',
52
875a37be1228 fix fetch calls in tomatowifi
drewp@bigasterisk.com
parents: 51
diff changeset
155 timeout=2,
875a37be1228 fix fetch calls in tomatowifi
drewp@bigasterisk.com
parents: 51
diff changeset
156 headers={'user-agent': ['tomatoWifi']}).addErrback(log.warn)
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
157 self.lastAddrs = newAddrs
309
68c2a5f1d563 wifi write to influxdb
drewp@bigasterisk.com
parents: 279
diff changeset
158 self.lastPollTime = now
340
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
159
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
160 self.updateGraph(masterGraph)
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
161 except Exception, e:
175
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
162 log.error("poll error: %r\n%s", e, traceback.format_exc())
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
163
309
68c2a5f1d563 wifi write to influxdb
drewp@bigasterisk.com
parents: 279
diff changeset
164 def influxPoint(self, now, address, value):
68c2a5f1d563 wifi write to influxdb
drewp@bigasterisk.com
parents: 279
diff changeset
165 return {
68c2a5f1d563 wifi write to influxdb
drewp@bigasterisk.com
parents: 279
diff changeset
166 'measurement': 'presence',
68c2a5f1d563 wifi write to influxdb
drewp@bigasterisk.com
parents: 279
diff changeset
167 'tags': {'sensor': 'wifi', 'address': address,},
68c2a5f1d563 wifi write to influxdb
drewp@bigasterisk.com
parents: 279
diff changeset
168 'fields': {'value': value},
68c2a5f1d563 wifi write to influxdb
drewp@bigasterisk.com
parents: 279
diff changeset
169 'time': now,
68c2a5f1d563 wifi write to influxdb
drewp@bigasterisk.com
parents: 279
diff changeset
170 }
68c2a5f1d563 wifi write to influxdb
drewp@bigasterisk.com
parents: 279
diff changeset
171
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
172 def computeActions(self, newWithSignal):
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
173 actions = []
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
174
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
175 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
176 d = dict(sensor="wifi",
175
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
177 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
178 name=addr.get('name'),
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
179 networkName=addr.get('clientHostname'),
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
180 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
181 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
182 # 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
183 # 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
184 # 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
185 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
186 return d
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
187
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
188 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
189 if addr['mac'] not in [r['mac'] for r in self.lastWithSignal]:
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
190 actions.append(makeAction(addr, 'arrive'))
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
191
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
192 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
193 if addr['mac'] not in [r['mac'] for r in newWithSignal]:
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
194 actions.append(makeAction(addr, 'leave'))
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
195
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
196 return actions
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
197
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
198
1
26a6cf58743d entrancemusic improve logging
drewp@bigasterisk.com
parents: 0
diff changeset
199 # these need to move out to their own service
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
200 def doEntranceMusic(self, action):
383
8f5a16a55f64 various docker setups and build fixes
drewp@bigasterisk.com
parents: 340
diff changeset
201 import restkit, json
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
202 dt = self.deltaSinceLastArrive(action['name'])
1
26a6cf58743d entrancemusic improve logging
drewp@bigasterisk.com
parents: 0
diff changeset
203 log.debug("dt=%s", dt)
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
204 if dt > datetime.timedelta(hours=1):
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
205 hub = restkit.Resource(
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
206 # PSHB not working yet; "http://bang:9030/"
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
207 "http://slash:9049/"
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
208 )
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
209 action = action.copy()
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
210 del action['created']
1
26a6cf58743d entrancemusic improve logging
drewp@bigasterisk.com
parents: 0
diff changeset
211 del action['_id']
26a6cf58743d entrancemusic improve logging
drewp@bigasterisk.com
parents: 0
diff changeset
212 log.info("post to %s", hub)
383
8f5a16a55f64 various docker setups and build fixes
drewp@bigasterisk.com
parents: 340
diff changeset
213 hub.post("visitorNet", payload=json.dumps(action))
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
214
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
215 def deltaSinceLastArrive(self, name):
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
216 results = list(self.mongo.find({'name' : name}).sort('created',
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
217 DESCENDING).limit(1))
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
218 if not results:
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
219 return datetime.timedelta.max
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
220 now = datetime.datetime.now(tz.gettz('UTC'))
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
221 last = results[0]['created'].replace(tzinfo=tz.gettz('UTC'))
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
222 return now - last
51
d2842eedd56d rewrite tomatowifi from restkit to cyclone httpclient
drewp@bigasterisk.com
parents: 50
diff changeset
223
340
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
224 def updateGraph(self, masterGraph):
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
225
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
226 g = ConjunctiveGraph()
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
227 ctx = DEV['wifi']
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
228
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
229 # someday i may also record specific AP and their strength,
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
230 # for positioning. But many users just want to know that the
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
231 # device is connected to some bigasterisk AP.
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
232 age = time.time() - self.lastPollTime
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
233 if age > 10:
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
234 raise ValueError("poll data is stale. age=%s" % age)
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
235
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
236 for dev in self.lastAddrs:
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
237 if not dev.get('connected'):
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
238 continue
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
239 uri = URIRef("http://bigasterisk.com/mac/%s" % dev['mac'].lower())
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
240 g.add((uri, ROOM['macAddress'], Literal(dev['mac'].lower()), ctx))
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
241
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
242 g.add((uri, ROOM['connected'], {
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
243 'wireless': URIRef("http://bigasterisk.com/wifiAccessPoints"),
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
244 '2.4G': URIRef("http://bigasterisk.com/wifiAccessPoints"),
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
245 '5G': URIRef("http://bigasterisk.com/wifiAccessPoints"),
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
246 'wired': URIRef("http://bigasterisk.com/houseOpenNet")}[dev['contype']], ctx))
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
247 if 'clientHostname' in dev and dev['clientHostname']:
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
248 g.add((uri, ROOM['wifiNetworkName'], Literal(dev['clientHostname']), ctx))
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
249 if 'name' in dev and dev['name']:
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
250 g.add((uri, ROOM['deviceName'], Literal(dev['name']), ctx))
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
251 if 'signal' in dev:
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
252 g.add((uri, ROOM['signalStrength'], Literal(dev['signal']), ctx))
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
253 if 'model' in dev:
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
254 g.add((uri, ROOM['networkModel'], Literal(dev['model']), ctx))
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
255 try:
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
256 conn = whenConnected(mongo, dev['mac'])
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
257 except ValueError:
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
258 traceback.print_exc()
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
259 pass
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
260 else:
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
261 g.add((uri, ROOM['connectedAgo'],
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
262 Literal(connectedAgoString(conn)), ctx))
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
263 g.add((uri, ROOM['connected'], Literal(conn), ctx))
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
264 masterGraph.setToGraph(g)
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
265
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
266
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
267 if __name__ == '__main__':
189
fc184ea1416d switch to docopt
drewp@bigasterisk.com
parents: 175
diff changeset
268 args = docopt.docopt('''
fc184ea1416d switch to docopt
drewp@bigasterisk.com
parents: 175
diff changeset
269 Usage:
fc184ea1416d switch to docopt
drewp@bigasterisk.com
parents: 175
diff changeset
270 tomatoWifi [options]
fc184ea1416d switch to docopt
drewp@bigasterisk.com
parents: 175
diff changeset
271
fc184ea1416d switch to docopt
drewp@bigasterisk.com
parents: 175
diff changeset
272 Options:
fc184ea1416d switch to docopt
drewp@bigasterisk.com
parents: 175
diff changeset
273 -v, --verbose more logging
fc184ea1416d switch to docopt
drewp@bigasterisk.com
parents: 175
diff changeset
274 --port=<n> serve on port [default: 9070]
fc184ea1416d switch to docopt
drewp@bigasterisk.com
parents: 175
diff changeset
275 --poll=<freq> poll frequency [default: .2]
fc184ea1416d switch to docopt
drewp@bigasterisk.com
parents: 175
diff changeset
276 ''')
fc184ea1416d switch to docopt
drewp@bigasterisk.com
parents: 175
diff changeset
277 if args['--verbose']:
fc184ea1416d switch to docopt
drewp@bigasterisk.com
parents: 175
diff changeset
278 from twisted.python import log as twlog
fc184ea1416d switch to docopt
drewp@bigasterisk.com
parents: 175
diff changeset
279 twlog.startLogging(sys.stdout)
fc184ea1416d switch to docopt
drewp@bigasterisk.com
parents: 175
diff changeset
280 log.setLevel(10)
fc184ea1416d switch to docopt
drewp@bigasterisk.com
parents: 175
diff changeset
281 log.setLevel(logging.DEBUG)
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
282
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
283 mongo = Connection('bang', 27017, tz_aware=True)['visitor']['visitor']
309
68c2a5f1d563 wifi write to influxdb
drewp@bigasterisk.com
parents: 279
diff changeset
284 influx = InfluxDBClient('bang', 9060, 'root', 'root', 'main')
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
285
340
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
286 masterGraph = PatchableGraph()
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
287 wifi = Wifi()
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
288 poller = Poller(wifi, mongo)
189
fc184ea1416d switch to docopt
drewp@bigasterisk.com
parents: 175
diff changeset
289 task.LoopingCall(poller.poll).start(1/float(args['--poll']))
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
290
189
fc184ea1416d switch to docopt
drewp@bigasterisk.com
parents: 175
diff changeset
291 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
292 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
293 [
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
294 (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
295 (r'/json', Json),
340
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
296 (r'/graph', CycloneGraphHandler, {'masterGraph': masterGraph}),
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
297 (r'/graph/events', CycloneGraphEventsHandler, {'masterGraph': masterGraph}),
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
298 (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
299 #(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
300 ],
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
301 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
302 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
303 mongo=mongo))
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
304 reactor.run()