Я смеюсь над этой историей все выходные, так что не могу не поделиться. Засидевшись до поздней ночи на Amazon, я купил автокормушку для животных PetKit FreshElement Solo. У меня имелось две проблемы, с решением которых она могла мне помочь: во-первых, мне сложно было себя замотивировать на работу над побочным проектом, во-вторых, я всерьез подсел на миндаль в темном шоколаде с морской солью из Target. Раз уж я кодер-мартышка, так почему бы не подкормить внутреннюю мартышку, когда выдаю код?
Найти USB-механизм для раздачи сладостей мне не удалось (даже на thinkgeek заглянул – ничего похожего), поэтому я решил попробовать кошачью кормушку. Отличная вещь, а под катом я расскажу, какие шаги предпринять, чтобы получить такой же результат, как у меня.
Вот тизер. Код лежит здесь. Чтобы запустить самим, вам придется выбрать имя пользователя и пароль по этой ссылке.
REST API – это, по сути, язык, на котором говорит интернет. У большинства продуктов общение между устройством и сервером происходит посредством их. Мне попался старый фрагмент кода на Python, в котором уже была реализован процесс авторизации, так что было от чего оттолкнуться.
Я покопался в поисках API-запроса для кормления вручную, скопировал его на Python с помощью Requests и привязал скрипт к кнопке на своем контроллере для стриминга – она же отвечает за отправку коммита командой ctl+enter.
Есть и другие способы (причем получше) получить тот же результат – AWS, вебхуки, хуки в git (хуки в git – пожалуй, самый надежный вариант), но мне хотелось, чтобы система работала строго локально, чтобы конфеты не сыпались, если я уеду куда-нибудь. Нет смысла всё усложнять! В худшем случае забуду нажать на кнопку и съем меньше сладкого.
Говорю без преувеличений: для выдачи вкусностей ничего лучше этого устройства не найдешь. Порция еды отмеряется при помощи аккуратненького механизма с силиконовым стержнем и силиконовыми лопастями, отделяющими нужное количество, которое и выпадает в лоток выдачи. Ловко придумано и для продуктов безопасно – они не крошатся и не портятся.
А это просто трогательно:
Прилагается шкала для измерения частиц еды; говорится, что размер должен быть менее 12 миллиметров. Но измерение и высыпание происходит примерно так:
поэтому даже если там все 12 миллиметров, может нормально пройти под углом. Я планирую поэкспериментировать с кусочками вяленого мяса и сырными шариками. Там гигроскопическая прокладка сверху, чтобы всё оставалось свежим… думаю, можно изощряться со спокойной душой.
На момент написания статьи такие кормушки стоили 70 $ за штуку, но работают они отлично и сделаны на совесть. Купить можно здесь.
Приложение неплохое. Единственное, немного странно с ним работать, когда домашних животных у тебя нет… Пришлось назваться собакой и выбрать себе породу.
Зато после этого я смог воспользоваться API. После нескольких тестов приложения на предмет размера порции, я узнал, что половина оборота – это примерно десятая часть стакана, то есть в среднем пять конфет.
Для ручного запуска кормления я использовал Packet Capture для Android.
И нашел там вот такой запрос:
Палочки-выручалочки не обнаружилось, мне пришлось просмотреть несколько групп запросов, чтобы отыскать то, что требовалось. Но мы видим /latest/d4/saveDailyFeed в качестве конечной точки, а это существенная подсказка! Секция URLENCODED говорит нам, что amount, time и deviceId входят в URL… Значит, всё можно повторить локально! В этой статье мы с Энди описали, как это делается на десктопе.
Код можно найти здесь.
Я начал с ответвления PyPetKit авторства geeks4hire. Всё, что касается авторизации, там было уже сделано за меня, оставалось только добавить выход на API. Из упомянутого выше пакета я узнал, в какую конечную точку нужно метить, и добавил непримечательную функцию для отправки запросов к API в моё ответвление пакета:
Выглядит сложно, но все заголовки скопированы у человека, который делал всё ровно то же самое, но на айфоне. Здесь используются запросы (requests.request) для создания HTTP-запроса произвольным методом. То есть то самое, что делает браузер, только на Python. В той статье про скрейпинг, о которой говорилось выше, мы разбираем это подробно – если есть возможность скопировать заголовки, это многое дает!
И вот, чтобы добраться до вожделенных конфет, только и нужно, что:
Мы задействовали реализацию авторизации из существующего кода и теперь посылаем запрос. Параметры соответствуют запросу, который мы обнаружили, когда вручную активировали кормушку из приложения. Я, конечно, попытался уменьшить размер порции, но, похоже, десять единиц – минимальное количество, которое может отмерить механизм. -1, кажется, запускает немедленную выдачу еды. В приложении можно задавать часы кормления, уверен, что и даты тоже.
Если всё работает как надо, выдача с run.py будет такой:
Затем негромкий писк и восхитительный звук конфет, падающих в (не заморачивайтесь, не так уж это и унизительно) миску.
Развертывание – это, конечно, сильно сказано, но иначе не назовешь. Система работает локально, чтобы еда не поступала, когда меня нет дома. У меня есть Elgato Stream Deck, который я очень люблю, и с его помощью я создал горячую клавишу.
System:Hotkey отправляет Ctl+Enter, чтобы отослать коммит, когда я допишу. System:Open открывает python c://run.py и тем самым обеспечивает мне сладкое шоколадное подкрепление правильных программистских привычек.
Всё это абсолютно точно можно реализовать «лучше», но в облаках и всяком таком просто нет необходимости – это маленький проект чисто для смеха.
Огромное спасибо тем, кто провел обратную разработку в отношении этого агрегата до меня. Мне только и осталось, что найти конечную точку и создать запрос – проще простого. Не знаю, подстегнет ли это меня в самом деле писать больше кода, но у других я такого еще не видел и рад, что предпринял эту попытку. Она определенно подсластила мне решение проблем с непрерывной интеграцией.
Как вы увидите, данные у этих продуктов отправляются простым текстом, что на сервер, что с сервера. Это очень сомнительно. Также они отправляют все сведения о местонахождении, что еще более сомнительно. Я бы посоветовал пользоваться этим приложением по минимуму и установить одноразовый пароль, на случай если произойдет утечка данных… а это рано или поздно вполне может случиться.
PETKIT Fresh Element Solo
Репозиторий на Github
Packet Capture для Android
Elgato Stream Deck
Миндаль в темном шоколаде с морской солью на Target (серьезно, он обалденный)
Найти USB-механизм для раздачи сладостей мне не удалось (даже на thinkgeek заглянул – ничего похожего), поэтому я решил попробовать кошачью кормушку. Отличная вещь, а под катом я расскажу, какие шаги предпринять, чтобы получить такой же результат, как у меня.
Вот тизер. Код лежит здесь. Чтобы запустить самим, вам придется выбрать имя пользователя и пароль по этой ссылке.
Обзор
REST API – это, по сути, язык, на котором говорит интернет. У большинства продуктов общение между устройством и сервером происходит посредством их. Мне попался старый фрагмент кода на Python, в котором уже была реализован процесс авторизации, так что было от чего оттолкнуться.
Я покопался в поисках API-запроса для кормления вручную, скопировал его на Python с помощью Requests и привязал скрипт к кнопке на своем контроллере для стриминга – она же отвечает за отправку коммита командой ctl+enter.
Есть и другие способы (причем получше) получить тот же результат – AWS, вебхуки, хуки в git (хуки в git – пожалуй, самый надежный вариант), но мне хотелось, чтобы система работала строго локально, чтобы конфеты не сыпались, если я уеду куда-нибудь. Нет смысла всё усложнять! В худшем случае забуду нажать на кнопку и съем меньше сладкого.
Аппаратное обеспечение
Говорю без преувеличений: для выдачи вкусностей ничего лучше этого устройства не найдешь. Порция еды отмеряется при помощи аккуратненького механизма с силиконовым стержнем и силиконовыми лопастями, отделяющими нужное количество, которое и выпадает в лоток выдачи. Ловко придумано и для продуктов безопасно – они не крошатся и не портятся.
А это просто трогательно:
Прилагается шкала для измерения частиц еды; говорится, что размер должен быть менее 12 миллиметров. Но измерение и высыпание происходит примерно так:
поэтому даже если там все 12 миллиметров, может нормально пройти под углом. Я планирую поэкспериментировать с кусочками вяленого мяса и сырными шариками. Там гигроскопическая прокладка сверху, чтобы всё оставалось свежим… думаю, можно изощряться со спокойной душой.
На момент написания статьи такие кормушки стоили 70 $ за штуку, но работают они отлично и сделаны на совесть. Купить можно здесь.
Приложение
Приложение неплохое. Единственное, немного странно с ним работать, когда домашних животных у тебя нет… Пришлось назваться собакой и выбрать себе породу.
Зато после этого я смог воспользоваться API. После нескольких тестов приложения на предмет размера порции, я узнал, что половина оборота – это примерно десятая часть стакана, то есть в среднем пять конфет.
Изыскания
Для ручного запуска кормления я использовал Packet Capture для Android.
И нашел там вот такой запрос:
Палочки-выручалочки не обнаружилось, мне пришлось просмотреть несколько групп запросов, чтобы отыскать то, что требовалось. Но мы видим /latest/d4/saveDailyFeed в качестве конечной точки, а это существенная подсказка! Секция URLENCODED говорит нам, что amount, time и deviceId входят в 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()
Выглядит сложно, но все заголовки скопированы у человека, который делал всё ровно то же самое, но на айфоне. Здесь используются запросы (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}
)
)
Мы задействовали реализацию авторизации из существующего кода и теперь посылаем запрос. Параметры соответствуют запросу, который мы обнаружили, когда вручную активировали кормушку из приложения. Я, конечно, попытался уменьшить размер порции, но, похоже, десять единиц – минимальное количество, которое может отмерить механизм. -1, кажется, запускает немедленную выдачу еды. В приложении можно задавать часы кормления, уверен, что и даты тоже.
Если всё работает как надо, выдача с run.py будет такой:
Затем негромкий писк и восхитительный звук конфет, падающих в (не заморачивайтесь, не так уж это и унизительно) миску.
«Развертывание»
Развертывание – это, конечно, сильно сказано, но иначе не назовешь. Система работает локально, чтобы еда не поступала, когда меня нет дома. У меня есть Elgato Stream Deck, который я очень люблю, и с его помощью я создал горячую клавишу.
System:Hotkey отправляет Ctl+Enter, чтобы отослать коммит, когда я допишу. System:Open открывает python c://run.py и тем самым обеспечивает мне сладкое шоколадное подкрепление правильных программистских привычек.
Всё это абсолютно точно можно реализовать «лучше», но в облаках и всяком таком просто нет необходимости – это маленький проект чисто для смеха.
В заключение
Огромное спасибо тем, кто провел обратную разработку в отношении этого агрегата до меня. Мне только и осталось, что найти конечную точку и создать запрос – проще простого. Не знаю, подстегнет ли это меня в самом деле писать больше кода, но у других я такого еще не видел и рад, что предпринял эту попытку. Она определенно подсластила мне решение проблем с непрерывной интеграцией.
Примечание о безопасности
Как вы увидите, данные у этих продуктов отправляются простым текстом, что на сервер, что с сервера. Это очень сомнительно. Также они отправляют все сведения о местонахождении, что еще более сомнительно. Я бы посоветовал пользоваться этим приложением по минимуму и установить одноразовый пароль, на случай если произойдет утечка данных… а это рано или поздно вполне может случиться.
Ссылки
PETKIT Fresh Element Solo
Репозиторий на Github
Packet Capture для Android
Elgato Stream Deck
Миндаль в темном шоколаде с морской солью на Target (серьезно, он обалденный)