"""Zabbix service for real-time printer supply lookups.""" import logging from typing import Dict, List, Optional import requests from flask import current_app logger = logging.getLogger(__name__) class ZabbixService: """ Zabbix API service for real-time printer supply lookups. Queries Zabbix by IP address to get current supply levels. No caching - always returns live data. """ def __init__(self): self._url = None self._token = None @property def isconfigured(self) -> bool: """Check if Zabbix is configured.""" self._url = current_app.config.get('ZABBIX_URL') self._token = current_app.config.get('ZABBIX_TOKEN') return bool(self._url and self._token) def _apicall(self, method: str, params: Dict) -> Optional[Dict]: """Make a Zabbix API call.""" if not self.isconfigured: return None payload = { 'jsonrpc': '2.0', 'method': method, 'params': params, 'auth': self._token, 'id': 1 } try: response = requests.post( f"{self._url}/api_jsonrpc.php", json=payload, headers={'Content-Type': 'application/json'}, timeout=10 ) response.raise_for_status() data = response.json() if 'error' in data: logger.error(f"Zabbix API error: {data['error']}") return None return data.get('result') except requests.RequestException as e: logger.error(f"Zabbix API request failed: {e}") return None def gethostbyip(self, ip: str) -> Optional[Dict]: """Find a Zabbix host by IP address.""" result = self._apicall('host.get', { 'output': ['hostid', 'host', 'name'], 'filter': {'ip': ip}, 'selectInterfaces': ['ip'] }) if result: return result[0] if result else None return None def getsuppliesbyip(self, ip: str) -> Optional[List[Dict]]: """ Get printer supply levels by IP address. Returns list of supplies with name and level percentage. """ # Find host by IP host = self.gethostbyip(ip) if not host: logger.debug(f"No Zabbix host found for IP {ip}") return None hostid = host['hostid'] # Get supply-related items items = self._apicall('item.get', { 'output': ['itemid', 'name', 'lastvalue', 'key_'], 'hostids': hostid, 'search': { 'key_': 'supply' # Common key pattern for printer supplies }, 'searchWildcardsEnabled': True }) if not items: # Try alternate patterns items = self._apicall('item.get', { 'output': ['itemid', 'name', 'lastvalue', 'key_'], 'hostids': hostid, 'search': { 'name': 'toner' }, 'searchWildcardsEnabled': True }) if not items: return [] supplies = [] for item in items: try: level = int(float(item.get('lastvalue', 0))) except (ValueError, TypeError): level = 0 supplies.append({ 'name': item.get('name', 'Unknown'), 'level': level, 'itemid': item.get('itemid'), 'key': item.get('key_'), }) return supplies def gethostid(self, ip: str) -> Optional[str]: """Get Zabbix host ID for an IP address.""" host = self.gethostbyip(ip) return host['hostid'] if host else None