[Из песочницы] Монитор батареи ноутбука на Ubuntu

Мне давно казалось странным, что современные операционные системы никак не отличают настольный ПК от ноутбука. А ведь ноутбук это мобильное устройство и его батареи далеко не всегда хватает на полный рабочий день. Конечно, есть базовые функции вроде показа оставшегося заряда батареи в процентах и расчет оставшегося времени до полного разряда. Но не понятно как оно рассчитывается и можно ли ему доверять. В общем, решил я написать свой монитор батареи для Ubuntu.


40dc0658eaaa40f4bcf255f842228b48.png

В качестве источника вдохновения взял монитор батареи на Андроиде:


  • иконка с уровнем заряда батареи в трее, рядом число (уровень заряда в процентах)
  • по клику на иконку всплывает меню с упрощенным графиком из двух частей: последние несколько часов работы устройства и ожидаемое время разряда


9d93246b836a4bf78bc165d576680e34.png

Позже оказалось, что встроить картинку в выпадающее меню — это непосильная для меня задача. Поэтому я решил вместо выпадающего меню выводить график в отдельном окне.

Программа состоит из следующих частей:


  • Получение данных о заряде батареи и их запись в логи
  • Извлечение данных из логов
  • Группировка данных по сессиям непрерывной работы
  • Преобразование абсолютного времени в относительное время работы устройства
  • Сглаживание дискретных данных в пределах сессии
  • Расчет времени до полного заряда/разряда
  • Генерация изображения
  • GUI: иконка в трее, выпадающее меню, график состояния батареи, цветовая тема

Программу хотелось написать с минимальным количеством внешних зависимостей. В настоящий момент используется только Python GI для графического интерфейса (индикатор в трее, окно).

Получение данных реализовано в виде чтения соответствующих файлов из директории /sys/class/power_supply/BAT0/. Тут можно найти все что относится к электропитанию устройства: текущие значения напряжения и тока, оставшийся заряд в процентах и т.д.

Запись в логи производится каждый раз при изменении уровня заряда, но не реже чем каждые 3–5 минут. Записи с промежутками больше этого будут определятся как периоды отключения ноутбука и не будут показываться на графике. Чтобы учитывать эти перерывы нам нужно преобразование абсолютного времени в виртуальное время работы устройства.

Еще одна особенность входных данных в том, что они дискретные. Уровень заряда батареи отображается в процентах и хранится в виде натурального числа. Поэтому на графике неизбежны ступеньки высотой в 1%.


924fdcf4115246c2ad52dfa8e84b15fc.png

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


8b5d1ffb165e47e585918ed4a4792da7.png

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


d4bafb3b063f43a795c8302852459772.png

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


ad05098fc88b4681b20c5686347142d8.png


fa8cab7502364466b6ab55d0e906dfbf.png

Расчет времени до полного заряда/разряда реализован через линейную экстраполяцию по касательной. Самое простое решение для начала.


687c67f89c3c4eaf9b556d4d1625f34e.png

Так как внешних зависимостей добавлять не хотелось, то написал свой генератор SVG-изображений.

Автоматическое определение цветовой темы сделать не получилось, поэтому просто добавил переключатель в выпадающее меню.

На этом, в общем-то, все.

→ Ссылка на GitHub

© Geektimes