Как считывать данные с принтеров Canon?
Есть у меня интересная задача автоматизировать мониторинг принтеров Canon (парк из 40 принтеров: 20 G1430 USB и 20 G5040 LAN). Смог написать простенький npm пакет canon-monitor, но есть проблема:
- Не могу собирать состояние принтеров, если у них ошибка: SNMB выдает пустую таблицу при ошибках на G5040, а через WMI на G5040 и G1430 возвращается ErrorState и LastErrorState, но там null. С G5040 я обошел кетч ошибки парсингом их веб-морды с помощью puppeeter, но парсинг происходит всегда каждые 5 секунд, если принтер онлайн, потому что узнать, что у них ошибка, фактически можно только через веб-морду (поправьте, если это не так). Поэтому каждые 5 секунд происходит неприятная и сильная нагрузка на сервер.
Мне нужно собирать такие данные:
- Текущая ошибка (предыдущая не нужна, так как все ошибки будут кидаться в метрики принтера)
- Кол-во отпечатанных страниц (хоть как, хоть через очередь печати, дальше суммирование и в метрику)
- Состояние: ошибка/онлайн/оффлайн/печатает
- Кол-во чернил (только для G5040)
- Состояние наполненности памперса
Что я сейчас могу получить: по WMI: workOffline true\false (принтер онлайн или нет), статус idle\printing по SNMB (G5040): general status offline\online (остальные статусы хз, но не работают), up-time. prtAlertTable пустой и в случае ошибки не заполняется.
Что я делаю не так и как можно получить эти данные с принтеров?
Ответы (1 шт):
Я такое реализовывал через сбор метрик с принт-серверов, по каждому принтеру получаю ошибки и состояния.
- Скрипт для сбора метрик с принт серверов
import winrm
import json
from zabbix_utils import Sender
username = "user"
password = "password"
servers = {
'your': 'printer-server',
}
# Даные которые меня не интересуют
except_printers = [
'Microsoft Print to PDF',
'Microsoft XPS Document Writer',
'_Total'
]
def send_to_zabbix(host, key, value):
try:
sender = Sender(server='your_zabbix_server', port=10051)
response_to_zabbix = sender.send_value(host, key, value)
print(response_to_zabbix)
except Exception as e:
print(f"Ошибка при отправке в Zabbix: {e}")
def get_printers_info():
total = []
for key, value in servers.items():
session = winrm.Session(
value,
auth=(username, password),
transport='ntlm',
)
command = """
$Printers = Get-CimInstance -ClassName Win32_PerfFormattedData_Spooler_PrintQueue
$PrinterStatuses = Get-Printer
$printerData = $Printers | ForEach-Object {
$printerName = $_.Name
$status = ($PrinterStatuses | Where-Object {$_.Name -eq $printerName} | Select-Object -First 1).PrinterStatus
@{
name = $printerName
jobs = $_.Jobs
status = $status
}
}
$printerData | ConvertTo-Json -Depth 2
"""
result = session.run_ps(command)
if result.status_code == 0:
output = result.std_out.decode('utf-8')
try:
printers_list = json.loads(output)
# Фильтруем принтеры (исключаем системные и _Total)
for printer in printers_list:
if printer['name'] not in except_printers:
total.append(printer)
except json.JSONDecodeError as e:
print(f"Ошибка декодирования JSON: {e}")
print(f"Сырые данные: {output}")
else:
print(f"Ошибка: {result.std_err.decode('utf-8')}")
format_data = json.dumps(total, indent=4, ensure_ascii=False)
# Отправка данных для LLD в Zabbix
send_to_zabbix('host_name_in_zabbix', 'item_key', format_data)
if __name__ == '__main__':
get_printers_info()
Скрипт ставим на автозапуск, можно через
crontab -e
и вставляем следующее содержимое(запуск скрипта каждые 2 минуты)
*/2 * * * * /path/to/yout/project/get-printers-info.py
Ну и дело за малым, обработать полученный Json в Zabbix и настроить Низкоуровневое обнаружение