Initial commit: Shop Database Flask Application
Flask backend with Vue 3 frontend for shop floor machine management. Includes database schema export for MySQL shopdb_flask database. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
5
plugins/printers/services/__init__.py
Normal file
5
plugins/printers/services/__init__.py
Normal file
@@ -0,0 +1,5 @@
|
||||
"""Printers plugin services."""
|
||||
|
||||
from .zabbix_service import ZabbixService
|
||||
|
||||
__all__ = ['ZabbixService']
|
||||
133
plugins/printers/services/zabbix_service.py
Normal file
133
plugins/printers/services/zabbix_service.py
Normal file
@@ -0,0 +1,133 @@
|
||||
"""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
|
||||
Reference in New Issue
Block a user