Подписка на изменение состояния CUPS

Я пытаюсь прослушать изменения состояния принтера (например, замятие бумаги, пауза...) Следующий код дает ответ «Bad notify-recipient-uri», затем блокируется на ippReadFile и не освобождается, когда принтер приостановлен/не приостановлен.

int main()
{
    http_t *http = httpConnectEncrypt(cupsServer(), ippPort(), 
    cupsEncryption());

    ipp_t *request = ippNewRequest(IPP_CREATE_PRINTER_SUBSCRIPTION);

    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
        NULL, "ipp://localhost:631/printers/Generic-text-only");
    ippAddString(request, IPP_TAG_SUBSCRIPTION, IPP_TAG_URI, "notify-recipient-uri",
        NULL, "cups_test://");
    ippAddString(request, IPP_TAG_SUBSCRIPTION, IPP_TAG_KEYWORD, "notify-events",
        NULL, "printer-state-changed");

    ipp_t *response = cupsDoRequest(http, request, "/");

    while (1)
    {
        ipp_state_t state;      
        ipp_t *event = ippNew();

        while ((state = ippReadFile(0, event)) != IPP_DATA)
        {
            printf("%s\n","Got Data");
        }

        printf("%s\n","Repeating");
        ippDelete(event);
    }
}

После просмотра атрибутов принтеров я обнаружил, что для атрибута notify-schemes-supported установлено значение «dbus». Мне не удалось изменить атрибут с помощью IPP_SET_PRINTER_ATTRIBUTES. Любые идеи о том, как заставить это работать?


person Kyle Berezin    schedule 25.04.2017    source источник
comment
Я не так хорошо знаком с чашками, но я заметил, что вы передаете файловый дескриптор 0 в качестве первого аргумента ippReadFile(int fd, ipp_t *ipp). Дескриптор файла 0 является стандартным вводом. Есть ли причина ожидать, что что-нибудь появится на стандартном вводе вашей программы? Иначе неудивительно, что он завис бы, как вы описали. Что, если бы вы использовали ippRead(http, event)?   -  person MassPikeMike    schedule 26.04.2017
comment
ippRead(http, event) не блокируется, поэтому он просто зацикливается бесконечно. Я получил этот код с github.com/apple/cups/ blob/master/notifier/testnotify.c и github.com/apple/cups/blob/master/test/ . Вполне возможно, что я делаю это совершенно неправильно, хотя я не думаю, что это так.   -  person Kyle Berezin    schedule 27.04.2017
comment
Согласно книге Майкла Свита «CUPS: Common UNIX Printing System», которая у меня есть, уведомители позволяют CUPS уведомлять пользователей или программы об изменениях состояния сервера, принтера или задания. Схема уведомления ipget реализована внутри сервера CUPS, тогда как все остальные уведомители CUPS являются внешними программами, получающими события в своих стандартных входных файлах.   -  person Kyle Berezin    schedule 27.04.2017
comment
получать события на свой стандартный ввод, это звучит так, как будто ваша программа должна получать что-то на стандартный ввод, так что, возможно, вы на правильном пути. Удачи.   -  person MassPikeMike    schedule 27.04.2017
comment
Я отказываюсь от этого. Я потратил на это почти месяц. Удивительно, как требуется всего 3 строки кода и немного поиска в Google, чтобы выяснить, как получить состояния принтера, но упаси бог, вы захотите заблокировать его. Я собираюсь создать программу, которая просто запрашивает свое состояние каждые 10 секунд, а затем опубликую это как ответ.   -  person Kyle Berezin    schedule 27.04.2017


Ответы (1)


Очень простой пример, который не требует никакого кода C, — это использование ipptool против макроса create-printer-subscription для подписки URI rss на события. Этот подход проиллюстрирован pyipptool.

ipptool обычно поставляется с CUPS, но для современных версий Ubuntu вам может потребоваться установить cups-ipp-utils.

Во-первых, создайте прослушиватель сокетов HTTP, который может получать события...

python -m SimpleHTTPServer 9876

Во-вторых, отправьте события прослушивателю сокета.

ipptool -d recipient=rss://localhost:9876 ipp://localhost:631/printers /usr/share/cups/ipptool/create-printer-subscription.test

Наконец, вызовите событие, такое как отключение принтера.

cupsdisable PDFWriter # or some valid printer name
cupsenable PDFWriter

Схема URI rss:// будет использовать команды PUT для сервера сокетов HTTP. Поскольку SimpleHTTPServer не имеет встроенной поддержки команды PUT, будут возникать ошибки 501. Вам придется настроить прослушиватель HTTP для обработки этих команд, но вы увидите запускаемые события.

Обратите внимание, что макрос create-printer-subscription по умолчанию настроен на отправку событий для printer-config-changed и printer-state-changed, но не printer-queue-order-changed, что может можно скорректировать, сделав копию макроса и отредактировав его.

Кроме того, это оставит подписку активной на срок аренды по умолчанию (определяемый как 86400 в источнике, который должен быть днем). Для бессрочной подписки можно указать дополнительный параметр notify-lease-duration, равный нулю.

person tresf    schedule 27.04.2017