From 8cd62b46edf42309c5e184cb2d0ee469141d1ce9 Mon Sep 17 00:00:00 2001 From: polyfloyd Date: Sat, 11 Mar 2017 12:09:38 +0100 Subject: [PATCH] Add the thing and a reader for the "Aruba Instant" --- access_points.d/aruba_instant.php | 74 ++++++++++++++++++++++ wifi-mqtt.py | 100 ++++++++++++++++++++++++++++++ 2 files changed, 174 insertions(+) create mode 100755 access_points.d/aruba_instant.php create mode 100755 wifi-mqtt.py diff --git a/access_points.d/aruba_instant.php b/access_points.d/aruba_instant.php new file mode 100755 index 0000000..cf2363e --- /dev/null +++ b/access_points.d/aruba_instant.php @@ -0,0 +1,74 @@ +#!/usr/bin/php5 + $value) { + $index = str_replace("iso.3.6.1.4.1.14823.2.3.3.1.2.3.1.", "", $index); + $index2 = explode(".", $index); + $index3 = array(); + + for ($i = 1; $i < 8; $i++) { + $index3[] = $index2[$i]; + } + $index3 = implode(".", $index3); + + if ($index2[0] == 4) { + $mac = str_replace(" ",":", trim(str_replace("Hex-STRING: ", "", $value))); + $ssid[$mac] = $wlanTable["iso.3.6.1.4.1.14823.2.3.3.1.2.3.1.3.".$index3]; +// $radio[$mac] = trim(str_replace("INTEGER: ", "", $wlanTable["iso.3.6.1.4.1.14823.2.3.3.1.2.3.1.2.".$index3])); + } +} + +$macs = array(); +$clientTable = snmprealwalk($ip, $snmp, ".1.3.6.1.4.1.14823.2.3.3.1.2.4.1"); +foreach($clientTable as $index => $value) { + $index = str_replace("iso.3.6.1.4.1.14823.2.3.3.1.2.4.1.", "", $index); + $index2 = explode(".", $index); + $index3 = array(); + + for ($i = 1; $i <= 6; $i++) { + $index3[] = $index2[$i]; + } + $index3 = implode(".", $index3); + + if ($index2[0] == 1) { + $radio_mac = $clientTable["iso.3.6.1.4.1.14823.2.3.3.1.2.4.1.2.".$index3]; + $radio_mac = str_replace(" ", ":", trim(str_replace("Hex-STRING: ", "", $radio_mac))); + $macs[] = array ( + "mac" => strtolower(str_replace(" ", ":", trim(str_replace("Hex-STRING: ", "", $value)))), + "ssid" => trim(str_replace("\"", "", str_replace("STRING: ", "", $ssid[$radio_mac]))), +// "radio" => "IAP", + "signal" => intval(trim(str_replace("INTEGER: ", "", $clientTable["iso.3.6.1.4.1.14823.2.3.3.1.2.4.1.7.".$index3]))), + ); + } +} + +print(json_encode($macs, JSON_PRETTY_PRINT)."\n"); + +} catch (Exception $err) { + print("Ah, fuck: $err\n"); +} diff --git a/wifi-mqtt.py b/wifi-mqtt.py new file mode 100755 index 0000000..feb9d30 --- /dev/null +++ b/wifi-mqtt.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python3 + +import json +import os +import os.path as path +import paho.mqtt.client as mqtt +import re +import subprocess +import time + + +MQTT_HOST = 'mqtt.bitlair.nl' +AP_DIR = path.join(path.dirname(__file__), 'access_points.d') + + +def read_ap(filepath): + regexp_mac = re.compile('^(:?[0-9a-f]{2}:){5}[0-9a-f]{2}$') + associations = json.loads(subprocess.check_output([ filepath ]).decode('utf8')) + assert type(associations) is list, 'The value returned by the AP driver is not a list' + for assoc in associations: + assert type(assoc['mac']) is str + assert regexp_mac.match(assoc['mac']), 'Invalid MAC: %s' % assoc['mac'] + assert type(assoc['ssid']) is str and len(assoc['ssid']) > 1, 'Invalid SSID: %s' % assoc['ssid'] + if 'signal' in assoc: + assert type(assoc['signal']) is int + return associations + +class Activity(object): + + def __init__(self, driver_directory): + self.associations = {} + if driver_directory == "": + return + for ap_driver in os.listdir(driver_directory): + filepath = path.join(driver_directory, ap_driver) + if os.access(filepath, os.X_OK): + self.associations.update({ assoc['mac']: assoc for assoc in read_ap(filepath) }) + + def ssids(self): + return { assoc['ssid'] for assoc in self.associations.values() } + + def macs(self): + return self.associations.keys() + + def diff(self, prev_activity): + macs_joined = self.macs() - prev_activity.macs() + macs_parted = prev_activity.macs() - self.macs() + return { + 'joined': [ self.associations[mac] for mac in macs_joined ], + 'parted': [ prev_activity.associations[mac] for mac in macs_parted ], + } + + +def hook_print(activity, prev_activity, diff): + print('') + print('total online: %s' % len(activity.associations)) + if len(diff['joined']) > 0: + print('joined: %s' % ', '.join([ '%s on %s' % (assoc['mac'], assoc['ssid']) for assoc in diff['joined'] ])) + if len(diff['parted']) > 0: + print('parted: %s' % ', '.join([ '%s on %s' % (assoc['mac'], assoc['ssid']) for assoc in diff['parted'] ])) + +def hook_mqtt(activity, prev_activity, diff): + normalize_ssid = lambda s: s.lower().replace(' ', '-') + mqttc.publish('bitlair/wifi/all/online', len(activity.associations), retain=True) + for ssid in activity.ssids() | prev_activity.ssids(): + online_count = sum(assoc['ssid'] == ssid for assoc in activity.associations.values()) + mqttc.publish('bitlair/wifi/%s/online' % normalize_ssid(ssid), str(online_count), retain=True) + for assoc in diff['joined']: + signal = assoc['signal'] if 'signal' in assoc else '-' + payload = 'join %s %s' % (assoc['mac'], signal) + mqttc.publish('bitlair/wifi/%s' % normalize_ssid(assoc['ssid']), payload) + for assoc in diff['parted']: + mqttc.publish('bitlair/wifi/%s' % normalize_ssid(assoc['ssid']), 'part %s' % assoc['mac']) + + +if __name__ == '__main__': + mqttc = mqtt.Client() + mqttc.connect(MQTT_HOST) + mqttc.loop_start() + + prev_activity = Activity('') + while True: + try: + activity = Activity(AP_DIR) + except Exception as err: + print(err) + time.sleep(1) + continue + + diff = activity.diff(prev_activity) + if len(diff['joined']) > 0 or len(diff['parted']) > 0: + hooks = [ +# hook_print, + hook_mqtt, + ] + for hook in hooks: + hook(activity, prev_activity, diff) + + prev_activity = activity + time.sleep(30)