diff --git a/app.py b/app.py index 7428093..c3f4585 100644 --- a/app.py +++ b/app.py @@ -41,18 +41,107 @@ def send_webhook(device, status, diagnostics): } requests.post(config['webhook_url'], json=webhook_data) +import requests +from urllib3.exceptions import InsecureRequestWarning +requests.packages.urllib3.disable_warnings(InsecureRequestWarning) + +class UnifiAPI: + def __init__(self, config): + self.base_url = config['unifi']['controller'] + self.headers = { + 'X-API-KEY': config['unifi']['api_key'], + 'Accept': 'application/json' + } + self.site_id = config['unifi']['site_id'] + self.session = requests.Session() + self.session.verify = False + + def get_device_details(self, device_id): + try: + url = f"{self.base_url}/proxy/network/integration/v1/sites/{self.site_id}/devices/{device_id}" + response = self.session.get(url, headers=self.headers, timeout=5) + response.raise_for_status() + return response.json() + except requests.exceptions.RequestException as e: + logging.error(f"Failed to get device details: {e}") + return None + + def get_device_diagnostics(self, device): + details = self.get_device_details(device['device_id']) + if not details: + return {'state': 'ERROR', 'error': 'Failed to fetch device details'} + + diagnostics = { + 'state': details['state'], + 'firmware': { + 'version': details['firmwareVersion'], + 'updatable': details.get('firmwareUpdatable', False) + }, + 'network': { + 'ip': details['ipAddress'], + 'mac': details['macAddress'] + }, + 'uptime': { + 'adopted_at': details['adoptedAt'], + 'provisioned_at': details['provisionedAt'] + }, + 'interfaces': {} + } + + # Add interface details + if 'interfaces' in details: + diagnostics['interfaces'] = self._parse_interfaces(details['interfaces']) + + return diagnostics + + def _parse_interfaces(self, interfaces): + result = { + 'ports': {}, + 'radios': {} + } + + for port in interfaces.get('ports', []): + result['ports'][f"port_{port['idx']}"] = { + 'state': port['state'], + 'type': port['connector'], + 'speed': { + 'current': port['speedMbps'], + 'max': port['maxSpeedMbps'] + } + } + + for radio in interfaces.get('radios', []): + result['radios'][f"{radio['frequencyGHz']}GHz"] = { + 'standard': radio['wlanStandard'], + 'channel': radio['channel'], + 'width': f"{radio['channelWidthMHz']}MHz" + } + + return result + + + def run_diagnostics(device): - diagnostics = {} + config = load_config() + unifi = UnifiAPI(config) + + diagnostics = unifi.get_device_diagnostics(device) + if device['connection_type'] == 'fiber': - # Add your fiber diagnostic commands here - diagnostics['optical_power'] = subprocess.getoutput('optical-power-check ' + device['ip']) - diagnostics['light_levels'] = subprocess.getoutput('light-level-check ' + device['ip']) - else: - # Add your copper diagnostic commands here - diagnostics['cable_test'] = subprocess.getoutput('ethtool ' + device['ip']) - diagnostics['signal_quality'] = subprocess.getoutput('signal-quality-check ' + device['ip']) + # Add fiber-specific diagnostics + sfp_data = get_sfp_diagnostics(device['ip']) + diagnostics['sfp'] = sfp_data + return diagnostics -@app.route('/') + +@app.route('/api/diagnostics') +def get_diagnostics(): + config = load_config() + diagnostics = {} + for device in config['devices']: + if device['device_id']: + diagnostics[device['name']] = run_diagnostics(device) + return jsonify(diagnostics)@app.route('/') def home(): return render_template('index.html') diff --git a/config.json b/config.json index 07b1942..c28fce8 100644 --- a/config.json +++ b/config.json @@ -1,32 +1,74 @@ { + "unifi": { + "controller": "https://10.10.10.1", + "api_key": "kyPfIsAVie3hwMD4Bc1MjAu8N7HVPIb8", + "site_id": "default" + }, "devices": [ { "name": "UniFi Dream Machine Pro", - "ip": "192.168.1.1", + "ip": "10.10.10.1", "type": "router", + "connection_type": "copper", + "critical": true, + "device_id": "udm-pro-id" + }, + { + "name": "USP PDU Pro", + "ip": "10.10.10.107", + "type": "pdu", + "connection_type": "copper", + "critical": true + }, + { + "name": "USW Aggregation", + "ip": "10.10.10.238", + "type": "switch", + "connection_type": "fiber", + "critical": true + }, + { + "name": "USW Flex Mini", + "ip": "10.10.10.169", + "type": "switch", "connection_type": "copper" }, { - "name": "UniFi Switch 24 PoE", - "ip": "192.168.1.2", + "name": "USW Pro 24 PoE", + "ip": "10.10.10.139", "type": "switch", - "connection_type": "fiber" + "connection_type": "fiber", + "critical": true, + "device_id": "usw-24-poe-id" }, { - "name": "AP Living Room", - "ip": "192.168.1.10", - "type": "access_point" + "name": "U6 Lite", + "ip": "10.10.10.154", + "type": "access_point", + "connection_type": "copper" }, { - "name": "AP Office", - "ip": "192.168.1.11", - "type": "access_point" + "name": "USP Strip", + "ip": "10.10.10.243", + "type": "pdu", + "connection_type": "copper" } ], "check_interval": 30, "webhook_url": "https://your-webhook-url", + "alert_thresholds": { + "fiber": { + "optical_power_min": -10, + "optical_power_max": 0, + "error_rate_threshold": 0.001 + }, + "copper": { + "signal_quality_min": 70, + "max_cable_length": 100 + } + }, "troubleshooting": { - "fiber_tests": ["optical_power", "light_levels", "error_rate"], - "copper_tests": ["cable_length", "crosstalk", "signal_quality"] + "fiber_tests": ["optical_power", "light_levels", "error_rate", "sfp_diagnostics"], + "copper_tests": ["cable_length", "crosstalk", "signal_quality", "poe_status"] } } diff --git a/index.html b/index.html index dd770fa..1644c83 100644 --- a/index.html +++ b/index.html @@ -17,49 +17,15 @@