Разработка
Реверс инжиниринг кормушки для кошек для повышения производительности разработки
При каждом коммите кормушка для кошек выдает мне порцию конфет.
После ночных покупок в Amazon я получил PetKit FreshElement Solo. У меня было две проблемы, которые он мог решить: низкая мотивация к побочному проекту и слишком большая любовь к миндалю с морской солью в темном шоколаде от Target. Я помешан на коде — так почему бы не подкормить мой обезьяний мозг, когда я пушу код? Так и возник мой проект — при каждом коммите кормушка для кошек выдает мне порцию конфет.
Я не смог найти USB-раздатчик конфет (я даже проверил thinkgeek, ничего близкого!), поэтому я и решил попробовать кормушку для кошек. Эта штука потрясающая, и я покажу вам, как повторить то, что я сделал.
Тизер
- Код:
https://github.com/morganpartee/pyPetKit/blob/master/run.py - Чтобы запустить подобный проект у себя, вам нужно будет установить свое имя пользователя и пароль здесь:
https://github.com/morganpartee/pyPetKit/blob/master/settings.py
Обзор
REST API — это, по сути, язык Интернета. Большинство продуктов используют их для передачи данных с устройств на серверы. Я видел какой-то старый код Python, в котором уже был отработан процесс аутентификации, так что мне было с чего начать.
Я отследил API-запрос, который выполнял ручную подачу корма, воспроизвел его в Python с помощью Requests и привязал этот скрипт к кнопке на моей streamdeck, который также отправляет ctl + enter для отправки коммита.
Есть и другие (лучшие) способы сделать это — AWS, веб-хуки, git-хуки (вероятно, git-хуки — лучший выбор), но я хотел, чтобы это работало только локально, поэтому я не раздаю конфеты, пока меня нет в городе. Не нужно усложнять! В худшем случае я забуду нажать на кнопку и съем меньше конфет.
Аппаратное обеспечение
Я действительно не могу переоценить — эта штука идеально подходит для раздачи снеков. Еда порционируется с помощью этой аккуратной маленькой силиконовой шнековой системы с силиконовыми пальцами, которые ограничивают количество, которое может попасть в дозатор. Он умный и нежный с едой. И безопасный с точки зрения пищи.
А это просто мило:
Они положили таблицу размеров продуктов, в которой указано, что кусочки должны быть менее 12 мм:
Но он фильтрует и порционирует такие продукты так:
Так что если кусок будет хотя бы в одном измерении 12 мм, то все сработает нормально. В будущем я планирую протестировать кусочки вяленого мяса и сырные шарики. В крышке есть пакет с влагопоглотителем, чтобы продукты оставались свежими. Так что сходить с ума довольно безопасно, я полагаю.
На момент написания кормушка стоит около 70 долларов, но она отлично работает и хорошо собрана.
Приложение
Приложение довольно хорошее. Хотя немного странно, если у вас нет питомца… Мне пришлось добавить себя в качестве собаки и выбрать свою «породу»:
Но после этого я смог использовать API. Несколько раз протестировав размер порции с помощью приложения я определил, что 1/10 чашки — это половина ротора, что в среднем составляет около пяти миндалин.
Слежка
Я использовал Packet Capture для Android, пока выполнял ручную подачу:
И нашел этот запрос:
Настоящей серебряной пули здесь нет, пришлось просмотреть несколько групп запросов, чтобы найти нужный. Но мы видим, что он достигает конечной точки /latest/d4/saveDailyFeed, что дает нам большой намек! Раздел URLENCODED сообщает нам, что количество, время и идентификатор устройства включены в URL-адрес… Таким образом, мы можем реплицировать его локально!
Мы с Энди рассказали, как это сделать на десктопе здесь.
Программирование
Код доступен здесь.
Я начал с форка PyPetKit от geeks4hire. Там уже был разработан поток авторизации, мне просто нужно было добавить доступ к API. Я знал конечную точку, которую я получил из приведенного выше пакета, поэтому я добавил общую функцию для отправки запросов к API в мой форк пакета:
def send_api_request(self, path, method="POST", params=None, json=None): """ Sends an API request. """ custom_headers = { "X-Session": self._access_token, "User-Agent": "PETKIT/7.26.1 (iPhone; iOS 14.7.1; Scale/3.00)", "X-Timezone": f"{round(self._tzone._utcoffset.seconds/60/60)}.0", "X-Api-Version": "7.26.1", "X-Img-Version": "1", "X-TimezoneId": self._tzone.zone, "X-Client": "ios(14.7.1;iPhone13,4)", "X-Locale": self._locale.replace("-", "_"), } return requests.request( method, self._apiServerBaseURL + path, headers=custom_headers, params=params, json=json, ).json()
Это выглядит сложно, но заголовки были скопированы кем-то, кто делал то же самое, что и я, с iPhone. Он использует запросы (requests.request) для выполнения HTTP-запроса любым методом. Это именно то, что делает браузер, но с Python! Мы подробно рассказываем об этом в упомянутом выше докладе о парсинге — если вы можете скопировать заголовки, вы можете многое что сделать.
Тогда получить сладкий миндаль можно просто так:
from pypetkit import PetKitAPI from settings import ( API_USERNAME, API_PASSWORD, API_COUNTRY_CODE, API_LOCALE_CODE, API_TIMEZONE, ) from pprint import pprint petkit_api = PetKitAPI( API_USERNAME, API_PASSWORD, API_COUNTRY_CODE, API_LOCALE_CODE, API_TIMEZONE ) #! Sign in petkit_api.request_token() print(f"Authorized: {petkit_api.is_authorized}") #! Send the actual feeding request pprint( petkit_api.send_api_request( "d4/saveDailyFeed", params={"deviceId": 10019856, "amount": 10, "time": -1} ) )
Мы используем существующий поток аутентификации, а затем отправляем наш запрос. Параметры совпадают с запросом, который мы нашли при ручном кормлении из приложения. Я попробовал меньший размер порции, но 10, кажется, наименьшее количество, которое он может выдать. Параметр -1, кажется, заставляет его выдавать всю еду немедленно. Вы можете запланировать кормление в приложении, я уверен.
Если это сработает, вы увидите такой вывод run.py:
И короткий звуковой сигнал, сопровождаемый прекрасным звуком удара вознаграждения по вашей миске (не думайте об этом слишком много, это лишь слегка унизительно):
Деплой
Развертывание — это сильно сказано, но я бы назвал это именно так. Я управляю этим локально, поэтому я не раздаю еду, когда нахожусь вдали от дома. У меня есть любимая Elgato Stream Deck, которую я использую для горячих клавиш.
System:Hotkey отправляет Ctl+Enter для отправки коммита, когда я закончу писать сообщение. Клавиша System:Open открывает python c:/<path>/run.py, который дает мне сладкое шоколадное подкрепление за мои хорошие привычки в программировании.
Наверняка вы могли бы сделать это лучше, но нет необходимости в облачном хостинге или чем-то еще для глупого маленького проекта. Это просто часть удовольствия!
Вывод
Огромное спасибо всем, кто реверсинженерил это до меня. Оставалось только найти конечную точку и сделать запрос, что было слишком просто! Кто знает, станет ли это настоящим подспорьем в написании кода, но я не видел, чтобы кто-то делал это раньше, и я рад, что попробовал. Устранение неполадок в CI стало намного приятнее.
Примечание по безопасности
Вы увидите, что данные для этих продуктов отправляются в виде открытого текста на их серверы и в них… нет HTTPS. Это просто слишком поверхностно. Они также отправляют ваше полное местоположение, что еще более нелепо. Я бы старался избегать использования приложения настолько часто, насколько это возможно, и использовать одноразовый пароль на случай его взлома… Потому что это действительно может произойти в какой-то момент.
-
Интегрированные среды разработки2 недели назад
Лучшая работа с Android Studio: 5 советов
-
Новости4 недели назад
Видео и подкасты о мобильной разработке 2024.43
-
Новости3 недели назад
Видео и подкасты о мобильной разработке 2024.44
-
Исследования2 недели назад
Поможет ли новая архитектура React Native отобрать лидерство у Flutter в кроссплатформенной разработке?