
Мой трекер продуктивности — это «волшебное зеркало», но вместо времени, погоды и мотивационных цитат оно показывает:
- Сколько времени я сегодня потратил на рабочие задачи за компьютером и в смартфоне (RescueTime).
- Мой список дел из Trello.
- «Радарный график», отображающий мои затраты времени на разные категории приложений по сравнению со вчерашним днём (RescueTime).
- Недельные итоги (RescueTime).
Если вы потратили больше 50 % времени на рабочие задачи, вокруг зеркала будет яркая зелёная подсветка. Если меньше 50 % — подсветка будет красной, сигнализируя вам, что нужно повысить продуктивность! Впрочем, распределение вы можете задать самостоятельно.


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

Я несколько месяцев собирался написать эту статью. Но мне этого не позволял мой старый друг по имени «Прокрастинация». Я постоянно откладывал написание, заполняя своё время просмотром видео из тёмных глубин YouTube.
Однажды я читал статью о прокрастинации и узнал про сервисы, которые могли бы помочь в решении моей проблемы: диспетчер задач Trello и планировщик времени RescueTime. Оба прекрасно подошли под мои нужды, но через какое-то время я перестал заходить на их страницы и начал игнорировать уведомления. И тогда я пришёл к идее своего проекта: хочу отображать данные из приложений на зеркало, висящее на стене. Тогда я точно не спрячусь от своих обязанностей.
Первый набросок проекта был простым: буду использовать API RescueTime API для отображения моей продуктивной/отвлекающей деятельности, а API Trello API — для отображения списка задач на день. Но позднее я добавил и другие возможности, но об этом ниже.
Инструменты и компоненты
Эти инструменты я использовал для создания своего трекера, ваш набор может быть другим!
Для рамы:
- 4 метра фанеры 7 x 15 см — зависит от размера вашего монитора.
- Одностороннее зеркало 30 x 40 см — зависит от размера вашего монитора.
- Монитор 25 x 35 см — нашёл на блошином рынке. Можете использовать любой.
- Raspberry Pi 3 Model B — подойдёт и Raspberry Pi 2, но придётся найти Wi-Fi-модуль.
- Кабель HDMI.
Для светодиодной подсветки:
- Двухметровая RGB-светодиодная лента smd5050 — нужна именно smd5050, причину объясню ниже.
- Три N-канальных мосфета (например, IRLZ34N).
- Блок питания 12 В — 2 A.
- Макетная плата.
Инструменты:
- Пила по дереву.
- Клей для дерева.
- Паяльные принадлежности (для светодиодной подсветки).
Код

Эта глава состоит из трёх частей, вам не нужны все перечисленные выше компоненты, пока достаточно лишь Raspberry Pi и монитора.
Настройка Raspberry Pi
Если вы ещё не настроили Raspberry Pi, сделайте это. Для проекта вам понадобится установить веб-сервер Apache и PHP-LED-контроллер.
Руководство по установке Apache: https://www.raspberrypi.org/documentation/remote-access/web-server/apache.md.
Руководство по установке PHP-LED-контроллера: https://github.com/k1sul1/Raspberry-Pi-PHP-LED-controller.
Теперь из репозитория проекта скачайте на вашу Raspberry Pi файл index.php и положите его сюда:
/var/www/html/Если не знаете, как перемещать файлы с помощью терминала Linux, почитайте здесь: https://www.linux.com/learn/how-move-files-using-linux-commands-or-file-managers.
Адаптация кода
Здесь потребуются небольшие знания HTML/CSS.
Мы будем адаптировать файл index.php, являющийся сердцем проекта. Подключите монитор к Raspberry Pi. Если попытаетесь открыть index.php, то ничего не выйдет, потому что сначала нужно вставить в код API-ключи. Для этого войдите в аккаунт на сайте RescueTime, перейдите в раздел для разработчиков и нажмите Activate This Key. Сохраните куда-нибудь этот ключ.
То же самое сделайте и для API Trello: войдите в аккаунт и на портале для разработчиков сгенерируйте API-ключ.
Теперь откройте в своём текстовом редакторе файл index.php, лежащий в
/var/www/html/, и замените [API_KEY] на ключи из RescueTime и Trello. [list_number] — номер списка, который нужен для получения списка задач из Trello. Чтобы сгенерировать номер, сначала создайте в Trello свежий список и назовите «To-Do», задачи из этого списка будут отображаться на волшебном зеркале.Теперь скопируйте из строки браузера адрес, который выглядит так:
https://trello.com/b/3hS6yyLo/board-nameдобавьте в конце .json: https://trello.com/b/3hS6yyLo/board-name.json
нажмите Enter, и экран заполнится кодом. Найдите в этом хаосе имя вашего списка ''To-Do". Это должно выглядеть подобным образом:
{"name":"To Do","id":"5981c123cd1b23f13907cd18"}, здесь id — идентификатор вашего списка. Вставьте его значение в [list_number] в файле index.php.Теперь откройте браузер, в адресной строке напишите localhost и нажмите Enter. На графиках должны отобразиться ваши данные.
Примечание: местоположение графиков может отличаться из-за разрешения вашего монитора. Настроить ширину, высоту и расположение элементов можно в CSS-разделе кода.
Теперь осталось сделать рамку для монитора и подключить светодиоды.
Примечание: если вас не интересует подробное рассмотрение API, можете сразу перейти к следующей главе.
API в подробностях
В основе проекта лежат два API:
Хотя в документации есть вся нужная информация, я объясню, какие данные из API использует наш проект.
В разделе управления временем вызывается RescueTime API и запрашивается информация о сегодняшнем распределении времени:
"https://www.rescuetime.com/anapi/data?key=[API_KEY]&perspective=rank&interval=hour&restrict_begin=".date('Y-m-d')."&restrict_end=".date('Y-m-d')."&format=json"Здесь
date('Y-m-d') — текущая дата.
perspective=rank — вид сортировки данных. В данном случае по «категории», то есть на что потрачено больше всего времени.
После выполнения вызова мы получаем файл в JSON-формате (см. код файла data.json в конце главы). Из него мы возьмём «Time Spent (seconds)» и «Productivity» (может иметь значения от -2 (отвлекаешься) до 2, (продуктивен)). На основе этих данных можно сгенерировать индекс продуктивности со значением больше 100.
Следующий вызов API RescueTime:
"https://www.rescuetime.com/anapi/daily_summary_feed?key=[API_KEY]"Вы получите недельный отчёт (см. код файла summary.json в конце главы). Эти данные используются для построения недельного графика.
Вызов Trello API:
"https://api.trello.com/1/lists/[list_number]/cards?fields=name&key=[API_KEY]&token=[Token]"Вы получите данные из карточек задач в Trello:
[{"id":"5a4160103bfcd14994852f59","name":"ceylan cinemagraph"},{"id":"59e8241f6aa8662a51eb7de6","name":"Learn GitHuB"},{"id":"5981c19577c732f826ad8025","name":"Publish Instructible"},{"id":"5a341dba7f17d235d7c5bbd1","name":"SPACE PROGRAM"}]В карточках вы можете размещать текст и передавать его ещё куда-нибудь.
data.json
Код
Formatted JSON Data
{
"notes":"data is an array of arrays (rows), column names for rows in row_headers",
"row_headers":[
"Rank",
"Time Spent (seconds)",
"Number of People",
"Activity",
"Category",
"Productivity"
],
"rows":[
[
1,
1536,
1,
"en.0wikipedia.org",
"Uncategorized",
0
],
[
2,
1505,
1,
"youtube.com",
"Video",
-2
],
[
3,
1178,
1,
"OpenOffice",
"Writing",
2
],
[
4,
709,
1,
"moodle.bilkent.edu.tr",
"General Reference \u0026 Learning",
2
],
[
5,
602,
1,
"google.com.tr",
"Search",
2
],
[
6,
439,
1,
"reddit.com",
"General News \u0026 Opinion",
-2
],
[
7,
437,
1,
"tr.sharelatex.com",
"Writing",
2
],
[
8,
361,
1,
"yemeksepeti.com",
"General Shopping",
-2
],
[
9,
356,
1,
"Gmail",
"Email",
0
],
[
10,
328,
1,
"Google Chrome",
"Browsers",
0
],
[
11,
207,
1,
"stars.bilkent.edu.tr",
"General Reference \u0026 Learning",
2
],
[
12,
179,
1,
"whatsapp",
"Instant Message",
-1
],summary.json
Код
[
{
"id":1515657600,
"date":"2018-01-11",
"productivity_pulse":54,
"very_productive_percentage":34.2,
"productive_percentage":10.6,
"neutral_percentage":25.6,
"distracting_percentage":0.0,
"very_distracting_percentage":29.6,
"all_productive_percentage":44.8,
"all_distracting_percentage":29.6,
"uncategorized_percentage":16.1,
"business_percentage":6.0,
"communication_and_scheduling_percentage":4.3,
"social_networking_percentage":0.0,
"design_and_composition_percentage":0.0,
"entertainment_percentage":15.2,
"news_percentage":3.3,
"software_development_percentage":5.4,
"reference_and_learning_percentage":22.8,
"shopping_percentage":12.9,
"utilities_percentage":14.1,
"total_hours":2.51,
"very_productive_hours":0.86,
"productive_hours":0.27,
"neutral_hours":0.64,
"distracting_hours":0.0,
"very_distracting_hours":0.74,
"all_productive_hours":1.12,
"all_distracting_hours":0.74,
"uncategorized_hours":0.4,
"business_hours":0.15,
"communication_and_scheduling_hours":0.11,
"social_networking_hours":0.0,
"design_and_composition_hours":0.0,
"entertainment_hours":0.38,
"news_hours":0.08,
"software_development_hours":0.13,
"reference_and_learning_hours":0.57,
"shopping_hours":0.32,
"utilities_hours":0.35,
"total_duration_formatted":"2h 30m",
"very_productive_duration_formatted":"51m 26s",
"productive_duration_formatted":"15m 56s",
"neutral_duration_formatted":"38m 34s",
"distracting_duration_formatted":"no time",
"very_distracting_duration_formatted":"44m 30s",
"all_productive_duration_formatted":"1h 7m",
"all_distracting_duration_formatted":"44m 30s",
"uncategorized_duration_formatted":"24m 11s",
"business_duration_formatted":"9m 6s",
"communication_and_scheduling_duration_formatted":"6m 26s",
"social_networking_duration_formatted":"no time",
"design_and_composition_duration_formatted":"no time",
"entertainment_duration_formatted":"22m 49s",
"news_duration_formatted":"4m 55s",
"software_development_duration_formatted":"8m 3s",
"reference_and_learning_duration_formatted":"34m 17s",
"shopping_duration_formatted":"19m 22s",
"utilities_duration_formatted":"21m 17s"
},
{
"id":1515571200,
"date":"2018-01-10",
"productivity_pulse":33,
"very_productive_percentage":21.9,
"productive_percentage":2.3,
"neutral_percentage":14.4,
"distracting_percentage":11.0,
"very_distracting_percentage":50.3,
"all_productive_percentage":24.2,
"all_distracting_percentage":61.4,
"uncategorized_percentage":0.3,
"business_percentage":0.0,
"communication_and_scheduling_percentage":13.5,
"social_networking_percentage":0.0,
"design_and_composition_percentage":6.3,
"entertainment_percentage":44.7,
"news_percentage":4.2,
"software_development_percentage":0.0,
"reference_and_learning_percentage":15.5,
"shopping_percentage":0.0,
"utilities_percentage":15.4,
"total_hours":2.24,
"very_productive_hours":0.49,
"productive_hours":0.05,
"neutral_hours":0.32,
"distracting_hours":0.25,
"very_distracting_hours":1.13,
"all_productive_hours":0.54,
"all_distracting_hours":1.37,
"uncategorized_hours":0.01,
"business_hours":0.0,
"communication_and_scheduling_hours":0.3,
"social_networking_hours":0.0,
"design_and_composition_hours":0.14,
"entertainment_hours":1.0,
"news_hours":0.09,
"software_development_hours":0.0,
"reference_and_learning_hours":0.35,
"shopping_hours":0.0,
"utilities_hours":0.34,
"total_duration_formatted":"2h 14m",
"very_productive_duration_formatted":"29m 22s",
"productive_duration_formatted":"3m 8s",
"neutral_duration_formatted":"19m 18s",
"distracting_duration_formatted":"14m 48s",
"very_distracting_duration_formatted":"1h 7m",
"all_productive_duration_formatted":"32m 30s",
"all_distracting_duration_formatted":"1h 22m",
"uncategorized_duration_formatted":"27s",
"business_duration_formatted":"1s",
"communication_and_scheduling_duration_formatted":"18m 5s",
"social_networking_duration_formatted":"no time",
"design_and_composition_duration_formatted":"8m 30s",
"entertainment_duration_formatted":"59m 54s",
"news_duration_formatted":"5m 39s",
"software_development_duration_formatted":"no time",
"reference_and_learning_duration_formatted":"20m 51s",
"shopping_duration_formatted":"no time",
"utilities_duration_formatted":"20m 39s"
},
{
"id":1515484800,
"date":"2018-01-09",
"productivity_pulse":68,
"very_productive_percentage":60.4,
"productive_percentage":0.5,
"neutral_percentage":11.0,
"distracting_percentage":7.1,
"very_distracting_percentage":21.0,
"all_productive_percentage":60.9,
"all_distracting_percentage":28.1,
"uncategorized_percentage":9.1,
"business_percentage":21.9,
"communication_and_scheduling_percentage":7.2,
"social_networking_percentage":5.1,
"design_and_composition_percentage":1.2,
"entertainment_percentage":1.6,
"news_percentage":12.5,
"software_development_percentage":9.1,
"reference_and_learning_percentage":28.2,
"shopping_percentage":2.9,
"utilities_percentage":1.2,
"total_hours":2.78,
"very_productive_hours":1.68,
"productive_hours":0.01,
"neutral_hours":0.31,
"distracting_hours":0.2,
"very_distracting_hours":0.58,
"all_productive_hours":1.69,
"all_distracting_hours":0.78,
"uncategorized_hours":0.25,
"business_hours":0.61,
"communication_and_scheduling_hours":0.2,
"social_networking_hours":0.14,
"design_and_composition_hours":0.03,
"entertainment_hours":0.04,
"news_hours":0.35,
"software_development_hours":0.25,
"reference_and_learning_hours":0.78,
"shopping_hours":0.08,
"utilities_hours":0.03,
"total_duration_formatted":"2h 46m",
"very_productive_duration_formatted":"1h 40m",
"productive_duration_formatted":"47s",
"neutral_duration_formatted":"18m 23s",
"distracting_duration_formatted":"11m 49s",
"very_distracting_duration_formatted":"34m 57s",
"all_productive_duration_formatted":"1h 41m",
"all_distracting_duration_formatted":"46m 46s",
"uncategorized_duration_formatted":"15m 7s",
"business_duration_formatted":"36m 26s",
"communication_and_scheduling_duration_formatted":"11m 59s",
"social_networking_duration_formatted":"8m 28s",
"design_and_composition_duration_formatted":"2m 4s",
"entertainment_duration_formatted":"2m 39s",
"news_duration_formatted":"20m 49s",
"software_development_duration_formatted":"15m 5s",
"reference_and_learning_duration_formatted":"46m 59s",
"shopping_duration_formatted":"4m 51s",
"utilities_duration_formatted":"2m 3s"
}
]Прототипирование



Данные теперь выводятся на монитор, пришла пора спроектировать рамку и зеркало. Здесь всё зависит от ваших предпочтений. Я взял светлую древесину, потому что она больше подходит к моему интерьеру.
Если вы хотите выбрать другую конструкцию рамы, то есть несколько отличных руководств:
https://www.instructables.com/id/Smart-Mirror-by-Raspberry-Pi/
https://www.instructables.com/id/Raspberry-Pi-Smart-Mirror/
https://www.instructables.com/id/Magic-Mirror/
Размеры заготовок для моей рамы:
Передняя сторона:
- 2 x 40 см
- 2 x 47 см
Задняя сторона:
- 2 x 38 см
- 2 x 50 см
Сборка рамы и зеркала



Некоторые замечания:
- Для сборки рамы я использовал клей для дерева. После установки зеркала в раму дополнительно вклеил в углах деревянные треугольники, фиксирующие зеркало. Но потом я понял, что это было не лучшим решением, поскольку из-за треугольников рама не прижимается к стене.
- Прежде чем склеивать детали, соберите всё на сухую и проверьте, нет ли зазоров вокруг монитора или других недочётов.
Сборка электроники








Если делаете базовую версию без светодиодов, можете пропустить соответствующий этап.
Схемы сборки и установки светодиодов взяты из двух разных руководств:
How to control a RGB LED-Strip with a Raspberry Pi
Raspberry Pi PHP LED controller
Важные замечания:
Я использовал такие пины:
- GPIO17 для красного провода.
- GPIO22 для зелёного провода.
- GPIO24 для синего провода.
Если хотите использовать другие пины, придётся изменить их номера в начале index.php.
Проверка

Всё должно работать нормально, но для запуска браузера и ввода localhost понадобятся мышь и клавиатура.
1. Запустите терминал и введите:
sudo nano /home/pi/.config/lxsession/LXDE-pi/autostart2. Затем введите:
chromium-browser --kiosk --incognito "http://localhost/index.php"Теперь можно отключить мышь и клавиатуру. Браузер должен запуститься и открыть файл index.php.
Устранение неисправностей
У меня ошибка API
У наших API есть ограничения на количество обращений. Если дёргать их слишком часто, получите ошибку. Для решения этой проблемы добавьте в index.php задержку обновления, по умолчанию стоит 360 секунд.
#Seconds to refresh the webpage<br>$sec = "360";Браузер не открывается при загрузке
В разных ОС файл autostart находится в разных местах. Я использовал Raspbian GNU/Linux 8.0 Jessie, так что уточните, где лежит этот файл в вашей ОС.
Светодиоды светятся разным цветом
Подключение светодиодных лент может различаться, и наверняка цветовые подключения перемешаны. Исправить это можно с помощью припайки проводов к правильным контактам. Также можете подстроить цвета подсветки с помощью HEX-значений в index.php.
if ($oran<50) { $led->setHex("#FF0000"); }else { $led->setHex("#00FF00"); }Вот вам в помощь HEX-калькулятор цветов.
Хочу использовать другие графики
Я применил JS-библиотеку chart.js. Если хотите использовать другие графики, почитайте документацию: http://www.chartjs.org/samples/latest/
Что дальше
Есть много способов улучшения этого проекта. Например:
- Экран побольше: тогда можно выводить гораздо больше графиков, или оставить часть площади именно под зеркало.
- Интеграция разных API: сегодня доступно огромное количество всевозможных API (Twitter, Google и множество других). Мне пришла в голову идея со Spotify API, чтобы отображать на зеркале, какая песня сейчас играется. Вот вам список для мозгового штурма: www.programmableweb.com/apis/directory
- Голосовое управление Amazon Alexa: у меня стоит такое устройство, могу с помощью голоса управлять светом. Можно прикрутить Алексу для управления графиками на зеркале.
