- petkit_food_check.py: watchdog для state.food (алярм мало/пусто, сброс при доливе) - petkit_raw.py, petkit_roster.py: прямые запросы к API для отладки - .gitignore: исключить .food_state (runtime состояние)
76 lines
2.7 KiB
Python
76 lines
2.7 KiB
Python
#!/usr/bin/env python3
|
|
"""Прямой запрос к PetKit API — сырой вывод без обработки библиотекой."""
|
|
import asyncio, hashlib, json, os
|
|
|
|
from aiohttp import ClientSession
|
|
|
|
HERE = os.path.dirname(os.path.abspath(__file__))
|
|
|
|
|
|
def load_env():
|
|
p = os.path.join(HERE, ".env")
|
|
if os.path.exists(p):
|
|
for line in open(p):
|
|
line = line.strip()
|
|
if line and not line.startswith("#") and "=" in line:
|
|
k, _, v = line.partition("=")
|
|
os.environ.setdefault(k.strip(), v.strip().strip('"').strip("'"))
|
|
|
|
|
|
REGION_URL = "https://passport.petkt.com/6/account/regionservers"
|
|
USER_AGENT = "PETKIT/11.2.1 (iPhone; iOS 15.1; Scale/3.00)"
|
|
|
|
|
|
async def main():
|
|
load_env()
|
|
email = os.environ["PETKIT_EMAIL"]
|
|
password = os.environ["PETKIT_PASSWORD"]
|
|
region = os.environ.get("PETKIT_REGION", "Russian Federation")
|
|
|
|
hdr = {
|
|
"Accept": "*/*",
|
|
"Accept-Language": "en-US;q=1, it-US;q=0.9",
|
|
"Accept-Encoding": "gzip, deflate",
|
|
"Content-Type": "application/x-www-form-urlencoded",
|
|
"User-Agent": USER_AGENT,
|
|
"X-Client": "ios(15.1;iPhone14,3)",
|
|
}
|
|
|
|
async with ClientSession() as s:
|
|
# 1. список региональных серверов
|
|
r = await s.post(REGION_URL, headers=hdr, data={})
|
|
sl = (await r.json())["result"]["list"]
|
|
region_id = None
|
|
base_url = None
|
|
for reg in sl:
|
|
if reg["name"] == region:
|
|
region_id = reg["id"]
|
|
base_url = reg["gateway"]
|
|
print("=== REGION ===", region, "-> id", region_id, base_url)
|
|
|
|
login_url = f"{base_url}user/login"
|
|
data = {
|
|
"client": '{"deviceModel":"iPhone14,3","systemVersion":"15.1","appVersion":"11.2.1","lang":"en","timezone":"Asia/Yekaterinburg"}',
|
|
"encrypt": "1",
|
|
"oldVersion": "11.2.1",
|
|
"password": hashlib.md5(password.encode()).hexdigest(),
|
|
"region": str(region_id),
|
|
"username": email,
|
|
}
|
|
r = await s.post(login_url, headers=hdr, data=data)
|
|
login = await r.json()
|
|
print("=== LOGIN ===")
|
|
print(json.dumps(login, ensure_ascii=False, indent=2))
|
|
token = login["result"]["session"]["id"]
|
|
hdr["X-Session"] = token
|
|
|
|
# 2. список устройств (device roster) — сырой
|
|
roster_url = f"{base_url}discovery/device_roster_v2"
|
|
r = await s.post(roster_url, headers=hdr, data={})
|
|
roster = await r.json()
|
|
print("\n=== DEVICE ROSTER (сырой) ===")
|
|
print(json.dumps(roster, ensure_ascii=False, indent=2))
|
|
|
|
|
|
asyncio.run(main())
|