Я работаю из дома. Я хотел, чтобы моя жена знала: «Джоэль сейчас занята».

Эта статья будет довольно технической, но не будет давать пошаговых инструкций для всех. Это больше предназначено для того, чтобы вдохновить других компьютерных профессионалов - определить, как они могут сделать что-то подобное.

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

Но я хотел, чтобы за дверью моего офиса было что-то, что указывало бы на то, что я занят, чтобы моя жена могла видеть - своего рода дисплей, - которым нам обоим было легко пользоваться.

В конце концов, моя жена не любит появляться на видеовстречах вне графика, а иногда мне хочется работать без перерыва.

Определение моих требований

Поскольку я технический специалист, я, естественно, начал с того, что записал свои требования. Вот что я придумал:

  • Устанавливается за дверью моего домашнего офиса, на стене или на самой двери
  • Работаем с Linux
  • Интеграция с календарем Google (например, указывать занят, когда у меня назначена встреча в календаре)
  • Включаюсь автоматически, когда используется веб-камера моего компьютера
  • Позвольте мне вручную отключить индикатор (например, включить или выключить свет)
  • Управляющая программа должна быть интерактивной терминальной программой.

Конечно, когда я думал об этом, я в конечном итоге копался в каждом из них немного подробнее.

Сам "Занятый свет"

Итак, первым делом нужно определиться со светом. После разговора с некоторыми ИТ-специалистами на работе был предложен Luxafor Bluetooth (этот Luxafor Flag также может работать как проводное решение). Он соответствовал моим требованиям - в нем использовался простой интерфейс USB (так что он работал в Linux). Я мог бы установить его за дверью. Он оснащен беспроводной связью и питается от батареи, что является огромным плюсом: не нужно сверлить дыры в моем доме - это хорошо! Батареи хватает на длительное время (недели) между подзарядками. Он разноцветный (оснащен светодиодной подсветкой RGB) с регулируемой яркостью, поэтому он не ослепляет людей в моем относительно темном коридоре. Беспроводной передатчик, с которым он поставляется, также имеет светодиод RGB, поэтому вы можете видеть, что направлено на свет с другой стороны непрозрачной двери. Это казалось идеальным решением, хотя может потребовать некоторой специальной работы со стороны программного обеспечения.

Позже я добавлю к этой настройке, но опишу это позже.

Интеграция с Google Calendar

Я хотел, чтобы свет загорелся, когда у меня в календаре будет встреча. Это означало: мне нужен был способ читать календарь из Linux, чтобы я мог обернуть сценарий, чтобы делать то, что мне нужно. По сути, я хотел, чтобы свет включился за пару минут до начала собрания и оставался включенным еще пару минут после того, как собрание закончилось.

Когда я подумал об этом, я подумал, что это будет хорошим визуальным напоминанием для меня о предстоящей встрече. На самом деле не было подходящего места для установки ключа передатчика Luxafor, где он мог бы привлечь мое внимание, когда он включился, поэтому я решил использовать флаг Luxafor, установленный под моим центральным монитором - прямо в центре моего зрения - для этого . Идея заключалась в том, что для встреч я включу оба света одновременно. Если под моим монитором загорится свет, это будет напоминать мне о предстоящей встрече.

Я понял, что могу читать календарь через программу gcalcli, а gcalcli уже был доступен как пакет для Ubuntu 20.04.

Также было легко создать командную строку, которая выводила бы интересующую меня информацию в формате значений, разделенных табуляцией (для облегчения синтаксического анализа на другом собрании). Я был заинтересован в предстоящих собраниях в ближайшие 24 часа или около того (это видно в представлении повестка дня), с указанием времени начала и окончания, и, не вдаваясь в собрания, я отказался. Мне также нужна была возможность указать, какой календарь я просматриваю (обычно я просматриваю свой основной календарь, в котором используется мой адрес электронной почты, но иногда мне нужно просматривать другие календари, к которым у меня был доступ). Командная строка для этого была:

Конечно, вы можете спросить: «Как gcalcli получает доступ к моему календарю? В первый раз, когда вы запустите его, появится всплывающее окно браузера и попросит вас войти в систему, поэтому вы просто запустите gcalcli scheme, которая затем откроет окно браузера, в котором вы сможете войти в свою учетную запись Google. . Если вы одобрите этот доступ, в ~ / .gcalcli_oauth будет сохранен токен доступа, который обеспечивает доступ к вашему календарю. Будущие исполнения будут повторно использовать эту аутентификацию. Очевидно, вы хотите защитить этот токен, но, по крайней мере, он ограничен только доступом к вашему календарю.

Интеграция с веб-камерой

Если я встречался с коллегой вне запланированной встречи или если видеовстреча длилась долго, я хотел, чтобы загорелся индикатор занятости. Это означает, что мне нужен был способ определить, использовалась ли камера. В Linux это довольно просто - я мог посмотреть, использовался ли модуль uvcvideo. Специальный файл / proc / modules - это читаемый текстовый файл, содержащий по одной строке на модуль. Третье поле в строке (ноль в примере ниже) - это количество программ, использующих этот модуль. Мне просто нужно было опрашивать этот файл примерно каждую секунду и искать значение, отличное от нуля.

Так что это просто!

Управление Luxafor

Итак, как мне включить или выключить индикатор Luxafor? Я немного поигрался с этим, пытаясь найти лучший способ. Я уверен, что есть способы получше, чем то, что я придумал, но то, что я придумал, работает.

После просмотра презентации Трэвиса Гибсона об использовании Raku для управления USB-устройствами я был вдохновлен попыткой управлять Luxafor с помощью сценария Raku (мой предпочтительный язык), поэтому я использовал модифицированную версию его модуля LibUSB для управления Luxafor. . Помимо выяснения протокола (легкая часть, отчасти благодаря просмотру сценария Python Luxafor), оставались две проблемы.

Во-первых, в более современных дистрибутивах Linux модуль RGB привязывается к модулю Luxafor. Я не хотел этого, так как я управлял устройством напрямую, поэтому мне нужно было сказать Linux, чтобы он не привязывался к этому модулю. Для этого я создал файл /etc/modprobe.d/luxafor.conf с содержимым:

параметры usbhid quirks = 0x04d8: 0xf372: 0x0004

Запись quirks для модуля usbhid сообщает модулю, что для устройства 0x04d8: 0xf372 (флаг Luxafor) применить quirks 0x0004. Эти причуды говорят usbhid игнорировать устройство и не привязываться к нему.

Но второй проблемой были разрешения. Я хотел, чтобы к устройству можно было получить доступ из учетной записи обычного пользователя, а не из учетной записи, работающей как root. Итак, я создал файл под именем /etc/udev/rules.d/luxafor.rules, чтобы сообщить udev, какие разрешения использовать для устройства:

SUBSYSTEM == ”usb”, ATTR {idVendor} == ”04d8 ', ATTR {idProduct} ==” f372' MODE = ”0664 ', OWNER =” jmaslak ”

Затем я перезагрузил окно, чтобы они вступили в силу (вы можете сделать это другими способами, но иногда проще перезагрузить окно, чем читать документы, даже если я потеряю несколько очков системного администратора за это). Теперь у меня есть устройство, которым я могу управлять из сценария Raku.

Терминальный интерфейс

Я также хотел бы, чтобы интерфейс командной строки все это видел. По сути, я думал, что могу запустить скрипт, который управляет светом из кадра tmux, чтобы он всегда был мне виден. Я хотел, чтобы интерфейс сообщал мне: «У вас сейчас встреча - это встреча на тему« Что-нибудь », когда у меня встреча. Это может спасти меня от выхода из среды терминала. В то время как я был на этом, иметь интерфейс терминала, также сообщающий мне, когда начнется следующая встреча, если я в данный момент не присутствовал на встрече, казалось мне удобной идеей.

Интерфейс, на котором я остановился, в основном обновлялся раз в минуту (мне нужны доказательства, что он работает!) Со статусом следующей встречи (или указанием, что я сейчас на встрече. Вот пример вывода:

«Ручное изменение» должно быть для меня простым в использовании, и оно должно выходить из режима отмены после начала другого собрания. По сути, он отменяет текущую встречу (встречи), но не будущие.

Поэтому я собрал сценарий, чтобы сделать все это - он будет включать свет на основе моих встреч в календаре Google (включение его за 2 минуты до встречи, выключение через 2 минуты после встречи), а также всякий раз, когда камера используется или когда я вручную отключил камеру.

К этому моменту у меня в основном был сценарий, который делал то, что я думал, что хочу.

Дополнительные улучшения

Со временем я внес в сценарий несколько дополнительных улучшений. Во-первых, я решил, что было бы здорово, если бы Luxafor указывал статус моего личного (не рабочего) календаря, поэтому я расширил скрипт, чтобы разрешить указание нескольких календарей (они оба должны быть доступны для одной и той же учетной записи Google, что не было не проблема). Теперь встречи в любом календаре изменят индикатор.

Это вызвало вторую проблему - подключение Luxafor к моему рабочему компьютеру означало, что он работал только тогда, когда рабочий компьютер был включен. Как мне заставить это работать, когда мой рабочий компьютер выключен? Я переместил ключи Luxafor на другую машину, которая всегда была включена, и это решило проблему, но создало новую: как я узнаю, что веб-камера моего рабочего компьютера используется? Решением было написать усовершенствование моего сценария - службы Ubuntu, которая отслеживает камеру и отправляет UDP-сообщение на машину с запущенным сценарием, указывая, использовалась ли эта удаленная камера. В качестве бонуса это означает, что я также могу отправлять эти сообщения со своей личной Linux-машины, если я когда-нибудь подключу к ней камеру.

Вилка для Раку

Я решил сделать это на языке программирования Raku. Раку - довольно новый язык, который, к сожалению, еще не пользуется заслуженной популярностью. В Raku есть потрясающая поддержка параллелизма. Например, я упомянул, что добавил поддержку удаленных компьютеров, чтобы сигнализировать о доступности камеры. Весь код сетевого сервера - это 25 строк кода (треть из которых - фигурные скобки или пустые строки) с удивительно небольшим «шаблоном»:

Сетевой сервер также поддерживает отправку нажатий клавиш с удаленного клиента (я обычно оставляю монитор на сервере «индикатора занятости» постоянно работающим, чтобы видеть статус собрания и т.п., но мне не нравится, что мне нужно несколько клавиатур на моем компьютере. стол письменный). В коде Raku используется необычный синтаксис (вдохновленный Perl), но он относительно ортогонален и невероятно гибок, так что пусть это не отвлекает вас от фантастического языка!

Итак, как мне это сделать?

Я хотел больше поделиться своими мыслями о том, как я подошел к этой проблеме, чем предоставить пошаговое руководство - я ожидаю, что мое решение очень специфично для моего стиля работы, моей среды, моих периферийных устройств, моей домашней сети и т. Д. надеюсь, что это поможет вдохновить вас на собственное решение.

При этом мой код доступен на Github. Существует установочный документ, в котором здесь описывается установка на Ubuntu (его лучше всего использовать с этим сообщением в блоге в качестве дополнения). Вы также можете просмотреть документацию по актуальному сценарию busy-indicator.raku (параметры командной строки, команды CLI и т. Д.).