Исправление конфигурации Home Assistant после обновления до v0.89

Всякие умные девайсы дома интегрированы в удобную штуку – Home Assistant, а само приложение крутится в докер-контейнере на моём домашнем Linux-сервере. Home Assistant релизится каждые две недели, я слежу за их обновлениями через RSS и обновляю всё дома простым перезапуском сервиса.

Обычно всё проходит гладко, но вот с при обновлении на v0.89 всё сломалось, о чём мне заботливо сообщил Uptime Robot. Пошёл смотреть логи, там было что-то странное:

INFO (MainThread) [homeassistant.core] Starting Home Assistant
ERROR (MainThread) [homeassistant.core] Error doing job: Task exception was never retrieved
 Traceback (most recent call last):
   File "/usr/src/app/homeassistant/core.py", line 1110, in async_call
     raise ServiceNotFound(domain, service) from None
 homeassistant.exceptions.ServiceNotFound: (ServiceNotFound(...), 'Service persistent_notification.create not found')
INFO (MainThread) [homeassistant.core] Timer:starting

Погуглил ошибку Service persistent_notification.create, но решения не нашёл, такое случалось у других людей с месяц назад, по причине изменения требований к формату некоторых конфигов, но, повторюсь, для меня это оказалось не применимо.

Пошёл разбираться, как проверить конфиг.

Зашёл внутрь запущенного контейнера

docker exec -it home-assistant bash

Там выполнил команду check_config:

python -m homeassistant --script check_config --config /config

Получил такое сообщение:

Testing configuration at /config
WARNING:homeassistant.components.http:Configuring 
trusted_networks via the http component has been deprecated. 
Use the trusted networks auth provider instead. 
For instructions, see 
https://www.home-assistant.io/docs/authentication/providers/#trusted-networks

Открыл настройки авторизации, исправил всё так, как нужно по документации – и всё починилось.

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

UPD: Похоже, внимательно дочитал раздел Breaking Changes и обнаружил там упоминание, что вручную сконфигурированные trusted_networks всё сломают ;)

Восстанавливаем работу USB-UART CH340G после апгрейда до Mojave

Так вышло, что я немного увлёкся разного рода микроконтроллерами и для прошивки пока использую простейший USB-UART на базе микросхемы CH340G. Сегодня принёс домой RFID/NFC контроллер PN532 и наверно с час  пытался завести его через libnfc. Ноnfc-poll упорно возвращал “No NFC device found”.

Уже сложил всё обратно в коробку и собрался идти спать, как вдруг пришло в голову проверить, а не отломали ли чего при обновлении до MacOS Mojave? И точно, снова что-то там не срослось с драйверами, если верить беглому поиску по интернету.

Решение простое – отрываем консоль и там вводим

sudo rm -rf /Library/Extensions/usbserial.kext
sudo reboot

После перезагрузки nfc-poll успешно нашёл NFC-ридер и пришлось исследовать всё, что хоть как-то походило на NFC-карту ;)

Логирование тела запроса в NGINX

Возникла (и уже не первый раз) необходимость залогировать тело json-запроса, приходящего от удалённого клиента. Делать логирование на стороне приложения не хотелось, потому что во-первых, это некрасиво, во-вторых — надо приложение пересобрать и передеплоить — то есть долго. На входе у нас стоит NGINX, и вот его можно гибко настроить и, что важно, изменения применяются мгновенно.

Для начала нужно сконфигурировать сообщение, которое будем логировать. В документации к директиве log_format можно найти много всякого интересного, но там нет нужной нам переменной, хотя она есть. Я добавил вот такую записать с секцию http в nginx.conf:

log_format postdata escape=json '"$request" $status'
                                ' [REQUEST BODY]: $request_body';

Здесь postdata — это название нашего кастомного формата сообщения для логирования, escape=json нужно для того, чтобы json-данные в логах были читаемы. Далее в кавычках само сообщение, как видим, оно может быть многострочным. Переменная $request содержит сам запрос, вида "POST /route/handler HTTP/1.0", $status — HTTP-код ответа, а $request_body — та самая переменная, которая отсутствует в документации, тело запроса.

Теперь нужно добавить использование нашего кастомного формата сообщения в нужном месте в конфигурации NGINX. Для этого используется директива access_log, которую можно переопределять на уровне секций http, server, location, if in location и limit_except. Наиболее удобным выглядит location или if in location, это позволит минимизировать распухание логов.

Но после добавления директивы access_log в нужное место произошло странное — часть запросов логировалась нормально, а для части из них $request_body оказывался пустым. Дело оказалось в том, что NGINX сохраняет в переменную $request_body только запросы ограниченной длины, по умолчанию 8 или 16 кб. Для более тяжёлых запросов не сохраняется ничего. Поэтому итоговая конфигурация получилась такой:

location ~ ^/awesome-location/(\w+)$ {
  access_log /var/log/nginx/access.log postdata;
  client_body_buffer_size 64k;
  # остальные директивы
}

Делаем git pull —rebase опцией по умолчанию

В конце января я рассказывал на митапе PiterCSS о том, как использовать интеграцию git с WebStorm (и любой другой IDE от JetBrains) на полную катушку.

В том числе, про то, как быстро синхронизироваться с удалённой копией репозитория (VCS > Update Project… или ⌘ + T/Ctrl + T). При выполнении этой команды появляется вот такое окошко:

2018-06-15_16-06-35

Для того, чтобы история изменений была линейной — желательно использовать Update Type: Rebase, но делать это каждый раз — откровенно лень. И вот встал вопрос, а как же использовать стратегию обновления git pull --rebase по умолчанию? К сожалению, тогда я не смог дать ответа на этот вопрос.

Но вот сегодня копаясь на внутренней вики в нашей компании увидел, что это очень легко делается через терминал:

git config --global branch.autosetuprebase always

Эта настройка будет действовать для всех вновь создаваемых репозиториев, для тех, что уже созданы нужно выполнить из консоли вот эту команду, находясь в каталоге с нужным проектом:

git config branch.master.rebase true

Удалить всё, что не *.mp3

Возникла необходимость удалить из каталога все файлы, за исключением mp3. В каталоге 60 подкаталогов, в каждом подкаталоге 10-20 разных файлов. Руками такое делать бесконечно утомительно. Но можно открыть консоль и набрать там такое:

find /media/sdcard -type f -not -regex ".*.mp3" -exec rm {} \;

эта команда отыщет все файлы в каталоге /media/sdcard и его подкаталогах, которые подходят под два условия:

  • - type f — простой файл (исключаем каталоги)
  • - not -regex ".*.mp3" — имеют любое расширение, кроме .mp3

А дальше команда все эти файлы передаются в команду rm и благополучно удаляются.