annotate service/wifi/wifi.py @ 427:db031d9ec28e

don't use 'connected' for time and for network. add rdf:type. Ignore-this: 59899796d4785300f40137de2c2c44d5
author drewp@bigasterisk.com
date Thu, 04 Apr 2019 02:19:10 -0700
parents e0703c7824e9
children d0830394bf7b
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
1 """
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
2 scrape the tomato router status pages to see who's connected to the
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
3 wifi access points. Includes leases that aren't currently connected.
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
4
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
5 Returns:
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
6 json listing (for magma page)
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
7 rdf graph (for reasoning)
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
8 activity stream, when we start saving history
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
9
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
10 Todo: this should be the one polling and writing to mongo, not entrancemusic
162
bb70eaa45666 whitespace
drewp@bigasterisk.com
parents: 161
diff changeset
11
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
12 """
423
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
13 import sys, json, traceback, time, datetime, logging
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
14 from typing import List
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
15
51
d2842eedd56d rewrite tomatowifi from restkit to cyclone httpclient
drewp@bigasterisk.com
parents: 50
diff changeset
16 from cyclone.httpclient import fetch
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
17 from dateutil import tz
423
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
18 from influxdb import InfluxDBClient
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
19 from pymongo import MongoClient as Connection, DESCENDING
427
db031d9ec28e don't use 'connected' for time and for network. add rdf:type.
drewp@bigasterisk.com
parents: 423
diff changeset
20 from rdflib import Namespace, Literal, ConjunctiveGraph, RDF
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
21 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
22 from twisted.internet.defer import inlineCallbacks
423
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
23 import ago
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
24 import cyclone.web
189
fc184ea1416d switch to docopt
drewp@bigasterisk.com
parents: 175
diff changeset
25 import docopt
423
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
26 import pystache
383
8f5a16a55f64 various docker setups and build fixes
drewp@bigasterisk.com
parents: 340
diff changeset
27
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
28 from cycloneerr import PrettyErrorHandler
1
26a6cf58743d entrancemusic improve logging
drewp@bigasterisk.com
parents: 0
diff changeset
29 from logsetup import log
423
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
30 from patchablegraph import PatchableGraph, CycloneGraphEventsHandler, CycloneGraphHandler
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
31 from scrape import Wifi, SeenNode
36
0ab069867c64 rdflib and jsonlib api updates
drewp@bigasterisk.com
parents: 1
diff changeset
32
422
19460b3f7baf factor out some URI generation
drewp@bigasterisk.com
parents: 421
diff changeset
33 AST = Namespace("http://bigasterisk.com/")
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
34 DEV = Namespace("http://projects.bigasterisk.com/device/")
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
35 ROOM = Namespace("http://projects.bigasterisk.com/room/")
51
d2842eedd56d rewrite tomatowifi from restkit to cyclone httpclient
drewp@bigasterisk.com
parents: 50
diff changeset
36 reasoning = "http://bang:9071/"
1
26a6cf58743d entrancemusic improve logging
drewp@bigasterisk.com
parents: 0
diff changeset
37
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
38 class Index(PrettyErrorHandler, cyclone.web.RequestHandler):
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
39 def get(self):
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
40 age = time.time() - self.settings.poller.lastPollTime
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
41 if age > 10:
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
42 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
43
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
44 self.set_header("Content-Type", "text/html")
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
45 self.write(open("index.html").read())
51
d2842eedd56d rewrite tomatowifi from restkit to cyclone httpclient
drewp@bigasterisk.com
parents: 50
diff changeset
46
175
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
47 def whenConnected(mongo, macThatIsNowConnected):
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
48 lastArrive = None
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
49 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
50 sort=[('created', -1)],
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
51 max_scan=100000):
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
52 if ev['action'] == 'arrive':
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
53 lastArrive = ev
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
54 if ev['action'] == 'leave':
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
55 break
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
56 if lastArrive is None:
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
57 raise ValueError("no past arrivals")
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
58
175
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
59 return lastArrive['created']
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
60
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
61 def connectedAgoString(conn):
423
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
62 return ago.human(conn.astimezone(tz.tzutc()).replace(tzinfo=None))
175
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
63
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
64 class Table(PrettyErrorHandler, cyclone.web.RequestHandler):
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
65 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
66 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
67 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
68 if 'name' not in row:
74
bca6d6c63bdc handle wifi users with no clientHostname
drewp@bigasterisk.com
parents: 62
diff changeset
69 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
70 if 'signal' not in row:
175
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
71 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
72
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 try:
175
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
74 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
75 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
76 except ValueError:
175
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
77 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
78 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
79 return row
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
80
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
81 self.set_header("Content-Type", "application/xhtml+xml")
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
82 self.write(pystache.render(
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
83 open("table.mustache").read(),
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
84 dict(
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
85 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
86 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
87 a.get('name'))))))
51
d2842eedd56d rewrite tomatowifi from restkit to cyclone httpclient
drewp@bigasterisk.com
parents: 50
diff changeset
88
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
89 class Json(PrettyErrorHandler, cyclone.web.RequestHandler):
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
90 def get(self):
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
91 self.set_header("Content-Type", "application/json")
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
92 age = time.time() - self.settings.poller.lastPollTime
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
93 if age > 10:
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
94 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
95 self.write(json.dumps({"wifi" : self.settings.poller.lastAddrs,
423
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
96 "dataAge" : age}))
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
97
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
98 class Poller(object):
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
99 def __init__(self, wifi, mongo):
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
100 self.wifi = wifi
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
101 self.mongo = mongo
423
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
102 self.lastAddrs = [] # List[SeenNode]
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
103 self.lastWithSignal = []
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
104 self.lastPollTime = 0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
105
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
106 def assertCurrent(self):
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
107 dt = time.time() - self.lastPollTime
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
108 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
109
d2842eedd56d rewrite tomatowifi from restkit to cyclone httpclient
drewp@bigasterisk.com
parents: 50
diff changeset
110 @inlineCallbacks
340
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
111 def poll(self):
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
112 try:
51
d2842eedd56d rewrite tomatowifi from restkit to cyclone httpclient
drewp@bigasterisk.com
parents: 50
diff changeset
113 newAddrs = yield self.wifi.getPresentMacAddrs()
423
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
114 self.onNodes(newAddrs)
421
47d7dd31bb2c port to py3
drewp@bigasterisk.com
parents: 420
diff changeset
115 except Exception as e:
175
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
116 log.error("poll error: %r\n%s", e, traceback.format_exc())
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
117
423
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
118 def onNodes(self, newAddrs: List[SeenNode]):
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
119 now = int(time.time())
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
120 newWithSignal = [a for a in newAddrs if a.connected]
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
121
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
122 actions = self.computeActions(newWithSignal)
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
123 points = []
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
124 for action in actions:
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
125 log.info("action: %s", action)
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
126 action['created'] = datetime.datetime.now(tz.gettz('UTC'))
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
127 mongo.save(action)
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
128 points.append(
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
129 self.influxPoint(now, action['address'].lower(),
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
130 1 if action['action'] == 'arrive' else 0))
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
131 if now // 3600 > self.lastPollTime // 3600:
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
132 log.info('hourly writes')
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
133 for addr in newWithSignal:
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
134 points.append(self.influxPoint(now, addr.mac.lower(), 1))
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
135
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
136 influx.write_points(points, time_precision='s')
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
137 self.lastWithSignal = newWithSignal
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
138 if actions: # this doesn't currently include signal strength changes
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
139 fetch(reasoning + "immediateUpdate",
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
140 method='PUT',
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
141 timeout=2,
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
142 headers={'user-agent': ['wifi']}).addErrback(log.warn)
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
143 self.lastAddrs = newAddrs
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
144 self.lastPollTime = now
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
145
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
146 self.updateGraph(masterGraph)
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
147
309
68c2a5f1d563 wifi write to influxdb
drewp@bigasterisk.com
parents: 279
diff changeset
148 def influxPoint(self, now, address, value):
68c2a5f1d563 wifi write to influxdb
drewp@bigasterisk.com
parents: 279
diff changeset
149 return {
68c2a5f1d563 wifi write to influxdb
drewp@bigasterisk.com
parents: 279
diff changeset
150 'measurement': 'presence',
68c2a5f1d563 wifi write to influxdb
drewp@bigasterisk.com
parents: 279
diff changeset
151 'tags': {'sensor': 'wifi', 'address': address,},
68c2a5f1d563 wifi write to influxdb
drewp@bigasterisk.com
parents: 279
diff changeset
152 'fields': {'value': value},
68c2a5f1d563 wifi write to influxdb
drewp@bigasterisk.com
parents: 279
diff changeset
153 'time': now,
68c2a5f1d563 wifi write to influxdb
drewp@bigasterisk.com
parents: 279
diff changeset
154 }
68c2a5f1d563 wifi write to influxdb
drewp@bigasterisk.com
parents: 279
diff changeset
155
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
156 def computeActions(self, newWithSignal):
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
157 actions = []
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
158
423
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
159 def makeAction(addr: SeenNode, act: str):
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
160 d = dict(sensor="wifi",
423
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
161 address=addr.mac.upper(), # mongo data is legacy uppercase
175
c81a451f9b26 rewrites for better graph export, removal of dhcp reader
drewp@bigasterisk.com
parents: 162
diff changeset
162 action=act)
423
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
163 if act == 'arrive':
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
164 # 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
165 # 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
166 # action with no ip and then never record your ip.
423
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
167 d['ip'] = addr.ip
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
168 return d
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
169
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
170 for addr in newWithSignal:
423
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
171 if addr.mac not in [r.mac for r in self.lastWithSignal]:
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
172 actions.append(makeAction(addr, 'arrive'))
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
173
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
174 for addr in self.lastWithSignal:
423
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
175 if addr.mac not in [r.mac for r in newWithSignal]:
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
176 actions.append(makeAction(addr, 'leave'))
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
177
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
178 return actions
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
179
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
180 def deltaSinceLastArrive(self, name):
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
181 results = list(self.mongo.find({'name' : name}).sort('created',
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
182 DESCENDING).limit(1))
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
183 if not results:
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
184 return datetime.timedelta.max
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
185 now = datetime.datetime.now(tz.gettz('UTC'))
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
186 last = results[0]['created'].replace(tzinfo=tz.gettz('UTC'))
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
187 return now - last
51
d2842eedd56d rewrite tomatowifi from restkit to cyclone httpclient
drewp@bigasterisk.com
parents: 50
diff changeset
188
340
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
189 def updateGraph(self, masterGraph):
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
190 g = ConjunctiveGraph()
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
191 ctx = DEV['wifi']
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
192
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
193 # someday i may also record specific AP and their strength,
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
194 # for positioning. But many users just want to know that the
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
195 # device is connected to some bigasterisk AP.
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
196 age = time.time() - self.lastPollTime
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
197 if age > 10:
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
198 raise ValueError("poll data is stale. age=%s" % age)
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
199
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
200 for dev in self.lastAddrs:
423
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
201 if not dev.connected:
340
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
202 continue
427
db031d9ec28e don't use 'connected' for time and for network. add rdf:type.
drewp@bigasterisk.com
parents: 423
diff changeset
203 g.add((dev.uri, RDF.type, ROOM['NetworkedDevice'], ctx))
423
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
204 g.add((dev.uri, ROOM['macAddress'], Literal(dev.mac), ctx))
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
205 g.add((dev.uri, ROOM['ipAddress'], Literal(dev.ip), ctx))
340
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
206
423
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
207 for s,p,o in dev.stmts:
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
208 g.add((s, p, o, ctx))
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
209
340
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
210 try:
423
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
211 conn = whenConnected(mongo, dev.mac)
340
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
212 except ValueError:
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
213 traceback.print_exc()
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
214 pass
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
215 else:
423
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
216 g.add((dev.uri, ROOM['connectedAgo'],
340
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
217 Literal(connectedAgoString(conn)), ctx))
423
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
218 g.add((dev.uri, ROOM['connected'], Literal(conn), ctx))
340
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
219 masterGraph.setToGraph(g)
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
220
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
221
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
222 if __name__ == '__main__':
189
fc184ea1416d switch to docopt
drewp@bigasterisk.com
parents: 175
diff changeset
223 args = docopt.docopt('''
fc184ea1416d switch to docopt
drewp@bigasterisk.com
parents: 175
diff changeset
224 Usage:
423
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
225 wifi.py [options]
189
fc184ea1416d switch to docopt
drewp@bigasterisk.com
parents: 175
diff changeset
226
fc184ea1416d switch to docopt
drewp@bigasterisk.com
parents: 175
diff changeset
227 Options:
fc184ea1416d switch to docopt
drewp@bigasterisk.com
parents: 175
diff changeset
228 -v, --verbose more logging
fc184ea1416d switch to docopt
drewp@bigasterisk.com
parents: 175
diff changeset
229 --port=<n> serve on port [default: 9070]
fc184ea1416d switch to docopt
drewp@bigasterisk.com
parents: 175
diff changeset
230 --poll=<freq> poll frequency [default: .2]
fc184ea1416d switch to docopt
drewp@bigasterisk.com
parents: 175
diff changeset
231 ''')
fc184ea1416d switch to docopt
drewp@bigasterisk.com
parents: 175
diff changeset
232 if args['--verbose']:
fc184ea1416d switch to docopt
drewp@bigasterisk.com
parents: 175
diff changeset
233 from twisted.python import log as twlog
fc184ea1416d switch to docopt
drewp@bigasterisk.com
parents: 175
diff changeset
234 twlog.startLogging(sys.stdout)
fc184ea1416d switch to docopt
drewp@bigasterisk.com
parents: 175
diff changeset
235 log.setLevel(10)
fc184ea1416d switch to docopt
drewp@bigasterisk.com
parents: 175
diff changeset
236 log.setLevel(logging.DEBUG)
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
237
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
238 mongo = Connection('bang', 27017, tz_aware=True)['visitor']['visitor']
309
68c2a5f1d563 wifi write to influxdb
drewp@bigasterisk.com
parents: 279
diff changeset
239 influx = InfluxDBClient('bang', 9060, 'root', 'root', 'main')
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
240
423
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
241 config = ConjunctiveGraph()
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
242 config.parse(open('private_config.n3'), format='n3')
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
243
340
70954bd426be wifi now uses PatchableGraph
drewp@bigasterisk.com
parents: 309
diff changeset
244 masterGraph = PatchableGraph()
423
e0703c7824e9 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp@bigasterisk.com
parents: 422
diff changeset
245 wifi = Wifi(config)
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
246 poller = Poller(wifi, mongo)
189
fc184ea1416d switch to docopt
drewp@bigasterisk.com
parents: 175
diff changeset
247 task.LoopingCall(poller.poll).start(1/float(args['--poll']))
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
248
422
19460b3f7baf factor out some URI generation
drewp@bigasterisk.com
parents: 421
diff changeset
249 reactor.listenTCP(
19460b3f7baf factor out some URI generation
drewp@bigasterisk.com
parents: 421
diff changeset
250 int(args['--port']),
19460b3f7baf factor out some URI generation
drewp@bigasterisk.com
parents: 421
diff changeset
251 cyclone.web.Application(
19460b3f7baf factor out some URI generation
drewp@bigasterisk.com
parents: 421
diff changeset
252 [
19460b3f7baf factor out some URI generation
drewp@bigasterisk.com
parents: 421
diff changeset
253 (r"/", Index),
19460b3f7baf factor out some URI generation
drewp@bigasterisk.com
parents: 421
diff changeset
254 (r'/json', Json),
19460b3f7baf factor out some URI generation
drewp@bigasterisk.com
parents: 421
diff changeset
255 (r'/graph', CycloneGraphHandler, {'masterGraph': masterGraph}),
19460b3f7baf factor out some URI generation
drewp@bigasterisk.com
parents: 421
diff changeset
256 (r'/graph/events', CycloneGraphEventsHandler, {'masterGraph': masterGraph}),
19460b3f7baf factor out some URI generation
drewp@bigasterisk.com
parents: 421
diff changeset
257 (r'/table', Table),
19460b3f7baf factor out some URI generation
drewp@bigasterisk.com
parents: 421
diff changeset
258 #(r'/activity', Activity),
19460b3f7baf factor out some URI generation
drewp@bigasterisk.com
parents: 421
diff changeset
259 ],
19460b3f7baf factor out some URI generation
drewp@bigasterisk.com
parents: 421
diff changeset
260 wifi=wifi,
19460b3f7baf factor out some URI generation
drewp@bigasterisk.com
parents: 421
diff changeset
261 poller=poller,
19460b3f7baf factor out some URI generation
drewp@bigasterisk.com
parents: 421
diff changeset
262 mongo=mongo))
0
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
263 reactor.run()