#!/usr/bin/python # -*- coding: utf-8 -*- from __future__ import print_function import io import json import subprocess import time from .exceptions import SanityCheckError class AlfredParser: alfred_json = 'alfred-json' alfred_datatypes = [('static', 158), ('dynamic', 159)] def __str__(self): types = ['{1}=>{0}'.format(x[0], x[1]) for x in self.alfred_datatypes] return 'AlfredParser \'{0}\' {1}'.format( self.alfred_json, str.join(' ', types), ) def sanitycheck(self): testdata = None try: cmd = [self.alfred_json, '-z', '-r', str(int(self.alfred_datatypes[0][1]))] testdata = subprocess.check_output(cmd) except Exception as err: raise SanityCheckError( self, "alfred-json not found or incompatible", err) try: json.loads(testdata) except Exception as err: raise SanityCheckError( self, "alfred-json does not return valid JSON data", err) return True def fetch(self, alfred_dump=None, include_rawdata=False): data = { } ts = int(time.time()) alfreddata = {} for datatype in self.alfred_datatypes: rawdata = subprocess.check_output([self.alfred_json, '-z', '-r', str(int(datatype[1]))]) newdata = json.loads(rawdata) for item in newdata: if not item in alfreddata: alfreddata[item] = {} alfreddata[item][datatype[0]] = newdata[item] if not alfred_dump is None: jsondata = json.dumps(alfreddata, ensure_ascii=False) dumpfile = io.open(alfred_dump, 'w') dumpfile.write(jsondata) dumpfile.close() for alfredid in alfreddata: alfredinfo = alfreddata[alfredid] if 'node_id' in alfredinfo['static']: myid = alfredinfo['static']['node_id'] else: alfredid.lower().replace(':', '') nodeinfo = { 'hostname': None, 'mac': None, 'software': {}, 'statistics': {}, '__UPDATED__': {'alfred': ts,}, '__RAW__': {'alfred': alfredinfo,}, } data[myid] = nodeinfo nodestatic = alfredinfo['static'] if 'hostname' in nodestatic: nodeinfo['hostname'] = nodestatic['hostname'] if 'network' in nodestatic: if 'mac' in nodestatic['network']: nodeinfo['mac'] = nodestatic['network']['mac'] if 'mesh_interfaces' in nodestatic['network']: nodeinfo['macs'] = [x for x in nodestatic['network']['mesh_interfaces']] else: nodeinfo['macs'] = [] if 'software' in nodestatic: sw = nodestatic['software'] nodeinfo['software']['firmware'] = sw['firmware']['release'] if 'firmware' in sw and 'release' in sw['firmware'] else None nodeinfo['software']['autoupdater'] = sw['autoupdater']['branch'] if sw['autoupdater']['enabled'] else 'off' nodedyn = alfredinfo['dynamic'] if 'dynamic' in alfredinfo else nodestatic['statistics'] if 'uptime' in nodedyn: nodeinfo['uptime'] = int(float(nodedyn['uptime'])) if 'gateway' in nodedyn: nodeinfo['gateway'] = nodedyn['gateway'] traffic = nodedyn["traffic"] if "traffic" in nodedyn else None if not traffic is None: if not 'traffic' in nodeinfo['statistics']: nodeinfo['statistics']['traffic'] = { } t = nodeinfo['statistics']['traffic'] t['rxbytes'] = int(traffic["rx"]["bytes"]) t['txbytes'] = int(traffic["tx"]["bytes"]) return data if __name__ == "__main__": a = AlfredParser() try: a.sanitycheck() except SanityCheckError as err: print('SANITY-CHECK failed:', str(err)) import sys sys.exit(1) adata = a.fetch() print(json.dumps(adata))