Мне давно казалось странным, что современные операционные системы никак не отличают настольный ПК от ноутбука. А ведь ноутбук это мобильное устройство и его батареи далеко не всегда хватает на полный рабочий день. Конечно, есть базовые функции вроде показа оставшегося заряда батареи в процентах и расчет оставшегося времени до полного разряда. Но не понятно как оно рассчитывается и можно ли ему доверять. В общем, решил я написать свой монитор батареи для Ubuntu.
Требования
В качестве источника вдохновения взял монитор батареи на Андроиде:
- иконка с уровнем заряда батареи в трее, рядом число (уровень заряда в процентах)
- по клику на иконку всплывает меню с упрощенным графиком из двух частей: последние несколько часов работы устройства и ожидаемое время разряда
Позже оказалось, что встроить картинку в выпадающее меню — это непосильная для меня задача. Поэтому я решил вместо выпадающего меню выводить график в отдельном окне.
Реализация
Программа состоит из следующих частей:
- Получение данных о заряде батареи и их запись в логи
- Извлечение данных из логов
- Группировка данных по сессиям непрерывной работы
- Преобразование абсолютного времени в относительное время работы устройства
- Сглаживание дискретных данных в пределах сессии
- Расчет времени до полного заряда/разряда
- Генерация изображения
- GUI: иконка в трее, выпадающее меню, график состояния батареи, цветовая тема
Программу хотелось написать с минимальным количеством внешних зависимостей. В настоящий момент используется только Python GI для графического интерфейса (индикатор в трее, окно).
Получение данных реализовано в виде чтения соответствующих файлов из директории /sys/class/power_supply/BAT0/
. Тут можно найти все что относится к электропитанию устройства: текущие значения напряжения и тока, оставшийся заряд в процентах и т.д.
Запись в логи производится каждый раз при изменении уровня заряда, но не реже чем каждые 3-5 минут. Записи с промежутками больше этого будут определятся как периоды отключения ноутбука и не будут показываться на графике. Чтобы учитывать эти перерывы нам нужно преобразование абсолютного времени в виртуальное время работы устройства.
Еще одна особенность входных данных в том, что они дискретные. Уровень заряда батареи отображается в процентах и хранится в виде натурального числа. Поэтому на графике неизбежны ступеньки высотой в 1%.
Сглаживание графиков я пытался делать разными способами. Начал с простого фильтра скользящего среднего, но он не подходит, т.к. вносит нежелательную задержку.
Потом попробовал фильтр Гаусса, но он не подходит тем, что сильно искажает значения в начале и в конце массива данных, а это важно для корректного отображения периодов постоянной работы ноутбука. В противном случае, начало и конец склеенных сессий получают искусственный разрыв.
В итоге, я изобрел велосипед и сделал фильтрацию основанную на оценке производной и изменением частоты дискретизации (сначала снижением, затем повышением). Спорный момент. Думаю, фанаты цифровой обработки сигналов закидают меня камнями, в общем, я открыт к дискуссии.
Расчет времени до полного заряда/разряда реализован через линейную экстраполяцию по касательной. Самое простое решение для начала.
Так как внешних зависимостей добавлять не хотелось, то написал свой генератор SVG-изображений.
Автоматическое определение цветовой темы сделать не получилось, поэтому просто добавил переключатель в выпадающее меню.
На этом, в общем-то, все.
Комментарии (38)
Labunsky
11.04.2017 00:09+1Но не понятно как оно рассчитывается и можно ли ему доверять
Разве оно не open source?mingrief
11.04.2017 11:54+1Речь не про open source. Посмотрите внимательно на первую картинку, там в трее родной убунтовский индикатор батареи предсказывает 10ч24м работы при текущем потреблении. При этом мой индикатор показывает, что осталось чуть меньше 6ч, а всего на полном заряде ноутбук проживет чуть меньше 8ч.
Теперь на второй картинке (спустя примерно 4ч работы) мы видим, что родной убунтовский индикатор предсказывает 2ч06м, мой около 1ч30м. При этом устройство разрядилось до 25% и похоже действительно проработает чуть меньше 8ч.
Речь о том, что я больше доверяю графику и могу грубо оценить на сколько предсказание верно. При этом я никак (даже примерно) не могу оценить точность предсказания в виде числа в трее.encyclopedist
11.04.2017 15:08Ну так штатный индикатор тоже показывает график. Непонятно, чем ваш принципиально лучше.
Labunsky
11.04.2017 17:24Как уже правильно заметили, графики есть и в стандартном. То есть по сути отличается лишь метод прогнозирования
И отсюда следует вопрос — а почему метод их статьи лучше (хуже, такой же) метода стандартного индикатора? А то, может стоит и форк сделать полноценныйmingrief
11.04.2017 19:27Да, графики есть и в стандартном, но давайте сравним:
Вы видите разницу? Какой вам кажется более понятным?Labunsky
11.04.2017 20:04Вы видите разницу? Какой вам кажется более понятным?
Одна заливка цветом на концептуальную разницу не тянет. Ну а чисто внешне мне стандартный нравится больше, что поделатьmingrief
11.04.2017 20:11Форма графиков за указанные промежутки времени разве никак не привлекли ваше внимание?
Labunsky
11.04.2017 21:30Это шарада?
Ну, индикатор бубунты по каким-то причинам не получал никаких данных от батареи за длинный промежуток времени (поведение, характерное для спящего режима). Почему при этом сторонний индикатор показывает другие даннные — не имею ни малейшего понятияmingrief
11.04.2017 22:12Индикатор убунты показывает астрономическое время. Был у вас выключен ноутбук ночью, получите на графике пустой промежуток.
encyclopedist
11.04.2017 23:21А ваш вырезает это время, так? Что вы делаете со скачками, которые из-за этого происходят (ноутбук зарядился или разрядился пока спал)?
Так вот это сравнение с штатным графиком и должно быть в статье, с обоснованием, почему вы считаете что ваш метод лучше. А в таком виде как статья опубликована, вообще было непонятно зачем это нужно.
mingrief
11.04.2017 23:43Смотрите третий и четвертый пункт в списке частей программы. И далее по тексту абзац про логи, черным по белому.
rPman
11.04.2017 00:21Сохраняйте статистику потребления не только за последние несколько часов, но и пару суток и даже недели, чтобы показывать на графике предыдущие графики за то же время за вчерашний день или даже тот же день недели.
Сделайте это настраиваемым.
Практика использования устройства почти наверняка идентична в одно и то же время/день недели, соответственно можно делать более точный прогноз.
monah_tuk
11.04.2017 07:43Лучший монитор, имхо, в Mate — mate-power-statistics (mate-power-manager):
Запчастей самого Mate почти не тянет. У себя в KDE использую.
ROR191505
11.04.2017 09:01+2Свою программу для мониторинга батареи можно найти у каждой «большой» ДЕ. Зачем писать свой велосипед мне совершенно не понятно.
Я исползую gnome-power-statistics. Отличная вещь.
mingrief
12.04.2017 11:18Зачем писать свой велосипед? Причин несколько:
- не нравится стандартный монитор батареи (обсуждение)
- в образовательных целях (linux, python, open source, signal processing, SVG)
- почему бы и нет?
inferrna
11.04.2017 10:39+21. Картинку в выпадающем меню можно подсмотреть в коде часов — вместо календарика вставить элемент картинки.
2. Ступеньки можно сгладить через fftpack из scipy — делаете одномерный dct, забиваете нулями в конце до нужной размерности, потом обратное преобразование.mingrief
11.04.2017 10:481. В этом и была моя изначальная задумка, но, как я написал в статье, у меня не получилось. Я смотрел исходный код часов (написан на С), но не нашел соответствующие возможности в Python GTK.
mingrief
11.04.2017 10:57+1Наверное, это возможно. У меня сохранилась ссылка на похожий вопрос на stackoverflow. Это делается через какие-то хаки, поэтому я решил пойти простым путем.
Bratak
11.04.2017 13:35Не совсем понял, зачем нужна такая реализация.Если хочется получить результат точнее текущего-надо брать и писать свой драйвер, который будет читать прямо с smbus данные от контроллера заряда батареи, и уже только после этого интерпретировать его.А взять данные от демона, которые сам их уже обработал, выдал в виде относительных величин в файл, и эти данные обрабатывать второй раз, внося определенную погрешность в вычисления-не понимаю совсем такого подхода.Неужели в linux foudation совсем далекие ребята сидят?
mingrief
11.04.2017 13:56+1Посмотрите, пожалуйста, пример из комментария выше. Там родной убунтовский индикатор батареи предсказывает еще 10ч30м работы (после 2ч работы, т.е. общее время 12ч30м), хотя устройство всего проработало около 7ч30м. Это 40% погрешность. Я думаю, что это не источник данных вносит такую погрешность, а способ расчета. Если на вход моего монитора приходят данные с 1-2% погрешностью, меня это вполне устраивает. О каких порядках погрешностей вы говорите?
x0wl
11.04.2017 16:24Не имею ничего против автора, но это выглядит как изобретение велосипеда, потому что такие мониторы встроены почти во все современные ос / дистрибутивы.
Вы бы лучше экстраполяцию сделали какой-нибудь более хорошей моделью (ARIMA?), вот это стало бы хорошим тычком в сторону тех, кто считает, что невозможно по-нормальному оставшееся время работы предсказывать.mingrief
11.04.2017 16:30Я бы предпочел начать с простой и прямолинейной реализации, не сильно заботясь об оптимизации, и постепенно улучшать продукт.
Hellsy22
Писать монитор батареи с вычислениями на питоне — это почти так же забавно, как и писать монитор памяти на Java.
mingrief
Извините, не понятно, хотелось бы увидеть развернутый комментарий.
voyager-1
Обычно такие вещи пишут на Си, ну или на худой конец — на любом другом компилируемом языке. Python и Java же — относятся к языкам интерпретируемым, а от того — обычно значительно более медленным в работе. Правда для такого приложения — это не принципиально.
А вот процессор желательно дёргать пореже (чтобы задержка между проверками состояния батареи была достаточной) — а то батарея может начать расходоваться значительно быстрее, так как большинство функций процессора по сохранению энергии в таком режиме перестают работать.
mingrief
Я тоже думаю, что «для такого приложения — это не принципиально», поэтому и попросил развернутого комментария от Hellsy22.
mihmig
Если не ошибаюсь — питон-скрипты можно тоже компилировать. Вон IDE Activestate Komodo так и сделано.
iSergios
А в чем, собственно, проблема? Прочесть, слегка обсчитать, отрисовать — такое можно писать на чем угодно, накладные расходы все равно мизерные. А Вы так говорите, словно автор напитонил целый драйвер устройства.
icCE
Согласен. Особенно когда смотришь на современные драйвера под 500 метров, да еще с дотнетом и прочим прочим, это просто манна небесная.
HSerg
Ограниченный min/max размером jvm-памяти монитор на Java в худшем случае упадёт сам, а вот протекающий на мелких событиях C/C++ монитор всех остальных переживёт и умрёт последним. Это из личного опыта.