
Мой трекер продуктивности — это «волшебное зеркало», но вместо времени, погоды и мотивационных цитат оно показывает:
- Сколько времени я сегодня потратил на рабочие задачи за компьютером и в смартфоне (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: у меня стоит такое устройство, могу с помощью голоса управлять светом. Можно прикрутить Алексу для управления графиками на зеркале.
