Мне давно казалось странным, что современные операционные системы никак не отличают настольный ПК от ноутбука. А ведь ноутбук это мобильное устройство и его батареи далеко не всегда хватает на полный рабочий день. Конечно, есть базовые функции вроде показа оставшегося заряда батареи в процентах и расчет оставшегося времени до полного разряда. Но не понятно как оно рассчитывается и можно ли ему доверять. В общем, решил я написать свой монитор батареи для Ubuntu.
Требования
В качестве источника вдохновения взял монитор батареи на Андроиде:
- иконка с уровнем заряда батареи в трее, рядом число (уровень заряда в процентах)
- по клику на иконку всплывает меню с упрощенным графиком из двух частей: последние несколько часов работы устройства и ожидаемое время разряда
Позже оказалось, что встроить картинку в выпадающее меню — это непосильная для меня задача. Поэтому я решил вместо выпадающего меню выводить график в отдельном окне.
Реализация
Программа состоит из следующих частей:
- Получение данных о заряде батареи и их запись в логи
- Извлечение данных из логов
- Группировка данных по сессиям непрерывной работы
- Преобразование абсолютного времени в относительное время работы устройства
- Сглаживание дискретных данных в пределах сессии
- Расчет времени до полного заряда/разряда
- Генерация изображения
- GUI: иконка в трее, выпадающее меню, график состояния батареи, цветовая тема
Программу хотелось написать с минимальным количеством внешних зависимостей. В настоящий момент используется только Python GI для графического интерфейса (индикатор в трее, окно).
Получение данных реализовано в виде чтения соответствующих файлов из директории /sys/class/power_supply/BAT0/
. Тут можно найти все что относится к электропитанию устройства: текущие значения напряжения и тока, оставшийся заряд в процентах и т.д.
Запись в логи производится каждый раз при изменении уровня заряда, но не реже чем каждые 3-5 минут. Записи с промежутками больше этого будут определятся как периоды отключения ноутбука и не будут показываться на графике. Чтобы учитывать эти перерывы нам нужно преобразование абсолютного времени в виртуальное время работы устройства.
Еще одна особенность входных данных в том, что они дискретные. Уровень заряда батареи отображается в процентах и хранится в виде натурального числа. Поэтому на графике неизбежны ступеньки высотой в 1%.
Сглаживание графиков я пытался делать разными способами. Начал с простого фильтра скользящего среднего, но он не подходит, т.к. вносит нежелательную задержку.
Потом попробовал фильтр Гаусса, но он не подходит тем, что сильно искажает значения в начале и в конце массива данных, а это важно для корректного отображения периодов постоянной работы ноутбука. В противном случае, начало и конец склеенных сессий получают искусственный разрыв.
В итоге, я изобрел велосипед и сделал фильтрацию основанную на оценке производной и изменением частоты дискретизации (сначала снижением, затем повышением). Спорный момент. Думаю, фанаты цифровой обработки сигналов закидают меня камнями, в общем, я открыт к дискуссии.
Расчет времени до полного заряда/разряда реализован через линейную экстраполяцию по касательной. Самое простое решение для начала.
Так как внешних зависимостей добавлять не хотелось, то написал свой генератор SVG-изображений.
Автоматическое определение цветовой темы сделать не получилось, поэтому просто добавил переключатель в выпадающее меню.
На этом, в общем-то, все.
Автор: mingrief