Как считывать данные с принтеров 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 шт):

Автор решения: resident

Я такое реализовывал через сбор метрик с принт-серверов, по каждому принтеру получаю ошибки и состояния.

  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 и настроить Низкоуровневое обнаружение

→ Ссылка