annotate service/wifi/wifi.py @ 1464:32d134dbfb1e

start ts config files, but this doesn't share the streamed-graph code properly yet Ignore-this: ef4e6fdf3369939b062caa5fdc2788e9 darcs-hash:e30e71ea5e8e9958c254c9210cdccde7a74b96bb
author drewp <drewp@bigasterisk.com>
date Tue, 17 Dec 2019 23:16:53 -0800
parents 517cbb905d4c
children 2e598cbcabf4
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1224
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
1 """
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
2 scrape the tomato router status pages to see who's connected to the
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
3 wifi access points. Includes leases that aren't currently connected.
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
4
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
5 Returns:
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
6 json listing (for magma page)
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
7 rdf graph (for reasoning)
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
8 activity stream, when we start saving history
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
9
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
10 Todo: this should be the one polling and writing to mongo, not entrancemusic
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
11
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
12 """
1226
7de8f0cd3392 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp <drewp@bigasterisk.com>
parents: 1225
diff changeset
13 import sys, json, traceback, time, datetime, logging
7de8f0cd3392 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp <drewp@bigasterisk.com>
parents: 1225
diff changeset
14 from typing import List
7de8f0cd3392 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp <drewp@bigasterisk.com>
parents: 1225
diff changeset
15
1223
34de6cfa0b6b rename historical 'tomatoWifi'
drewp <drewp@bigasterisk.com>
parents:
diff changeset
16 from cyclone.httpclient import fetch
1224
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
17 from dateutil import tz
1226
7de8f0cd3392 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp <drewp@bigasterisk.com>
parents: 1225
diff changeset
18 from influxdb import InfluxDBClient
7de8f0cd3392 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp <drewp@bigasterisk.com>
parents: 1225
diff changeset
19 from pymongo import MongoClient as Connection, DESCENDING
1230
ec0db53aa833 don't use 'connected' for time and for network. add rdf:type.
drewp <drewp@bigasterisk.com>
parents: 1226
diff changeset
20 from rdflib import Namespace, Literal, ConjunctiveGraph, RDF
1224
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
21 from twisted.internet import reactor, task
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
22 from twisted.internet.defer import inlineCallbacks
1226
7de8f0cd3392 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp <drewp@bigasterisk.com>
parents: 1225
diff changeset
23 import ago
7de8f0cd3392 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp <drewp@bigasterisk.com>
parents: 1225
diff changeset
24 import cyclone.web
1224
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
25 import docopt
1226
7de8f0cd3392 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp <drewp@bigasterisk.com>
parents: 1225
diff changeset
26 import pystache
1224
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
27
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
28 from cycloneerr import PrettyErrorHandler
1367
b287950fbcf4 update build on service/wifi
drewp <drewp@bigasterisk.com>
parents: 1230
diff changeset
29 from standardservice.logsetup import log
1226
7de8f0cd3392 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp <drewp@bigasterisk.com>
parents: 1225
diff changeset
30 from patchablegraph import PatchableGraph, CycloneGraphEventsHandler, CycloneGraphHandler
7de8f0cd3392 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp <drewp@bigasterisk.com>
parents: 1225
diff changeset
31 from scrape import Wifi, SeenNode
1224
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
32
1225
b8c0daabe5a5 factor out some URI generation
drewp <drewp@bigasterisk.com>
parents: 1224
diff changeset
33 AST = Namespace("http://bigasterisk.com/")
1224
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
34 DEV = Namespace("http://projects.bigasterisk.com/device/")
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
35 ROOM = Namespace("http://projects.bigasterisk.com/room/")
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
36
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
37 class Index(PrettyErrorHandler, cyclone.web.RequestHandler):
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
38 def get(self):
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
39 age = time.time() - self.settings.poller.lastPollTime
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
40 if age > 10:
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
41 raise ValueError("poll data is stale. age=%s" % age)
1461
517cbb905d4c remote suspend, wifi group arg
drewp <drewp@bigasterisk.com>
parents: 1369
diff changeset
42
1224
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
43 self.set_header("Content-Type", "text/html")
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
44 self.write(open("index.html").read())
1223
34de6cfa0b6b rename historical 'tomatoWifi'
drewp <drewp@bigasterisk.com>
parents:
diff changeset
45
1224
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
46 def whenConnected(mongo, macThatIsNowConnected):
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
47 lastArrive = None
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
48 for ev in mongo.find({'address': macThatIsNowConnected.upper()},
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
49 sort=[('created', -1)],
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
50 max_scan=100000):
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
51 if ev['action'] == 'arrive':
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
52 lastArrive = ev
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
53 if ev['action'] == 'leave':
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
54 break
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
55 if lastArrive is None:
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
56 raise ValueError("no past arrivals")
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
57
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
58 return lastArrive['created']
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
59
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
60 def connectedAgoString(conn):
1226
7de8f0cd3392 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp <drewp@bigasterisk.com>
parents: 1225
diff changeset
61 return ago.human(conn.astimezone(tz.tzutc()).replace(tzinfo=None))
1461
517cbb905d4c remote suspend, wifi group arg
drewp <drewp@bigasterisk.com>
parents: 1369
diff changeset
62
1224
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
63 class Table(PrettyErrorHandler, cyclone.web.RequestHandler):
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
64 def get(self):
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
65 def rowDict(row):
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
66 row['cls'] = "signal" if row.get('connected') else "nosignal"
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
67 if 'name' not in row:
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
68 row['name'] = row.get('clientHostname', '-')
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
69 if 'signal' not in row:
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
70 row['signal'] = 'yes' if row.get('connected') else 'no'
1223
34de6cfa0b6b rename historical 'tomatoWifi'
drewp <drewp@bigasterisk.com>
parents:
diff changeset
71
1224
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
72 try:
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
73 conn = whenConnected(self.settings.mongo, row.get('mac', '??'))
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
74 row['connectedAgo'] = connectedAgoString(conn)
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
75 except ValueError:
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
76 row['connectedAgo'] = 'yes' if row.get('connected') else ''
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
77 row['router'] = row.get('ssid', '')
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
78 return row
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
79
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
80 self.set_header("Content-Type", "application/xhtml+xml")
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
81 self.write(pystache.render(
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
82 open("table.mustache").read(),
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
83 dict(
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
84 rows=sorted(map(rowDict, self.settings.poller.lastAddrs),
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
85 key=lambda a: (not a.get('connected'),
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
86 a.get('name'))))))
1223
34de6cfa0b6b rename historical 'tomatoWifi'
drewp <drewp@bigasterisk.com>
parents:
diff changeset
87
1224
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
88 class Json(PrettyErrorHandler, cyclone.web.RequestHandler):
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
89 def get(self):
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
90 self.set_header("Content-Type", "application/json")
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
91 age = time.time() - self.settings.poller.lastPollTime
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
92 if age > 10:
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
93 raise ValueError("poll data is stale. age=%s" % age)
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
94 self.write(json.dumps({"wifi" : self.settings.poller.lastAddrs,
1226
7de8f0cd3392 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp <drewp@bigasterisk.com>
parents: 1225
diff changeset
95 "dataAge" : age}))
1224
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
96
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
97 class Poller(object):
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
98 def __init__(self, wifi, mongo):
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
99 self.wifi = wifi
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
100 self.mongo = mongo
1226
7de8f0cd3392 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp <drewp@bigasterisk.com>
parents: 1225
diff changeset
101 self.lastAddrs = [] # List[SeenNode]
1224
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
102 self.lastWithSignal = []
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
103 self.lastPollTime = 0
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
104
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
105 def assertCurrent(self):
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
106 dt = time.time() - self.lastPollTime
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
107 assert dt < 10, "last poll was %s sec ago" % dt
1223
34de6cfa0b6b rename historical 'tomatoWifi'
drewp <drewp@bigasterisk.com>
parents:
diff changeset
108
34de6cfa0b6b rename historical 'tomatoWifi'
drewp <drewp@bigasterisk.com>
parents:
diff changeset
109 @inlineCallbacks
1461
517cbb905d4c remote suspend, wifi group arg
drewp <drewp@bigasterisk.com>
parents: 1369
diff changeset
110 def poll(self):
1224
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
111 try:
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
112 newAddrs = yield self.wifi.getPresentMacAddrs()
1226
7de8f0cd3392 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp <drewp@bigasterisk.com>
parents: 1225
diff changeset
113 self.onNodes(newAddrs)
1224
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
114 except Exception as e:
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
115 log.error("poll error: %r\n%s", e, traceback.format_exc())
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
116
1226
7de8f0cd3392 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp <drewp@bigasterisk.com>
parents: 1225
diff changeset
117 def onNodes(self, newAddrs: List[SeenNode]):
7de8f0cd3392 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp <drewp@bigasterisk.com>
parents: 1225
diff changeset
118 now = int(time.time())
7de8f0cd3392 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp <drewp@bigasterisk.com>
parents: 1225
diff changeset
119 newWithSignal = [a for a in newAddrs if a.connected]
7de8f0cd3392 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp <drewp@bigasterisk.com>
parents: 1225
diff changeset
120
7de8f0cd3392 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp <drewp@bigasterisk.com>
parents: 1225
diff changeset
121 actions = self.computeActions(newWithSignal)
7de8f0cd3392 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp <drewp@bigasterisk.com>
parents: 1225
diff changeset
122 points = []
7de8f0cd3392 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp <drewp@bigasterisk.com>
parents: 1225
diff changeset
123 for action in actions:
7de8f0cd3392 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp <drewp@bigasterisk.com>
parents: 1225
diff changeset
124 log.info("action: %s", action)
7de8f0cd3392 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp <drewp@bigasterisk.com>
parents: 1225
diff changeset
125 action['created'] = datetime.datetime.now(tz.gettz('UTC'))
7de8f0cd3392 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp <drewp@bigasterisk.com>
parents: 1225
diff changeset
126 mongo.save(action)
7de8f0cd3392 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp <drewp@bigasterisk.com>
parents: 1225
diff changeset
127 points.append(
7de8f0cd3392 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp <drewp@bigasterisk.com>
parents: 1225
diff changeset
128 self.influxPoint(now, action['address'].lower(),
7de8f0cd3392 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp <drewp@bigasterisk.com>
parents: 1225
diff changeset
129 1 if action['action'] == 'arrive' else 0))
7de8f0cd3392 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp <drewp@bigasterisk.com>
parents: 1225
diff changeset
130 if now // 3600 > self.lastPollTime // 3600:
7de8f0cd3392 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp <drewp@bigasterisk.com>
parents: 1225
diff changeset
131 log.info('hourly writes')
7de8f0cd3392 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp <drewp@bigasterisk.com>
parents: 1225
diff changeset
132 for addr in newWithSignal:
7de8f0cd3392 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp <drewp@bigasterisk.com>
parents: 1225
diff changeset
133 points.append(self.influxPoint(now, addr.mac.lower(), 1))
7de8f0cd3392 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp <drewp@bigasterisk.com>
parents: 1225
diff changeset
134
7de8f0cd3392 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp <drewp@bigasterisk.com>
parents: 1225
diff changeset
135 influx.write_points(points, time_precision='s')
7de8f0cd3392 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp <drewp@bigasterisk.com>
parents: 1225
diff changeset
136 self.lastWithSignal = newWithSignal
7de8f0cd3392 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp <drewp@bigasterisk.com>
parents: 1225
diff changeset
137 self.lastAddrs = newAddrs
7de8f0cd3392 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp <drewp@bigasterisk.com>
parents: 1225
diff changeset
138 self.lastPollTime = now
7de8f0cd3392 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp <drewp@bigasterisk.com>
parents: 1225
diff changeset
139
7de8f0cd3392 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp <drewp@bigasterisk.com>
parents: 1225
diff changeset
140 self.updateGraph(masterGraph)
1369
42f4fed9cd25 no more immediateUpdate since we push patch events now. and the code was broken for py3 anyway
drewp <drewp@bigasterisk.com>
parents: 1367
diff changeset
141
1224
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
142 def influxPoint(self, now, address, value):
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
143 return {
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
144 'measurement': 'presence',
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
145 'tags': {'sensor': 'wifi', 'address': address,},
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
146 'fields': {'value': value},
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
147 'time': now,
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
148 }
1461
517cbb905d4c remote suspend, wifi group arg
drewp <drewp@bigasterisk.com>
parents: 1369
diff changeset
149
1224
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
150 def computeActions(self, newWithSignal):
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
151 actions = []
1223
34de6cfa0b6b rename historical 'tomatoWifi'
drewp <drewp@bigasterisk.com>
parents:
diff changeset
152
1226
7de8f0cd3392 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp <drewp@bigasterisk.com>
parents: 1225
diff changeset
153 def makeAction(addr: SeenNode, act: str):
1224
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
154 d = dict(sensor="wifi",
1226
7de8f0cd3392 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp <drewp@bigasterisk.com>
parents: 1225
diff changeset
155 address=addr.mac.upper(), # mongo data is legacy uppercase
1224
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
156 action=act)
1226
7de8f0cd3392 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp <drewp@bigasterisk.com>
parents: 1225
diff changeset
157 if act == 'arrive':
1224
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
158 # this won't cover the possible case that you get on
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
159 # wifi but don't have an ip yet. We'll record an
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
160 # action with no ip and then never record your ip.
1226
7de8f0cd3392 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp <drewp@bigasterisk.com>
parents: 1225
diff changeset
161 d['ip'] = addr.ip
1461
517cbb905d4c remote suspend, wifi group arg
drewp <drewp@bigasterisk.com>
parents: 1369
diff changeset
162 return d
1224
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
163
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
164 for addr in newWithSignal:
1226
7de8f0cd3392 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp <drewp@bigasterisk.com>
parents: 1225
diff changeset
165 if addr.mac not in [r.mac for r in self.lastWithSignal]:
1224
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
166 actions.append(makeAction(addr, 'arrive'))
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
167
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
168 for addr in self.lastWithSignal:
1226
7de8f0cd3392 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp <drewp@bigasterisk.com>
parents: 1225
diff changeset
169 if addr.mac not in [r.mac for r in newWithSignal]:
1224
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
170 actions.append(makeAction(addr, 'leave'))
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
171
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
172 return actions
1223
34de6cfa0b6b rename historical 'tomatoWifi'
drewp <drewp@bigasterisk.com>
parents:
diff changeset
173
1224
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
174 def deltaSinceLastArrive(self, name):
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
175 results = list(self.mongo.find({'name' : name}).sort('created',
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
176 DESCENDING).limit(1))
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
177 if not results:
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
178 return datetime.timedelta.max
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
179 now = datetime.datetime.now(tz.gettz('UTC'))
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
180 last = results[0]['created'].replace(tzinfo=tz.gettz('UTC'))
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
181 return now - last
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
182
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
183 def updateGraph(self, masterGraph):
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
184 g = ConjunctiveGraph()
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
185 ctx = DEV['wifi']
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
186
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
187 # someday i may also record specific AP and their strength,
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
188 # for positioning. But many users just want to know that the
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
189 # device is connected to some bigasterisk AP.
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
190 age = time.time() - self.lastPollTime
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
191 if age > 10:
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
192 raise ValueError("poll data is stale. age=%s" % age)
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
193
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
194 for dev in self.lastAddrs:
1226
7de8f0cd3392 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp <drewp@bigasterisk.com>
parents: 1225
diff changeset
195 if not dev.connected:
1224
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
196 continue
1230
ec0db53aa833 don't use 'connected' for time and for network. add rdf:type.
drewp <drewp@bigasterisk.com>
parents: 1226
diff changeset
197 g.add((dev.uri, RDF.type, ROOM['NetworkedDevice'], ctx))
1226
7de8f0cd3392 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp <drewp@bigasterisk.com>
parents: 1225
diff changeset
198 g.add((dev.uri, ROOM['macAddress'], Literal(dev.mac), ctx))
7de8f0cd3392 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp <drewp@bigasterisk.com>
parents: 1225
diff changeset
199 g.add((dev.uri, ROOM['ipAddress'], Literal(dev.ip), ctx))
1223
34de6cfa0b6b rename historical 'tomatoWifi'
drewp <drewp@bigasterisk.com>
parents:
diff changeset
200
1226
7de8f0cd3392 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp <drewp@bigasterisk.com>
parents: 1225
diff changeset
201 for s,p,o in dev.stmts:
7de8f0cd3392 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp <drewp@bigasterisk.com>
parents: 1225
diff changeset
202 g.add((s, p, o, ctx))
7de8f0cd3392 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp <drewp@bigasterisk.com>
parents: 1225
diff changeset
203
1224
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
204 try:
1226
7de8f0cd3392 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp <drewp@bigasterisk.com>
parents: 1225
diff changeset
205 conn = whenConnected(mongo, dev.mac)
1224
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
206 except ValueError:
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
207 traceback.print_exc()
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
208 pass
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
209 else:
1226
7de8f0cd3392 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp <drewp@bigasterisk.com>
parents: 1225
diff changeset
210 g.add((dev.uri, ROOM['connectedAgo'],
1224
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
211 Literal(connectedAgoString(conn)), ctx))
1226
7de8f0cd3392 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp <drewp@bigasterisk.com>
parents: 1225
diff changeset
212 g.add((dev.uri, ROOM['connected'], Literal(conn), ctx))
1224
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
213 masterGraph.setToGraph(g)
1223
34de6cfa0b6b rename historical 'tomatoWifi'
drewp <drewp@bigasterisk.com>
parents:
diff changeset
214
1461
517cbb905d4c remote suspend, wifi group arg
drewp <drewp@bigasterisk.com>
parents: 1369
diff changeset
215 class RemoteSuspend(PrettyErrorHandler, cyclone.web.RequestHandler):
517cbb905d4c remote suspend, wifi group arg
drewp <drewp@bigasterisk.com>
parents: 1369
diff changeset
216 def post(self):
517cbb905d4c remote suspend, wifi group arg
drewp <drewp@bigasterisk.com>
parents: 1369
diff changeset
217 # windows is running shutter (https://www.den4b.com/products/shutter)
517cbb905d4c remote suspend, wifi group arg
drewp <drewp@bigasterisk.com>
parents: 1369
diff changeset
218 fetch('http://DESKTOP-GOU4AC4:8011/action', postdata={'id': 'Sleep'})
517cbb905d4c remote suspend, wifi group arg
drewp <drewp@bigasterisk.com>
parents: 1369
diff changeset
219
1224
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
220
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
221 if __name__ == '__main__':
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
222 args = docopt.docopt('''
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
223 Usage:
1226
7de8f0cd3392 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp <drewp@bigasterisk.com>
parents: 1225
diff changeset
224 wifi.py [options]
1223
34de6cfa0b6b rename historical 'tomatoWifi'
drewp <drewp@bigasterisk.com>
parents:
diff changeset
225
1224
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
226 Options:
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
227 -v, --verbose more logging
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
228 --port=<n> serve on port [default: 9070]
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
229 --poll=<freq> poll frequency [default: .2]
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
230 ''')
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
231 if args['--verbose']:
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
232 from twisted.python import log as twlog
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
233 twlog.startLogging(sys.stdout)
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
234 log.setLevel(10)
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
235 log.setLevel(logging.DEBUG)
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
236
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
237 mongo = Connection('bang', 27017, tz_aware=True)['visitor']['visitor']
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
238 influx = InfluxDBClient('bang', 9060, 'root', 'root', 'main')
1223
34de6cfa0b6b rename historical 'tomatoWifi'
drewp <drewp@bigasterisk.com>
parents:
diff changeset
239
1226
7de8f0cd3392 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp <drewp@bigasterisk.com>
parents: 1225
diff changeset
240 config = ConjunctiveGraph()
7de8f0cd3392 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp <drewp@bigasterisk.com>
parents: 1225
diff changeset
241 config.parse(open('private_config.n3'), format='n3')
1461
517cbb905d4c remote suspend, wifi group arg
drewp <drewp@bigasterisk.com>
parents: 1369
diff changeset
242
1224
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
243 masterGraph = PatchableGraph()
1226
7de8f0cd3392 very big rewrite. py3; orbi-only for now; n3 config file; delete or move out dead code
drewp <drewp@bigasterisk.com>
parents: 1225
diff changeset
244 wifi = Wifi(config)
1224
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
245 poller = Poller(wifi, mongo)
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
246 task.LoopingCall(poller.poll).start(1/float(args['--poll']))
1223
34de6cfa0b6b rename historical 'tomatoWifi'
drewp <drewp@bigasterisk.com>
parents:
diff changeset
247
1225
b8c0daabe5a5 factor out some URI generation
drewp <drewp@bigasterisk.com>
parents: 1224
diff changeset
248 reactor.listenTCP(
b8c0daabe5a5 factor out some URI generation
drewp <drewp@bigasterisk.com>
parents: 1224
diff changeset
249 int(args['--port']),
b8c0daabe5a5 factor out some URI generation
drewp <drewp@bigasterisk.com>
parents: 1224
diff changeset
250 cyclone.web.Application(
b8c0daabe5a5 factor out some URI generation
drewp <drewp@bigasterisk.com>
parents: 1224
diff changeset
251 [
b8c0daabe5a5 factor out some URI generation
drewp <drewp@bigasterisk.com>
parents: 1224
diff changeset
252 (r"/", Index),
1464
32d134dbfb1e start ts config files, but this doesn't share the streamed-graph code properly yet
drewp <drewp@bigasterisk.com>
parents: 1461
diff changeset
253 (r"/build/(wifi\.bundle\.js)", cyclone.web.StaticFileHandler, {"path": 'build'}),
1225
b8c0daabe5a5 factor out some URI generation
drewp <drewp@bigasterisk.com>
parents: 1224
diff changeset
254 (r'/json', Json),
b8c0daabe5a5 factor out some URI generation
drewp <drewp@bigasterisk.com>
parents: 1224
diff changeset
255 (r'/graph', CycloneGraphHandler, {'masterGraph': masterGraph}),
b8c0daabe5a5 factor out some URI generation
drewp <drewp@bigasterisk.com>
parents: 1224
diff changeset
256 (r'/graph/events', CycloneGraphEventsHandler, {'masterGraph': masterGraph}),
b8c0daabe5a5 factor out some URI generation
drewp <drewp@bigasterisk.com>
parents: 1224
diff changeset
257 (r'/table', Table),
1461
517cbb905d4c remote suspend, wifi group arg
drewp <drewp@bigasterisk.com>
parents: 1369
diff changeset
258 (r'/remoteSuspend', RemoteSuspend),
1225
b8c0daabe5a5 factor out some URI generation
drewp <drewp@bigasterisk.com>
parents: 1224
diff changeset
259 #(r'/activity', Activity),
b8c0daabe5a5 factor out some URI generation
drewp <drewp@bigasterisk.com>
parents: 1224
diff changeset
260 ],
b8c0daabe5a5 factor out some URI generation
drewp <drewp@bigasterisk.com>
parents: 1224
diff changeset
261 wifi=wifi,
b8c0daabe5a5 factor out some URI generation
drewp <drewp@bigasterisk.com>
parents: 1224
diff changeset
262 poller=poller,
b8c0daabe5a5 factor out some URI generation
drewp <drewp@bigasterisk.com>
parents: 1224
diff changeset
263 mongo=mongo))
1224
e1202af42d4d port to py3
drewp <drewp@bigasterisk.com>
parents: 1223
diff changeset
264 reactor.run()