Обратное проектирование инсулиновой помпы для самостоятельной терапии с замкнутым контуром

Примерно 3 года назад я услышал о веб-сайте, предлагающем вознаграждение за то, что было очень близко моему сердцу: обратный инжиниринг связи с инсулиновой помпой. Моя дочь уже использовала систему, которую я помог создать, под названием Loop, с помпой Medtronic, для которой я перепроектировал радиочастотную связь ». Но помпа Medtronic требовала от нее отключения во время гимнастики на несколько часов. Бескамерный дизайн этого насоса Omnipod звучал великолепно, и у меня были все инструменты, чтобы начать работать над проблемой.

Система Omnipod состоит из небольшого одноразового насоса, называемого контейнером, и блока управления, называемого PDM.

Поскольку PDM связывается с модулем по радио, а модуль не имеет встроенного интерфейса, это означает, что модуль полностью управляется по радио. Была возможность создать полную интеграцию с Loop, используя только RileyLink или его модифицированную версию.

Джеймс Веддинг назначил награду, и она привлекла много внимания и, в конечном итоге, нужных людей, которые потребуются для достижения прогресса.

Программно-определяемое радио

SDR - это потрясающие инструменты; они делают видимым скрытый мир радио. Есть все виды сообщений, которые все время архивируются, и эти инструменты позволяют вам копаться, просматривать сообщения и, немного поработав, начать расшифровывать маленькие всплески, которые вы там видите. Если вы ищете сообщения с определенного устройства, вам необходимо знать, в какой области следует начинать поиск. Вот где вам пригодятся общедоступные документы Федеральной комиссии по связи.

В документации FCC для PDM RBV-019 указано, что устройство передает в диапазоне 433 МГц. Конфигурация программного обеспечения SDR для прослушивания в диапазоне 433 МГц при выдаче статуса из PDM показывает следующие сообщения:

Как я в конце концов узнал, эти две яркие линии указывают на определенный тип модуляции, называемый частотной манипуляцией или FSK. Это означает, что частота сигнала зависит от передаваемой информации. Бит 1 отправляется с более высокой частотой (верхняя строка), а бит 0 отправляется с немного более низкой частотой (нижняя строка). А с помощью инструмента inspectrum мы можем проанализировать данные, чтобы более четко отображать единицы и нули. Вот увеличенное изображение первого сообщения выше:

В итоге я написал сценарий Python для извлечения этих битов, чтобы мы могли рассматривать их как единый пакет.

Оказывается, этот повторяющийся узор был частью преамбулы. Для экономии энергии приемники часто спят и периодически просыпаются, чтобы проверить наличие сигнала. Передатчик отправляет преамбулу, достаточно длинную, чтобы поймать приемник в течение одного из коротких периодов прослушивания. Когда получатель слышит преамбулу, он не спит, пока не появятся реальные данные.

Нам пришлось пройти еще один уровень, прежде чем мы начали рассматривать фактические пакетные данные. Вы не можете отправлять данные по радио в точности как исходные биты, потому что получатель использует переходы для синхронизации во времени, когда ожидать следующего бита. Если у вас длинный набор единиц или нулей, приемник может рассинхронизироваться. Поэтому радиосвязь обычно использует кодировку, чтобы обеспечить достаточное количество переходов. Коммуникации Omnipod используют кодировку, называемую манчестерское кодирование. Каждый бит кодируется двумя битами. Бит 1 кодируется как 10, а бит 0 кодируется как 01.

Все это потребовало много хеширования, и в openomni slack было высказано множество теорий, поскольку мы пытались сделать получение сырых битов повторяемыми. Марк Брайтон, Дэн Кэрон и @larsonlr добились определенных успехов с использованием RFCat и TI Stick для захвата пакетов. Evariste Courjaud в конечном итоге напишет инструмент под названием rtlomni, использующий карту rtl-sdr для прослушивания пакетов и их декодирования, что окажется очень удобным и более надежным, чем методы на основе TI-Stick.

Пакеты декодирования

Получив фактические биты пакета, мы начали изучать структуру пакета. Основываясь на том, какие биты менялись между разными модулями и разными командами, мы пришли к следующему выводу.

CRC8

Радио - далеко не идеальная среда передачи. Существует множество различных источников помех, из-за которых приемник может слышать 1, когда был отправлен 0, и наоборот. Важно знать, когда это произошло, поэтому в большинстве протоколов используется своего рода контрольная сумма, часто называемая CRC. Приемник вычисляет CRC при получении данных, а последний байт пакета включает CRC, вычисленный передатчиком. Если они не совпадают, получатель выбрасывает пакет и ждет повторной передачи.

В протоколе Omnipod использовалась стандартная 8-битная CRC, поэтому, когда мы это обнаружили, мы подумали, что действительно близки к тому, чтобы разобраться с сообщениями. Мало ли мы знали ...

Сообщения, CRC16

Некоторые сообщения слишком велики, чтобы поместиться в один пакет, поэтому они отправляются как несколько пакетов. Мы начали составлять формат сообщений и заметили еще один набор битов в конце каждого сообщения, который выглядел как 16-битная CRC. Но это было странно; 5 из 16 бит никогда не устанавливались. Мы пробовали много разных техник, чтобы выяснить, как это настраивается, но ничего не сработало.

Это был первый большой блокиратор; мы могли бы приступить к выяснению того, что были другие биты в сообщениях, но это мало поможет понять, что было отправлено, но мы не сможем сами генерировать новые пакеты, и поэтому прогресс замедлился.

Прошли месяцы с небольшим прогрессом, и, наконец, зимой 2016 года член группы с ником @lorelai сообщила, что она успешно сбросила прошивку с более крупного чипа на базе ARM на PDM и начала утомительный процесс разборки. : взять инструкции процессора и превратить их в понятный человеку код с семантическими переменными и именами функций. Она проделала потрясающую работу, выяснив, какие различные методы используются для передачи данных по радио.

Я смотрел на одну из безымянных подпрограмм и заметил, что она выглядела как стандартная реализация вычисления CRC на основе таблицы. И в таблице были значения для стандартной 16-битной CRC. Я написал свою собственную реализацию, используя таблицу, и она проверила ее как обычный CRC. Затем я внимательно посмотрел, как написана функция. Обычная реализация CRC выглядит так:

while (len--) {
  crc = (crc << 8) ^ crctable[((crc >> 8) ^ *c++)];
}

Они выглядели так:

while (len--) {
  crc = (crc >> 8) ^ crctable[((crc >> 8) ^ *c++)];
}

Найди отличие? То, что должно было быть оператором побитового сдвига влево, каким-то образом было закодировано как сдвиг вправо. Это ошибка; нет причин нарушать работу вашего собственного алгоритма CRC, поскольку он снижает вероятность обнаружения поврежденных сообщений.

Мы снова взялись за дело! Мы начали работу по декодированию сообщений, записи сеансов из PDM для введения болюсов, временных базальных доз, приостановок и т. Д.

Nonce

Все команды доставки инсулина имели 4-байтовый блок данных в начале сообщения, который выглядел так, как будто это могла быть какая-то форма криптографии. Опять же, мы пробовали много разных способов интерпретировать его и анализировать в контексте сообщений, в которых он был отправлен, но это не CRC (иногда мы видели те же 4 байта, даже если данные сообщения были разными. ). А иногда мы видели, как шаблон повторяется. Похоже, это была часть протокола, предназначенного для предотвращения повторного воспроизведения данных. У других протоколов были такие функции, которые назывались nonce.

Один из возможных путей, который мы рассмотрели, заключался в записи базы данных сообщений для воспроизведения заданных команд. Даже если адрес каждого модуля был другим, теперь, когда мы знали, как сгенерировать crc сообщения, мы могли взять копию команды, которую мы видели раньше, поместить новый адрес в сообщение и пересчитать crc. Вот только этот одноразовый номер мешал нам использовать эту стратегию. Для следующей команды доставки инсулина, независимо от того, какая команда была отправлена, модуль будет принимать только следующий одноразовый номер в последовательности, и мы не знали, как сгенерировать следующий одноразовый номер.

Но эй! Теперь у нас есть декомпилированная прошивка PDM, можно просто посмотреть! Итак, мы внимательно изучили прошивку PDM, отследили генерацию сообщений в коде и нашли, где должны быть эти четыре байта. Но вместо метода вычисления некоторого криптографического Nonce мы просто нашли четыре символа «INS.». WTF?!?! Хорошо, каким-то образом эта область сообщения должна обновляться позже в конвейере.

На ДПМ была еще одна микросхема, ближе к магнитоле. Это был тот же самый чип, который использовался в модулях, чип с идентификатором SC9S08ER48, который не был зарегистрирован в Интернете и, вероятно, был изготовлен специально для Инсулета. Может быть, нам удастся получить прошивку от этого чипа. К сожалению, эта микросхема была заблокирована, что предотвратило сброс прошивки.

И снова прогресс замедлился… Это было похоже на настоящий тупик. Мы приложили все свои умения к этому безумию, и у нас не было никаких хороших выводов по математике, лежащей в основе этого. И ER48, который (возможно) хранил секреты, был заблокирован, и было трудно найти какие-либо публичные подробности, которые могли бы помочь нам раскрыть его.

Рентгеновские снимки

Пытаясь больше узнать об ER48, некоторые члены сообщества Slack предложили попробовать получить рентгеновские снимки, что было действительно круто, но, к сожалению, не открыло никаких новых возможностей.

Удаление колпачков и визуализация

Дэн Кэрон решил обратиться к исследователю Dr. Сергей Скоробогатов из Кембриджского университета в Великобритании, о котором он читал, у кого есть опыт извлечения кода из заблокированных чипов, и убедил его взглянуть на нашу проблему. Доктор Скоробогатов руководил исследованием использования SEM (сканирующей электронной микроскопии) для реверс-инжиниринга микросхем и предположил, что это возможно, но будет дорого, потребует доступа к дорогостоящему оборудованию и не гарантировано. Джо Моран, который недавно начал использовать Loop после того, как мы встретились на осеннем хакатоне Nightscout 2016, нырнул, чтобы помочь в этом проекте, и договорился с компанией Nanolab Technologies, занимающейся производством, для снятия колпачков и визуализации чипов. а также любезно профинансировал работу Nanolab и доктора Скоробогатова (а также его личные коробки с капсулами).

Доктор Скоробогатов поручил Nanolab выполнить различные методы визуализации, чтобы выяснить, можно ли победить защиту известными неинвазивными или полуинвазивными методами. В результате получилось много изображений, некоторые из них очень красивые. Это фотографии кремниевого кристалла, полученные с помощью оптического микроскопа.

Были также получены изображения определенных областей штампа с помощью сканирующей электронной микроскопии. Были предприняты попытки с разным напряжением, разной подготовкой поверхности и разным оборудованием.

К сожалению, ни одно из этих изображений не позволило разрешить реальное содержимое флэш-памяти.

У доктора Скоробогатова был последний метод, который можно было использовать только в том случае, если другие методы не помогли. Это был запатентованный метод, который должен был получить благословение, чтобы его использовал университет. Доктор Скоробогатов провел первоначальный тест и подтвердил, что он способен обрабатывать данные на этом чипе. Но прежде чем мы могли продолжить, необходимо было согласовать соглашение о неразглашении, и поэтому были предприняты переговоры о том, кто будет получателем извлеченной прошивки.

Фонд Nightscout в конечном итоге станет стороной, подписывающей NDA, и возьмет на себя ответственность за предотвращение несанкционированного раскрытия методов и результатов добычи.

Результатом такой договоренности и работы стала невероятная статья, написанная доктором Сергеем Скоробогатовым, и необработанные данные прошивки. Первоначальное извлечение прошивки содержало значительное количество ошибок, но этого было достаточно, чтобы начать работу. Джо спросил на весеннем мероприятии Nightscout Foundation Hack, готов ли кто-нибудь заняться разборкой. Никто не поднял руки. Превращение инструкций процессора в нечто понятное - это кропотливая работа, и очень мало людей умеют это делать. Я попытался покопаться в этом, используя документацию с инструкциями по процессору, но добился очень небольшого прогресса и разочаровался. Другие оптимистично попросили прошивку с большими ожиданиями быстрого прогресса, а затем осознали масштаб и сложность задачи и незаметно ушли.

Оказывается, у Джо также есть обширный опыт работы на уровне сборки, и он сам начал брать на себя обременительную задачу. В июле доктор Скоробогатов завершил вторую экстракцию с гораздо меньшим количеством ошибок. Все лето Джо Моран неустанно работал над составлением схемы огромного количества инструкций процессора и постепенным объединением их в более крупную картину псевдокода модуля.

В конце концов, Кен Ширрифф, эксперт в области реверс-инжиниринга аппаратного обеспечения, присоединился к усилиям и значительно ускорил процесс. Вместе Джо и Кен в конечном итоге наметили достаточно кода, чтобы найти функцию, отвечающую за кодирование одноразового номера сентября 2017 года.

RileyLink и петля

Мы обновляли сценарии python openomni с учетом нашего понимания коммуникаций, но теперь пришло время сосредоточиться на RileyLink + iOS, поэтому я начал работу над OmniKit и обновлениями прошивки для RileyLink. Я полагал, что у нас были разработаны основы протокола, а остальное - лишь детали. Опять же, совершенно недооценивая, сколько еще впереди нас.

Мне пришлось написать новую прошивку, которая бы обрабатывала модуляцию и кодирование стручка. Мне также пришлось переписать способ взаимодействия двух микросхем на RL друг с другом, чтобы обрабатывать нули, поскольку 0 был специальным маркером конца пакета для Medtronic. Многое в Loop нужно было переработать для поддержки нескольких насосов, а также создать новые интерфейсы для поддержки сопряжения, деактивации и обработки ошибок. К счастью, Нейт Раклифт заложил в Loop прочную основу для того, чтобы это произошло.

Между тем, работа по пониманию формата команд продолжалась и была тщательно задокументирована в openomni wiki, которая является наиболее полной документацией по протоколу pod, опубликованной публично. Джо, Эварист и Элке Ягер действительно проделали огромную работу по декодированию сообщений и обновлению страниц с течением времени. Различные участники slack-канала внесли перехваты PDM в сообщения Pod, чтобы помочь усилиям по декодированию.

Декодирование было увлекательной работой, с множеством небольших выигрышей, поскольку каждый компонент каждой команды был расшифрован, и мне очень понравилось работать над этой частью и добавлением кода в цикл для реализации. В апреле 2018 года я рассказал о Slack, что у меня было «сопряжение через iPhone + RL, грунтовка, введение канюли, запрограммированная схема базального введения, а затем болюсное введение 5U».

Прошивка 2.0 RL была завершена в июле 2018 года, и начались новые поставки, включая ее. Была надежда, что эти платы можно будет использовать с Loop и Omnipod, но существующая антенна на 915 МГц оказалась слишком плохой для эффективной связи на частоте 433 МГц.

Декодирование и реализация за лето прошли хорошо, и опыт Loop начал собираться. Джо сделал потрясающую вещь, предоставив мне финансирование, чтобы я бросил свою повседневную работу и больше сосредоточился на этом проекте, и в конечном итоге присоединился к замечательной команде Tidepool. Конечно, помимо истории omnipod RE в сфере DIY и регуляторов происходило больше событий, которые я не буду описывать, но это было очень интересное лето!

Крикуны

Когда в драйвере появилось больше функциональных возможностей, я начал подключать его к Loop, включая возможность автоматической регулировки доставки по временным базальным значениям. В этот момент довольно часто можно было получить кричащую капсулу, что означало, что некоторые из внутренних проверок капсулы обнаружили ситуацию, когда она решила, что существует проблема, и она не должна продолжать подавать инсулин.

Но это казалось работоспособной проблемой, поскольку мы продолжали находить небольшие несоответствия в том, что отправлял Loop, по сравнению с тем, что PDM отправлял бы, если бы команда была доставлена ​​вручную, и я предположил, что если мы исправим все из них, крики прекратятся.

Цикл!

3 октября 2018 года Джо надел на себя модуль, управляемый Loop, и стал первым пользователем Loop Omnipod, но не сказал мне сразу, так как знал, что я буду беспокоиться. Когда он сказал мне, я все еще волновался. Мы видели работу модуля и понимали его функциональность, а основной алгоритм Loop проверялся долгое время, но все же ...

Месяц спустя, на хакатоне Nightscout в ноябре 2018 года, еще несколько смельчаков решили попробовать это на себе и стали частью небольшой частной тестовой группы, которая вырастет до более чем 30 человек, прежде чем ветка станет общедоступной.

К сожалению, у нас все еще были скримеры, которые часто возникали до того, как закончились полные 3 дня использования, и мы тщательно сравнили команды Loop с эталонными версиями PDM. Элке был особенно полезен в этом процессе, создав сценарий, который мог автоматически проверять команды на соответствие их эталонным версиям. Я начал беспокоиться о том, что повышенные требования к батарее для связи каждые пять минут подтолкнули модуль к тому, что было устойчивым.

Итак, я начал измерять напряжение на капсуле с помощью Arduino, записывая данные и сохраняя их в локальной базе данных для визуализации. Сравнение PDM и Loop.

К сожалению, это тоже оказалось тупиком; с помощью PDM и большого количества болтов, я мог приводить капсулу к более низкому напряжению, чем даже Loop мог бы сделать за весь срок службы контейнера, и не мог заставить капсулу кричать. Похоже, проблема не в напряжении, значит, должно быть что-то еще.

В какой-то момент я заметил, что в случае сбоя обмена сообщениями с модулем модуль иногда оставался в состоянии попытки завершить обмен путем повторной отправки пакетов снова и снова. Журналы тестеров также показывали множество отказов, и поэтому я начал экспериментировать с антеннами. Обе эти проблемы следует решить улучшением связи. Я планировал попробовать разные антенны и заказал их из случайных мест в Интернете, но у меня не было времени попробовать их, пока это не стало приоритетной задачей.

У меня было несколько гибких антенн 433 МГц, которые можно было приклеить на внутренней стороне корпуса RL. В одних сценариях они часто дают отличную производительность, в других - нет; это было слишком ненадежно. Когда я подошел к катушке, она стабильно показывала хорошие характеристики и на очень удивительных диапазонах. Время для нового дела RileyLink.

С новой антенной и некоторыми оптимизациями для меньшего количества обменов сообщениями, при этом позволяя регулировку каждые 5 минут, частота крикунов снизилась до очень низкого уровня. Вероятно, сравнимо с обычным использованием модуля с PDM. За последние 7500 часов живого тестирования 94% модулей завершили работу без сбоев.

Тестирование и документация

Группа тестирования росла медленно, что было отличным способом постоянно получать новые взгляды на систему и видеть, какие части сбивают с толку. Эти тестировщики терпели множество кричащих модулей и внесли большой вклад в улучшение работы Loop с Omnipod. Они делали это в первую очередь, делясь отчетами о проблемах с каждого из своих модулей, независимо от того, были они успешными или нет.

В отчетах о проблемах есть журнал сообщений, который можно проанализировать с помощью инструмента, созданного Eelke, что дает нам представление о том, были ли у нас какие-либо искаженные команды, а также позволяет нам собирать статистику по определенным частям взаимодействия Loop с модулями.

Марион Баркер присоединилась к группе тестирования и добавила специальные отчеты и дополнительную статистику о ходе тестирования, и мы смогли использовать ее статистику успешных модулей и неудач, чтобы иметь представление о прогрессе на высоком уровне.

В конце концов Кэти ДиСимон присоединилась к группе тестирования и начала большую реструктуризацию loopdocs.org, чтобы предоставить документацию для использования Loop с несколькими устройствами. Ожидания по поводу версии Loop, которая работала с Omnipod, были невероятно высокими, и без хорошей документации мы были уверены, что нас снова и снова будут наводнять одни и те же вопросы.

Новые функции для Loop

Интеграция Omnipod потребовала переосмысления некоторых элементов интерфейса и добавления новых элементов управления. Модуль не сообщает о заряде батареи, и пользователь мало что может сделать с разрядом батареи, если он каким-то образом случится, поэтому отображение виджета уровня заряда батареи не имело смысла. Кроме того, без пользовательского интерфейса на помпе пользователь должен иметь возможность быстро отменить болюс. Значок резервуара был изображением резервуара Medtronic, поэтому мы хотели переосмыслить его. Благодарим Paul Forgione за разработку логотипа контейнера, который теперь показывает уровень в резервуаре.

Спасибо

Спасибо всем людям, которые помогают сделать этот долгий путь таким, чтобы мы могли поделиться этим с другими и реализовать цель, которую мы поставили перед собой давным-давно. Я знаю, что не всех охватил и все, что произошло. Это было бы невозможно в одном посте, и для меня, поскольку у меня есть только этот опыт. Трудно представить, сколько часов на это потрачено. Если бы вы могли сложить их все, я уверен, это было бы шокирующим. Не говоря уже о работе, которая была затрачена на создание самого Омнипода, который, как я полагаю, затмевает эти усилия. Так что спасибо * всем *. Кроме того, в противном случае многие из этих часов были бы проведены с семьями. Я очень ценю, что моя жена и дети понимают то, что я потратил на это время, и хочу их тоже поблагодарить.

Примечания

Я должен упомянуть Joakim Ornstedt, как одного из участников декодирования openomni, а также создателя того, что, вероятно, на самом деле является первой циклической интеграцией с omnipod. Он построил устройство, использующее оптическое распознавание символов (OCR) на PDM для получения данных от PDM, и подключило цифровые нажатия кнопок к PDM через другой микроконтроллер. Это сложно масштабируемый подход, но он очень умный и позволяет обойти многие проблемы, с которыми нам приходилось сталкиваться при разработке решения на основе RE. Я действительно восхищался им за то, что он это сделал, и за крошечную долю времени, необходимого для того, чтобы заставить его работать с Loop.

[1] Бен Уэст декодировал большую часть основного протокола связи для насосов Medtronic с помощью USB-накопителя Carelink. Я выяснил, что такое RF, и немного поработал над протоколом.

📝 Прочтите этот рассказ позже в Журнале.

👩‍💻 Просыпайтесь каждое воскресное утро и слушайте самые интересные истории недели в области технологий, которые ждут вас в вашем почтовом ящике. Прочтите информационный бюллетень« Примечательно в технологиях .