![](https://habrastorage.org/webt/co/zz/ig/cozzig_w09j1hipfnm5gfzfovti.png)
Недавно получил свой заказ с новой логической платой от Sensor Watch для вездесущих классических часов Casio F-91W. Модель F-91W не требует представления. Это наверняка самые популярные кварцевые часы в мире, которых в общей сложности было продано около 90 миллионов.
В купленной мной плате Sensor Watch оригинальный кварцевый механизм F-91W заменён новым мозгом на базе ARM Cortex M0+. В ней используются оригинальный ЖК-дисплей, толкатели для кнопок и пьезодинамик. Эта программируемая плата, и проект Sensor Watch также предоставляет простой в плане модификаций набор циферблатов и небольшие дополнительные приложения.
В устройстве нет Bluetooth, но комбинация легковесного, проверенного временем корпуса с долгоживущей батареей и функциональностью, которую без проблем можно воссоздать дома, на удивление великолепна. Где-то за час я смог: заменить плату, настроить двухфакторную аутентификацию (2FA) для своих аккаунтов Google и GitHub, чтобы получать наиболее часто используемые OTP-коды прямо на своё запястье, и написать циферблат-счётчик, который можно использовать для отсчёта шагов или взмахов при гребле на лодке.
Хакать такой девайс — одно удовольствие. Причём для него есть даже эмулятор на основе WASM, который упрощает тестирование на ПК и позволяет поиграться с различными кастомными сборками, например, с моей (в оригинале статьи доступна интерактивная версия часов, — прим. пер.):
![](https://habrastorage.org/webt/hz/m7/4k/hzm74kgvndbce54btxwdoq0qlh4.png)
Нажмите MODE один раз, чтобы перейти на экран 2FA-токенов. Сейчас ALARM выполняет переключение между токенами Google и GitHub. Не беспокойтесь, я заменил свои реальные секреты TOTP фиктивными значениями. Нажмите ещё раз MODE, чтобы перейти на разработанный мной циферблат со счётчиком. Теперь периодически нажимайте ALARM, чтобы измерять частоту в минуту или иной интересующий вас показатель. Среди прочих циферблатов в этой сборке присутствуют мировые часы, калькулятор времени восходов/закатов, индикатор лунных фаз, показания температурного датчика в реальном времени, установщик формата 24h и режим настройки даты/времени. В дереве исходного кода
movement
репозитория Sensor Watch есть и много других крутых циферблатов, включая тонометр и модель Солнечной системы.Весь процесс апгрейда модуля F-91W хорошо описан в блоге Джона Грэхама-Камминга — я даже заказал один экземпляр его крутых оранжевых часов, чтобы переставить туда новую плату.
Ниже я поделюсь о том, как перенести ваши секреты TOTP в сборку, и расскажу о своей разработке нового циферблата.
Циферблат TOTP
Этот циферблат генерирует одноразовые пароли с привязкой ко времени (двухфакторные коды аутентификации), позволяя безопасно авторизовываться на многих популярных сайтах (например, Google и GitHub). Механизм TOTP (time-based one-time password) представляет собой алгоритм, который генерирует одноразовый пароль (OTP), обеспечивая его уникальность на основе текущего времени.
Нажмите кнопку ALARM для переключения между настроенными сайтами/секретами TOTP.
Этот циферблат поддерживает несколько секретов сайтов, которые нужно извлекать из QR-кодов TOTP и добавлять в его исходный код следующим образом:
- Получать секрет TOTP или QR-код от сайта, для которого требуется сгенерировать коды.
- Если у вас есть только QR-код, сайт Штефана Сандина позволит извлечь его секрет в кодировке Base32 — это будет буквенно-цифровая строка из примерно 32 символов.
- Для добавления полученного секрета в код циферблата нужно преобразовать его в шестнадцатеричные байты. Сделать это можно на сайте cryptii.com. Обратите внимание, что TOTP-секрет нужно вводить в верхнем регистре.
- Наконец, вам нужно взять полученные шестнадцатеричные байты, добавить их в исходный код циферблата TOTP и заново скомпилировать
movement
:
▍ Редактирование totp_face.c
Вы можете решить удалить демо-ключи. Предположим, вы захотите добавить ключ в конец списка. В таком случае прибавьте единицу к числу в этой строке:
static const uint8_t num_keys = 2;
Добавьте шестнадцатеричные байты, полученные на шаге 3, в конец этого массива, разделив их запятыми и указав в начале каждого
0x
.static uint8_t keys[] = {
// Добавьте шестнадцатеричные байты ключа
};
Добавьте в конец этого массива размер секрета (количество только что внесённых шестнадцатеричных байтов):
static const uint8_t key_sizes[] = {
Добавьте ещё одну запись 30 в конец этого массива.
static const uint32_t timesteps[] = {
Добавьте метку для секрета. Например, если он относится к аккаунту Google, можете указать в качестве неё символы
{ 'g', 'o' }
.static const char labels[][2] = {
Вот и всё — наслаждайтесь всеми удобствами кодов TOTP на своём запястье!
▍ Написание собственного циферблата-счётчика
Весь код находится в этом пул-реквесте, который я отправил в основной проект.
Написать эту функциональность оказалось, на удивление, легко — практически вся реализация уместилась в одной основной функции.
bool ratemeter_face_loop(movement_event_t event,
movement_settings_t *settings,
void *context) {
(void) settings;
ratemeter_state_t *ratemeter_state = (ratemeter_state_t *)context;
char buf[14];
Эта функция обрабатывает все нужные вам события нажатий кнопок, а также каждый тик часов.
switch (event.event_type) {
При этом, если вас интересует измерение промежутков времени, обработка анимаций или нечто аналогичное, то циферблат может запрашивать частоту тактов.
В дереве
movement
присутствует вспомогательная функция watch_display_string
, которая как умеет старается отрисовывать буквенно-цифровую строку для различных элементов дисплея Casio, состоящих из 7 и более сегментов. При попытке вывести на эту ограниченную поверхность произвольные строки возникают всяческие проблемы, но всё это достаточно хорошо описано в документации.Итак, перечислю все состояния часов, которые нас интересуют.
При активации циферблата в индикаторе дней отображается RA.
case EVENT_ACTIVATE:
watch_display_string("ra ", 0);
break;
При нажатии MODE происходит переключение на следующий циферблат.
case EVENT_MODE_BUTTON_UP:
movement_move_to_next_face();
break;
При нажатии LIGHT включается подсветка.
case EVENT_LIGHT_BUTTON_DOWN:
movement_illuminate_led();
break;
А теперь самое важное… При нажатии ALARM:
- Обновляется вычисленная частота на основе промежутка между текущим нажатием кнопки и предыдущим.
- Сбрасывается счётчик тактов (часть специального состояния циферблата, который я написал).
- Сбрасывается частота быстрых тактов (эта константа определена как 1/16 секунды).
case EVENT_ALARM_BUTTON_DOWN:
if (ratemeter_state->ticks != 0) {
ratemeter_state->rate =
(int16_t)(60.0 /
((float)ratemeter_state->ticks /
(float)RATEMETER_FACE_FREQUENCY));
}
ratemeter_state->ticks = 0;
movement_request_tick_frequency(RATEMETER_FACE_FREQUENCY);
break;
И, наконец, при каждом тике… Обновляется дисплей, отображая текущую частоту или «Hi», если частота больше 500/минуту, либо «Lo», если она составляет 1/минуту. При этом также инкрементируется счётчик тактов.
case EVENT_TICK:
if (ratemeter_state->rate == 0) {
watch_display_string("ra ", 0);
} else {
if (ratemeter_state->rate > 500) {
watch_display_string("ra Hi", 0);
} else if (ratemeter_state->rate < 1) {
watch_display_string("ra Lo", 0);
} else {
sprintf(buf, "ra %-3d pn", ratemeter_state->rate);
watch_display_string(buf, 0);
}
}
ratemeter_state->ticks++;
break;
Вот и всё! Проект получился проще и интереснее, чем я ожидал.
Если вам понравился этот апгрейд, можете тоже заказать себе плату Sensor Watch с Oddly Specific Objects. Я с ними никак не аффилирован, просто считаю, что Джо реализовал действительно крутую идею.
Telegram-канал со скидками, розыгрышами призов и новостями IT ?
![](https://habrastorage.org/webt/tp/sk/z-/tpskz-7w7a8e74isoowuep40xeg.png)
Комментарии (10)
Dynasaur
09.08.2024 13:29+1видимо, если эту плату продавать в своих часах, это нафиг никому не нужно. А так, может, и найдутся гики раскурочить старые часы и вставить плату а потом думать - а нафига?
vagon333
09.08.2024 13:29Использую эту модель часов десятки лет: для походов на море самое то.
Наверное глупый вопрос, но зачем усложнять?
Если только не нужна какая-то секретность для хранения OTP генератора, почему для OTP не использовать smart watch?
nixtonixto
09.08.2024 13:29+2Цифровой подстройки точности хода так и не добавили. Наверное, никому из разработчиков не мешают вечно спешащие или отстающие часы. Датчик температуры, показывающий нечто среднее между температурой руки и температурой воздуха - есть, более нужный датчик давления (помогающий предсказать погоду на ближайшие часы) добавить не догадались... Сколько будильников, есть ли среди них недельные и месячные - для напоминания о еженедельных или ежемесячных событий?
Didimus
09.08.2024 13:29+1А если больше трёх-четырёх сервисов и некоторые редко используются, заколебешься переключать...
alcotel
09.08.2024 13:29+1Если у вас есть только QR-код, сайт Штефана Сандина позволит извлечь его секрет ...
Для добавления полученного секрета в код циферблата нужно преобразовать его в шестнадцатеричные байты. Сделать это можно на сайте cryptii.com...
"Это ты, Чебурашка, здорово придумал!" - пропускать свои секретики через пару левых сайтов. Не поверю, что на том же питоне нет либ, работающих локально.
vvzvlad
09.08.2024 13:29А кому нужен ваш секрет непонятно от какого именно сервиса и логина? Это же как пин-код от банковской карты ввести.
xSVPx
09.08.2024 13:29Ну т.е. любой нашедший ваши часы....
Нет, так безопасность не увеличивается...
Наверное, можно допилить до состояния "введите пин", но как-то я сомневаюсь, что это год проработает. Тотр вообще-то требует еще и довольно точного времени...
SagePtr
09.08.2024 13:29Любой нашедший не знает ни логина-пароля владельца часов, ни какому сервису код принадлежит
hw_store
Во-первых, часы на картинке - левые (что не очень важно, т.к. плата от них не используется... но корпус может оказаться не водонепроницаемым)
Во-вторых, не понятно, как вот этот код туда заносить
В-третьих, автор почему-то не упоминает, каково время жизни системы от батарейки.
А так-то да, забавная штуковина.
encyclopedist
Не автор, но после посещения ссылок:
На плате micro-USB
Обещают год