Własne skrypty
Wbudowane skrypty obejmują typowe przepływy. Gdy potrzebujesz czegoś, czego nie oferują — kroku w innej kolejności, ekranu, którego nigdy nie dotykają, albo aplikacji innej niż TikTok czy Instagram — możesz napisać to sam w dowolnym języku, a TikMatrix odda ci telefon.
Wymagania
Własne skrypty wymagają planu Pro, Team lub Business. Plan Starter nie ma dostępu.
Liczba urządzeń w twoim planie jest zarazem limitem równoległości: plan Pro (20 urządzeń) może sterować 20 telefonami naraz — przez zadania wbudowane, własne skrypty albo jedno i drugie.
Dwa sposoby uruchamiania skryptu
Samodzielny
Program uruchamiasz sam. TikMatrix tylko wypożycza ci urządzenia.
from tikmatrix import TikMatrix
client = TikMatrix()
for device in client.devices():
if device["busy"]:
continue
with client.device(device["serial"], label="my crawler") as d:
d.press("home")
print(d.info())
Dobre do zadań jednorazowych, zbierania danych i wszystkiego, co chcesz odpalać z własnego harmonogramu.
Zarządzany
Rejestrujesz program w TikMatrix i staje się on zadaniem jak każde inne. Dostaje kolejkę zadań, równoległość zgodną z planem, automatyczne ponowienia, dziennik zadań i szablony harmonogramów. TikMatrix dzierżawi urządzenie przed uruchomieniem twojego programu i przekazuje identyfikator dzierżawy w środowisku.
from tikmatrix import TikMatrix
with TikMatrix.from_env() as d: # urządzenie jest już wydzierżawione
d.click(text="Log in")
print("done") # ta linia trafi do dziennika zadania
Dobre do wszystkiego, co chcesz uruchamiać wielokrotnie, o wyznaczonej porze albo na wielu urządzeniach.
Co wybrać
| Samodzielny | Zarządzany | |
|---|---|---|
| Kto uruchamia | Ty | Kolejka zadań TikMatrix |
| Dzierżawa urządzenia | Bierzesz ją sam | Jest już utrzymywana przy starcie |
| Ponowienia, harmonogram, dziennik | Budujesz sam | W komplecie |
| Praca na wielu urządzeniach | Sam piszesz pętlę | Jedno zadanie na urządzenie, równolegle |
| Najlepsze do | Eksploracji, crawlerów, zadań jednorazowych | Wszystkiego, co chcesz powtarzać |
Możesz zacząć od trybu samodzielnego, dopracować przepływ, a potem zarejestrować ten sam plik jako skrypt zarządzany — zmienia się tylko linia TikMatrix.from_env().
Pierwsze kroki
1. Zainstaluj bibliotekę kliencką
pip install requests
Następnie skopiuj tikmatrix.py z katalogu SDK obok swojego skryptu. Biblioteka to jeden plik bez innych zależności.
Nie musisz jej używać — API to zwykły JSON po HTTP, a surowe endpointy opisano niżej.
2. Napisz skrypt
from tikmatrix import TikMatrix
client = TikMatrix()
with client.device("192.168.1.5:5555") as d:
d.press("home")
d.adb("shell", "am", "start", "-a", "android.settings.SETTINGS")
d.wait_for(text="Settings", timeout=15)
d.screenshot("settings.png")
Uruchom go przy otwartym TikMatrix i podłączonym telefonie. Jeśli wypisze słownik z informacjami o urządzeniu, wszystko jest połączone poprawnie.
3. Zarejestruj go (tylko tryb zarządzany)
Przejdź do Urządzenia → Własne skrypty → Dodaj skrypt:
| Pole | Znaczenie |
|---|---|
| Nazwa | Widoczna na liście skryptów i w dzienniku zadań |
| Polecenie | Wiersz uruchamiający program, np. python C:/scripts/my_flow.py |
| Katalog roboczy | Opcjonalny. Miejsce startu programu |
| Platforma | Zobacz tryby platformy niżej |
| Limit czasu | Po ilu sekundach skrypt zostaje zabity, a zadanie oznaczone jako nieudane. Domyślnie 1800 |
| Dodatkowe zmienne środowiskowe | Opcjonalny obiekt JSON scalany ze środowiskiem programu |
| Włączony | Wyłącz skrypt bez usuwania. Wyłączony skrypt nie może zostać rozdysponowany |
Potem naciśnij ▶ w wierszu skryptu i wybierz urządzenia — dokładnie jak przy skrypcie wbudowanym.
Asystent AI potrafi napisać własny skrypt na podstawie opisu zwykłym językiem i zarejestrować go w jednym kroku. Pokazuje cały plik, zanim cokolwiek zostanie zapisane na dysku.
Dzierżawy urządzeń
Telefonem może w danej chwili sterować tylko jedna rzecz. Wydzierżawienie go mówi TikMatrixowi, że urządzenie jest zajęte, więc:
- kolejka zadań nie wyśle zadania na ten sam ekran, a
- twoje wywołania JSON-RPC raportują kondycję agenta dokładnie tak, jak robi to skrypt wbudowany, więc watchdog widzi agenta zajętego, a nie milczącego.
Dzierżawa zajmuje też jedno miejsce urządzenia w twoim planie.
Dzierżawy wygasają — domyślnie po 120 sekundach, maksymalnie po 600. Biblioteka Pythona odnawia twoją w wątku w tle i zwalnia ją po wyjściu z bloku with, więc skrypt, który padnie, oddaje urządzenie w kilka sekund zamiast trzymać je do restartu aplikacji. Jeśli wołasz API bezpośrednio, musisz sam wysyłać sygnały życia.
Wszystkie żywe dzierżawy zobaczysz — i wymusisz ich zwolnienie — w Ustawienia → Developer API → Aktywne sesje urządzeń.
Tryby platformy
Zarejestrowany skrypt deklaruje swój cel:
Generic — urządzenie zostaje przekazane nietknięte. Żadna aplikacja nie jest uruchamiana, konta nie są przełączane, metoda wprowadzania nie jest sprawdzana, a po zakończeniu nic nie jest zamykane. Użyj tego do automatyzacji wszystkiego, co nie jest TikTokiem ani Instagramem.
TikTok / Instagram — aplikacja zostaje otwarta, a konto przełączone przed startem twojego programu; po zakończeniu aplikacja jest zamykana, dokładnie jak przy skrypcie wbudowanym. TIKMATRIX_PACKAGE mówi, który pakiet został ustalony. Użyj tego, by dodać krok, którego nie obejmują skrypty wbudowane.
Zmienne środowiskowe
Zarządzany skrypt otrzymuje:
| Zmienna | Znaczenie |
|---|---|
TIKMATRIX_API_BASE | URL serwera, np. http://127.0.0.1:50809 |
TIKMATRIX_SESSION_ID | Dzierżawa już utrzymywana w twoim imieniu |
TIKMATRIX_SERIAL | Urządzenie, na które trafiło to zadanie |
TIKMATRIX_PACKAGE | Ustalony pakiet aplikacji |
TIKMATRIX_PLATFORM | tiktok, instagram lub generic |
TikMatrix.from_env() odczytuje to wszystko za ciebie.
Skrypty samodzielne nie dostają żadnej z nich — wydzierżaw urządzenie jawnie.
Wszystko, co wpiszesz w Dodatkowe zmienne środowiskowe, jest scalane na wierzchu. To zwyczajowy sposób, by przekazać jednemu zarejestrowanemu skryptowi ustawienia dla konkretnego uruchomienia bez edytowania pliku.
Dokumentacja biblioteki Pythona
TikMatrix — połączenie
| Wywołanie | Co robi |
|---|---|
TikMatrix(base_url=None, timeout=30.0) | Łączy się. Sięga po TIKMATRIX_API_BASE, potem http://127.0.0.1:50809 |
client.devices() | Urządzenia online, każde z serial, real_serial i busy |
client.sessions() | Wszystkie żywe dzierżawy, także cudze |
client.device(serial, label=..., ttl_secs=120) | Dzierżawi urządzenie i zwraca Device |
TikMatrix.from_env() | Przejmuje urządzenie, z którym wystartował zarządzany skrypt |
Device — telefon
| Wywołanie | Co robi |
|---|---|
d.info() | Informacje o urządzeniu z UIAutomator2 |
d.window_size() | (szerokość, wysokość) |
d.screenshot(path=None) | Bajty PNG, opcjonalnie zapisane do path |
d.hierarchy() | Bieżące drzewo interfejsu jako XML |
d.find(text=, resource_id=, description=, class_name=) | Pasujące węzły, każdy z bounds i center |
d.exists(**criteria) | Czy cokolwiek pasuje |
d.wait_for(timeout=10.0, interval=1.0, **criteria) | Czeka, aż się pojawi, i zwraca element |
d.click(timeout=10.0, **criteria) | Czeka na element i stuka w jego środek |
d.click_xy(x, y) | Stuka we współrzędne |
d.swipe(sx, sy, ex, ey, steps=20) | Przesuwa palcem |
d.press(key) | back, home, recent, enter, … |
d.input_text(text) | Pisze w aktywnym polu przez dołączoną szybką metodę wprowadzania |
d.jsonrpc(method, params=None, timeout=10) | Dowolna metoda UIAutomator2 |
d.adb(*args, timeout_ms=None) | Wykonuje polecenie ADB |
d.release() | Zwalnia dzierżawę. with robi to za ciebie |
find dopasowuje na zrzuconym drzewie interfejsu, więc gdy selektor spudłuje, możesz wywołać print(d.hierarchy()) i zobaczyć dokładnie, w czym szukał. Inspektor elementów w widoku urządzenia pokazuje to samo drzewo wizualnie — zwykle to najszybszy sposób na znalezienie resource-id.
input_text wymaga ADBWysyła broadcast do dołączonej metody wprowadzania, co idzie przez adb shell. Włącz dostęp ADB przed użyciem, inaczej dostaniesz 403.
Błędy
Biblioteka zgłasza dwa wyjątki, oba dziedziczące po RuntimeError:
| Wyjątek | Kiedy |
|---|---|
DeviceBusyError | HTTP 409 — urządzenie jest już wydzierżawione albo w planie nie ma wolnego miejsca |
TikMatrixError | Cała reszta: za niski plan, wygasła dzierżawa, wyłączony ADB, selektor, który nigdy nie trafił |
from tikmatrix import TikMatrix, TikMatrixError, DeviceBusyError
client = TikMatrix()
try:
with client.device("192.168.1.5:5555") as d:
d.click(text="Log in", timeout=20)
except DeviceBusyError:
print("ten telefon ma ktoś inny — spróbuj innego")
except TikMatrixError as exc:
print("niepowodzenie:", exc)
W zarządzanym skrypcie zwykle właściwe jest pozwolić wyjątkowi wylecieć: niezerowy kod wyjścia oznacza zadanie jako nieudane, a ślad stosu trafia do dziennika zadania.
Endpointy HTTP
Operacje na urządzeniu wymagają nagłówka x-session-id wskazującego żywą dzierżawę. Nie ma klucza API: tak jak reszta lokalnego API, te endpointy nie są uwierzytelniane — kontrolą dostępu jest sama możliwość dotarcia do maszyny w sieci. Nie wysyłają nagłówków CORS, więc wołaj je z programu (curl, Python, dowolny kod serwerowy), a nie ze strony w przeglądarce.
| Metoda | Ścieżka | Cel |
|---|---|---|
GET | /api/v1/rpc/devices | Lista urządzeń online i informacja, czy są zajęte |
POST | /api/v1/rpc/session | Dzierżawi urządzenie → session_id |
POST | /api/v1/rpc/session/{id}/heartbeat | Przedłuża dzierżawę |
DELETE | /api/v1/rpc/session/{id} | Zwalnia dzierżawę |
GET | /api/v1/rpc/session | Lista żywych dzierżaw |
POST | /api/v1/rpc/jsonrpc | Wywołuje metodę UIAutomator2 |
POST | /api/v1/rpc/adb | Wykonuje polecenie ADB |
GET | /api/v1/rpc/hierarchy?serial= | Bieżące drzewo interfejsu jako XML |
GET | /api/v1/rpc/screenshot?serial= | Bieżący ekran jako PNG |
Odpowiedzi JSON używają tej samej koperty co reszta lokalnego API — {"code": 0, "message": "success", "data": ...}, z niezerowym code przy niepowodzeniu. hierarchy i screenshot zwracają surową treść.
Przykład
# Wydzierżaw urządzenie
curl -X POST http://127.0.0.1:50809/api/v1/rpc/session \
-H "Content-Type: application/json" \
-d '{"serial":"192.168.1.5:5555","label":"curl test","ttl_secs":120}'
# {"code":0,"message":"success","data":{"session_id":"ff3ae079-...","serial":"192.168.1.5:5555", ...}}
# Steruj nim
curl -X POST http://127.0.0.1:50809/api/v1/rpc/jsonrpc \
-H "x-session-id: ff3ae079-..." \
-H "Content-Type: application/json" \
-d '{"serial":"192.168.1.5:5555","method":"deviceInfo","params":[]}'
# Utrzymuj dzierżawę przy życiu w trakcie pracy
curl -X POST http://127.0.0.1:50809/api/v1/rpc/session/ff3ae079-.../heartbeat \
-H "Content-Type: application/json" \
-d '{"ttl_secs":120}'
# Oddaj urządzenie
curl -X DELETE http://127.0.0.1:50809/api/v1/rpc/session/ff3ae079-...
Błędy
| Status | Znaczenie |
|---|---|
| 403 | Plan niższy niż Pro, brak dzierżawy, wygasła dzierżawa albo wyłączony dostęp ADB |
| 409 | Urządzenie już wydzierżawione albo w planie nie ma wolnego miejsca |
Pisanie w innym języku
Nic tutaj nie jest związane z Pythonem. Wystarczy dowolne środowisko potrafiące wysłać żądanie HTTP — kontrakt trybu zarządzanego brzmi tylko: „odczytaj trzy zmienne środowiskowe, zakończ z kodem 0 przy powodzeniu".
// my_flow.js — zarejestruj poleceniem: node C:/scripts/my_flow.js
const base = process.env.TIKMATRIX_API_BASE || "http://127.0.0.1:50809";
const serial = process.env.TIKMATRIX_SERIAL;
const session = process.env.TIKMATRIX_SESSION_ID;
async function jsonrpc(method, params = []) {
const res = await fetch(`${base}/api/v1/rpc/jsonrpc`, {
method: "POST",
headers: { "content-type": "application/json", "x-session-id": session },
body: JSON.stringify({ serial, method, params }),
});
const body = await res.json();
if (!res.ok || body.code !== 0) throw new Error(body.message || res.statusText);
return body.data;
}
console.log(await jsonrpc("deviceInfo"));
Jeśli interpretera nie ma w PATH, podaj pełną ścieżkę w polu Polecenie, np. C:/Program Files/nodejs/node.exe C:/scripts/my_flow.js.
Uruchamianie własnego skryptu przez API
Zarejestrowane skrypty można też uruchamiać przez API zarządzania zadaniami, dzięki czemu jeden skrypt może kolejkować dalszą pracę:
curl -X POST http://127.0.0.1:50809/api/v1/task \
-H "Content-Type: application/json" \
-d '{
"serials": ["192.168.1.5:5555"],
"script_name": "custom_script",
"script_config": {
"custom_script_id": 1,
"custom_script_platform": "generic"
}
}'
custom_script_id to identyfikator zarejestrowanego przez ciebie skryptu.
Dostęp ADB
/api/v1/rpc/adb daje twoim skryptom powłokę na urządzeniu — potrzebujesz jej do wgrywania mediów, instalowania APK i zmiany ustawień systemowych. Ponieważ to pełna powłoka na endpointcie bez klucza API, jest domyślnie wyłączona. Włącz ją w Ustawienia → Developer API → Zezwól na polecenia ADB, gdy masz skrypt, który jej potrzebuje; automatyzacja interfejsu przez /rpc/jsonrpc działa i bez niej.
Kiedy jest wyłączona, /api/v1/rpc/adb odpowiada 403, a reszta API działa normalnie. Każde polecenie ADB uruchomione przez skrypt trafia do twojego pliku dziennika.
Jak pisać skrypty, które nadal działają
- Czekaj na ekran, nie usypiaj za niego.
d.wait_for(...)wraca, gdy tylko element się pojawi; stały sleep jest albo wolniejszy niż trzeba, albo za krótki w gorszy dzień. - Sprawdź, zanim stukniesz.
d.exists(...)na oknie zgody albo komunikacie „nie teraz" kosztuje jeden zrzut drzewa i ratuje przebieg, który inaczej stuknąłby w pustkę. - Wypisuj, co zrobiłeś. W trybie zarządzanym stdout jest dziennikiem zadania i jedynym śladem przebiegu, którego nikt nie oglądał.
- Zadbaj o bezpieczne powtórzenie. Ponowienie uruchamia cały program od nowa, więc skrypt publikujący powinien sprawdzić, czy już opublikował, zamiast zakładać, że startuje od zera.
- Jeden skrypt, jedno zadanie. Równoległość liczy się na urządzenie, więc dziesięć małych zadań na dziesięciu telefonach kończy się znacznie szybciej niż jeden skrypt przechodzący pętlą po dziesięciu telefonach.
Uwagi i ograniczenia
- Polecenie jest wykonywane bezpośrednio, nie przez powłokę, więc
&&i|są traktowane jako argumenty, a nie operatory. Zarejestrujcmd /c "..."(Windows) lubsh -c "..."(macOS), jeśli chcesz zachowania powłoki. - Ścieżki ze spacjami ujmuj w cudzysłowy:
"C:/Program Files/Python/python.exe" my_script.py. - Skrypt przekraczający swój limit czasu zostaje zakończony, a zadanie oznaczone jako nieudane.
- Niezerowy kod wyjścia oznacza zadanie jako nieudane; wszystko, co skrypt wypisze na stdout i stderr, trafia do dziennika zadania.
- Skrypty działają z tymi samymi uprawnieniami co sam TikMatrix. Rejestruj tylko programy, które sam napisałeś albo którym ufasz.
Rozwiązywanie problemów
API access requires Pro or higher plan (403)
Licencja na tej maszynie to Starter albo jest nieaktywna. Sprawdź Ustawienia → Licencja.
Odmowa połączenia na 127.0.0.1:50809
TikMatrix nie działa albo działa jako inny użytkownik. Serwer istnieje tylko wtedy, gdy aplikacja jest otwarta.
409 przy każdej próbie dzierżawy Albo telefon faktycznie jest zajęty — sprawdź Ustawienia → Developer API → Aktywne sesje urządzeń — albo wszystkie miejsca urządzeń w planie zajmują już działające zadania.
Dzierżawa wygasa w środku długiego kroku
Domyślny TTL to 120 s, a biblioteka odnawia go w tle, więc zwykle oznacza to, że skrypt zablokował swój główny wątek na dłużej niż TTL. Podnieś ttl_secs (do 600) albo przenieś długą pracę poza ten wątek.
d.adb(...) kończy się błędem 403
Dostęp ADB jest wyłączony. Włącz go w Ustawienia → Developer API → Zezwól na polecenia ADB.
Selektor nigdy nie pasuje
print(d.hierarchy()) pokazuje dokładnie to drzewo, które przeszukał find. Tekst porównywany jest dosłownie, więc dodatkowa spacja albo przetłumaczona etykieta to typowa przyczyna; dopasowanie po resource_id jest stabilniejsze niż po text.
Zadanie oznaczone jako nieudane, a telefon wygląda dobrze Przeczytaj dziennik zadania. Niezerowe wyjście — w tym nieprzechwycony wyjątek na końcu udanego przebiegu — oznacza zadanie jako nieudane, nawet jeśli sama automatyzacja zadziałała.
Dalsze kroki
- Przegląd lokalnego API — uwierzytelnianie i format odpowiedzi
- API zarządzania zadaniami — tworzenie, odpytywanie, ponawianie i zatrzymywanie zadań
- Asystent AI — pozwól modelowi napisać i zarejestrować skrypt za ciebie
- SDK i przykłady na GitHubie