diff service/tomatoWifi/wifi.py @ 867:d9bc9a82dcca

redo wifi scraper to work with zyxel router report page too. add last connected time (from mongo) to web table Ignore-this: 18bade72e14d40532bd019791d03fa7d darcs-hash:20130407000819-312f9-6b262edf71421b17947050e80560005d7bffa80b
author drewp <drewp@bigasterisk.com>
date Sat, 06 Apr 2013 17:08:19 -0700
parents 1168b0cd90af
children c81a451f9b26
line wrap: on
line diff
--- a/service/tomatoWifi/wifi.py	Sun Feb 10 13:41:35 2013 -0800
+++ b/service/tomatoWifi/wifi.py	Sat Apr 06 17:08:19 2013 -0700
@@ -1,4 +1,5 @@
 import re, ast, logging, socket
+import lxml.html.soupparser
 from twisted.internet.defer import inlineCallbacks, returnValue
 from cyclone.httpclient import fetch
 from rdflib import Literal, Graph
@@ -12,6 +13,8 @@
 class Wifi(object):
     """
     gather the users of wifi from the tomato routers
+
+    with host names from /var/lib/dhcp/dhcpd.leases
     """
     def __init__(self, tomatoConfig="/my/site/magma/tomato_config.js",
                  accessN3="/my/proj/openid_proxy/access.n3"):
@@ -48,15 +51,14 @@
 	    userPass, tail = tail.split("@", 1)
             r.url = http + '//' + tail
             r.headers = {'Authorization': ['Basic %s' % userPass.encode('base64').strip()]}
-            r.name = {'tomato1' : 'bigasterisk3',
+            r.name = {'tomato1' : 'bigasterisk5',
                       'tomato2' : 'bigasterisk4'}[name.split('/')[1]]
             self.routers.append(r)
 
     @inlineCallbacks
     def getPresentMacAddrs(self):
-        aboutIp = {}
-        byMac = {} # mac : [ip]
-
+        rows = []
+        
         for router in self.routers:
             log.debug("GET %s", router)
             try:
@@ -66,57 +68,35 @@
                 log.warn("get on %s failed" % router)
                 continue
             data = resp.body
-
-            for (ip, mac, iface) in jsValue(data, 'arplist'):
-                aboutIp.setdefault(ip, {}).update(dict(
-                    ip=ip,
-                    router=router.name,
-                    mac=mac,
-                    iface=iface,
-                    ))
-
-                byMac.setdefault(mac, set()).add(ip)
-
-            for (name, ip, mac, lease) in jsValue(data, 'dhcpd_lease'):
-                if lease.startswith('0 days, '):
-                    lease = lease[len('0 days, '):]
-                aboutIp.setdefault(ip, {}).update(dict(
-                    router=router.name,
-                    rawName=name,
-                    mac=mac,
-                    lease=lease
-                    ))
-
-                byMac.setdefault(mac, set()).add(ip)
+            if 'Wireless -- Authenticated Stations' in data:
+                # zyxel 'Station Info' page
+                rows.extend(self.parseZyxel(data, router.name))
+            else:
+                # tomato page
+                rows.extend(self.parseTomato(data, router.name))
 
-            for iface, mac, signal in jsValue(data, 'wldev'):
-                matched = False
-                for addr in aboutIp.values():
-                    if (addr['router'], addr['mac']) == (router.name, mac):
-                        addr.update(dict(signal=signal, iface=iface))
-                        matched = True
-                if not matched:
-                    aboutIp["mac-%s-%s" % (router, mac)] = dict(
-                        router=router.name,
-                        mac=mac,
-                        signal=signal,
-                        )
+        for r in rows:
+            try:
+                r['name'] = self.knownMacAddr[r['mac']]
+            except KeyError:
+                pass
+                
+        returnValue(rows)
+        
+    def parseZyxel(self, data, routerName):
+        root = lxml.html.soupparser.fromstring(data)
+        for tr in root.cssselect('tr'):
+            mac, assoc, uth, ssid, iface = [td.text_content().strip() for td in tr.getchildren()]
+            if mac == "MAC":
+                continue
+            assoc = assoc.lower() == 'yes'
+            yield dict(router=routerName, mac=mac, assoc=assoc, connected=assoc)
 
-        ret = []
-        for addr in aboutIp.values():
-            if addr.get('ip') in ['192.168.1.1', '192.168.1.2', '192.168.0.2']:
-                continue
-            try:
-                addr['name'] = self.knownMacAddr[addr['mac']]
-            except KeyError:
-                addr['name'] = addr.get('rawName')
-                if addr['name'] in [None, '*']:
-                    addr['name'] = 'unknown'
-            ret.append(addr)
-
-        returnValue(ret)
-
-
+    def parseTomato(self, data, routerName):
+        for iface, mac, signal in jsValue(data, 'wldev'):
+            yield dict(router=routerName, mac=mac, signal=signal, connected=bool(signal))
+        
+            
 def jsValue(js, variableName):
     # using literal_eval instead of json parser to handle the trailing commas
     val = re.search(variableName + r'\s*=\s*(.*?);', js, re.DOTALL).group(1)