Ga naar hoofdinhoud

Eigen scripts

De ingebouwde scripts dekken de gebruikelijke stromen af. Wanneer je iets nodig hebt wat ze niet bieden — een stap in een andere volgorde, een scherm dat ze nooit aanraken, of een app die geen TikTok of Instagram is — kun je het zelf schrijven in elke taal en laat TikMatrix je de telefoon overhandigen.

Vereisten

Licentievereiste

Eigen scripts vereisen een Pro-, Team- of Business-abonnement. Het Starter-abonnement heeft geen toegang.

Het aantal apparaten in je abonnement is tevens de gelijktijdigheidslimiet: een Pro-abonnement (20 apparaten) kan 20 telefoons tegelijk aansturen, via ingebouwde taken, eigen scripts of een mix van beide.

Twee manieren om een script te draaien

Zelfstandig

Je start je programma zelf. TikMatrix leent je alleen apparaten uit.

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())

Geschikt voor eenmalige klussen, dataverzameling en alles wat je vanuit je eigen planner wilt starten.

Beheerd

Je registreert het programma in TikMatrix en het wordt een taak als alle andere. Het krijgt de takenwachtrij, gelijktijdigheid volgens abonnement, automatische nieuwe pogingen, het takenlogboek en planningssjablonen. TikMatrix least het apparaat voordat het je programma start en geeft het lease-id mee in de omgeving.

from tikmatrix import TikMatrix

with TikMatrix.from_env() as d: # apparaat is al geleased
d.click(text="Log in")
print("done") # deze regel belandt in het takenlogboek

Geschikt voor alles wat je herhaaldelijk, volgens schema of op veel apparaten wilt draaien.

Welke kiezen

ZelfstandigBeheerd
Wie start hetJijDe takenwachtrij van TikMatrix
ApparaatleaseNeem je zelfAl in handen bij de start
Nieuwe pogingen, planning, logboekBouw je zelfInbegrepen
Draaien op veel apparatenJe schrijft zelf de lusEén taak per apparaat, parallel verdeeld
Het meest geschikt voorVerkennen, crawlers, eenmalige klussenAlles wat je wilt herhalen

Je kunt zelfstandig beginnen terwijl je de stroom afstemt en daarna hetzelfde bestand registreren als beheerd script — de enige regel die verandert is TikMatrix.from_env().

Aan de slag

1. Installeer de clientbibliotheek

pip install requests

Kopieer daarna tikmatrix.py uit de SDK-map naast je script. De bibliotheek is één bestand zonder verdere afhankelijkheden.

Je hoeft haar niet te gebruiken — de API is gewone JSON over HTTP, en de ruwe endpoints staan hieronder beschreven.

2. Schrijf je script

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")

Draai het met TikMatrix open en de telefoon aangesloten. Print het een woordenboek met apparaatgegevens, dan zit alles goed aangesloten.

3. Registreer het (alleen beheerde modus)

Ga naar Apparaten → Eigen scripts → Script toevoegen:

VeldBetekenis
NaamZichtbaar in de scriptlijst en het takenlogboek
OpdrachtDe programmaregel die wordt uitgevoerd, bv. python C:/scripts/my_flow.py
WerkmapOptioneel. Waar het programma start
PlatformZie platformmodi hieronder
Time-outSeconden voordat het script wordt afgebroken en de taak als mislukt wordt gemarkeerd. Standaard 1800
Extra omgevingsvariabelenOptioneel JSON-object dat in de omgeving van het programma wordt samengevoegd
IngeschakeldZet een script uit zonder het te verwijderen. Een uitgeschakeld script kan niet worden uitgedeeld

Druk daarna op ▶ in de scriptregel en kies je apparaten, precies zoals bij een ingebouwd script.

Laat de assistent het schrijven

De AI-assistent kan een eigen script opstellen aan de hand van een omschrijving in gewone taal en het in één stap registreren. Hij toont je het hele bestand voordat er iets naar schijf wordt geschreven.

Apparaatleases

Een telefoon kan maar door één ding tegelijk worden aangestuurd. Hem leasen vertelt TikMatrix dat het apparaat bezet is, zodat:

  • de takenwachtrij geen taak naar hetzelfde scherm stuurt, en
  • je JSON-RPC-aanroepen de gezondheid van de agent net zo rapporteren als een ingebouwd script doet, waardoor de watchdog een drukke agent ziet in plaats van een zwijgende.

Een lease verbruikt ook één apparaatplek uit je abonnement.

Leases verlopen — standaard na 120 seconden, maximaal 600. De Python-bibliotheek vernieuwt de jouwe in een achtergrondthread en geeft hem vrij zodra het with-blok eindigt, zodat een gecrasht script zijn apparaat binnen seconden vrijgeeft in plaats van het vast te houden tot je de app herstart. Roep je de API rechtstreeks aan, dan moet je zelf hartslagen sturen.

Je ziet elke levende lease — en kunt er één geforceerd vrijgeven — onder Instellingen → Developer API → Actieve apparaatsessies.

Platformmodi

Een geregistreerd script verklaart waarop het mikt:

Generic — het apparaat wordt onaangeroerd overgedragen. Er wordt geen app gestart, geen account gewisseld, geen invoermethode gecontroleerd, en achteraf wordt niets afgesloten. Gebruik dit om alles te automatiseren wat geen TikTok of Instagram is.

TikTok / Instagram — de app wordt geopend en het account gewisseld voordat je programma start, en de app wordt gesloten wanneer het klaar is, precies zoals bij een ingebouwd script. TIKMATRIX_PACKAGE vertelt welk pakket is gekozen. Gebruik dit om een stap toe te voegen die de ingebouwde scripts niet dekken.

Omgevingsvariabelen

Een beheerd script ontvangt:

VariabeleBetekenis
TIKMATRIX_API_BASEServer-URL, bv. http://127.0.0.1:50809
TIKMATRIX_SESSION_IDDe lease die al voor je wordt aangehouden
TIKMATRIX_SERIALHet apparaat waarnaar deze taak is gestuurd
TIKMATRIX_PACKAGEHet gekozen app-pakket
TIKMATRIX_PLATFORMtiktok, instagram of generic

TikMatrix.from_env() leest dit allemaal voor je uit.

Zelfstandige scripts krijgen hier niets van — lease dan expliciet een apparaat.

Alles wat je in Extra omgevingsvariabelen zet, wordt er bovenop samengevoegd; dat is de gebruikelijke manier om één geregistreerd script per run andere instellingen te geven zonder het bestand aan te passen.

Naslag voor de Python-bibliotheek

TikMatrix — de verbinding

AanroepWat het doet
TikMatrix(base_url=None, timeout=30.0)Verbindt. Valt terug op TIKMATRIX_API_BASE, daarna http://127.0.0.1:50809
client.devices()Online apparaten, elk met serial, real_serial en busy
client.sessions()Alle levende leases, ook die van andere processen
client.device(serial, label=..., ttl_secs=120)Least een apparaat en geeft een Device terug
TikMatrix.from_env()Neemt het apparaat over waarmee een beheerd script is gestart

Device — de telefoon

AanroepWat het doet
d.info()Apparaatgegevens van UIAutomator2
d.window_size()(breedte, hoogte)
d.screenshot(path=None)PNG-bytes, optioneel weggeschreven naar path
d.hierarchy()De huidige UI-boom als XML
d.find(text=, resource_id=, description=, class_name=)Overeenkomende knopen, elk met bounds en center
d.exists(**criteria)Of er iets overeenkomt
d.wait_for(timeout=10.0, interval=1.0, **criteria)Wacht tot het verschijnt en geeft het terug
d.click(timeout=10.0, **criteria)Wacht op een element en tikt op het midden ervan
d.click_xy(x, y)Tikt op een coördinaat
d.swipe(sx, sy, ex, ey, steps=20)Veegt
d.press(key)back, home, recent, enter, …
d.input_text(text)Typt in het actieve veld via de meegeleverde snelle invoermethode
d.jsonrpc(method, params=None, timeout=10)Elke UIAutomator2-methode
d.adb(*args, timeout_ms=None)Voert een ADB-opdracht uit
d.release()Geeft de lease vrij. with doet dit voor je

find zoekt in de uitgelezen UI-boom, dus als een selector mist kun je print(d.hierarchy()) doen en precies zien waarin is gezocht. De Element Inspector in de apparaatweergave toont dezelfde boom visueel, meestal de snelste manier om een resource-id te vinden.

input_text heeft ADB nodig

Het stuurt een broadcast naar de meegeleverde invoermethode, en dat loopt via adb shell. Zet ADB-toegang aan voordat je het gebruikt, anders mislukt het met 403.

Fouten

De bibliotheek gooit twee excepties, beide subklassen van RuntimeError:

ExceptieWanneer
DeviceBusyErrorHTTP 409 — het apparaat is al geleased, of je abonnement heeft geen vrije plek
TikMatrixErrorAl het andere: abonnement te laag, lease verlopen, ADB uit, selector die nooit trof
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("die telefoon is bij iemand anders in gebruik — probeer een andere")
except TikMatrixError as exc:
print("mislukt:", exc)

In een beheerd script is de exceptie laten doorlopen meestal het juiste: de afsluitcode ongelijk aan nul markeert de taak als mislukt en de traceback belandt in het takenlogboek.

HTTP-endpoints

Apparaatbewerkingen hebben een x-session-id-header nodig die naar een levende lease verwijst. Er is geen API-sleutel: net als de rest van de lokale API zijn deze endpoints niet geauthenticeerd — de machine over het netwerk kunnen bereiken ís de toegangscontrole. Ze sturen geen CORS-headers, dus roep ze aan vanuit een programma (curl, Python, welke servercode dan ook) en niet vanuit een pagina in een browser.

MethodePadDoel
GET/api/v1/rpc/devicesToont online apparaten en of ze bezet zijn
POST/api/v1/rpc/sessionLeast een apparaat → session_id
POST/api/v1/rpc/session/{id}/heartbeatVerlengt de lease
DELETE/api/v1/rpc/session/{id}Geeft de lease vrij
GET/api/v1/rpc/sessionToont levende leases
POST/api/v1/rpc/jsonrpcRoept een UIAutomator2-methode aan
POST/api/v1/rpc/adbVoert een ADB-opdracht uit
GET/api/v1/rpc/hierarchy?serial=Huidige UI-boom als XML
GET/api/v1/rpc/screenshot?serial=Huidig scherm als PNG

JSON-antwoorden gebruiken dezelfde envelop als de rest van de lokale API — {"code": 0, "message": "success", "data": ...}, met een code ongelijk aan nul bij een fout. hierarchy en screenshot geven in plaats daarvan de ruwe body terug.

Voorbeeld

# Een apparaat leasen
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", ...}}

# Aansturen
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":[]}'

# In leven houden tijdens het werk
curl -X POST http://127.0.0.1:50809/api/v1/rpc/session/ff3ae079-.../heartbeat \
-H "Content-Type: application/json" \
-d '{"ttl_secs":120}'

# Teruggeven
curl -X DELETE http://127.0.0.1:50809/api/v1/rpc/session/ff3ae079-...

Fouten

StatusBetekenis
403Abonnement lager dan Pro, geen lease, verlopen lease of ADB-toegang uitgeschakeld
409Apparaat al geleased, of je abonnement heeft geen vrije plek

In een andere taal schrijven

Niets hiervan is Python-specifiek. Elke runtime die een HTTP-verzoek kan doen werkt — het contract van de beheerde modus is alleen: "lees drie omgevingsvariabelen, sluit af met 0 bij succes".

// my_flow.js — registreer met: 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"));

Staat de interpreter niet in PATH, geef dan het volledige pad op bij Opdracht, bv. C:/Program Files/nodejs/node.exe C:/scripts/my_flow.js.

Een eigen script starten via de API

Geregistreerde scripts kunnen ook via de Takenbeheer-API worden gestart, zodat één script vervolgwerk in de wachtrij kan zetten:

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 is het id van het script dat je hebt geregistreerd.

ADB-toegang

/api/v1/rpc/adb geeft je scripts een shell op het apparaat — je hebt die nodig om media te pushen, APK's te installeren en systeeminstellingen te wijzigen. Omdat het een volwaardige shell is op een endpoint zonder API-sleutel, staat hij standaard uit. Zet hem aan onder Instellingen → Developer API → ADB-opdrachten toestaan zodra je een script hebt dat hem nodig heeft; UI-automatisering via /rpc/jsonrpc werkt ook zonder.

Zolang hij uit staat antwoordt /api/v1/rpc/adb met 403 en blijft de rest van de API gewoon werken. Elke ADB-opdracht die een script uitvoert wordt in je logbestand geschreven.

Scripts schrijven die blijven werken

  • Wacht op het scherm, slaap er niet voor. d.wait_for(...) keert terug zodra het element er is; een vaste sleep is óf trager dan nodig, óf te kort op een slechte dag.
  • Controleer voordat je tikt. Een d.exists(...) op een toestemmingsvenster of een "niet nu"-melding kost één boomuitlezing en redt een run die anders in het luchtledige zou tikken.
  • Print wat je hebt gedaan. In de beheerde modus ís stdout het takenlogboek, en het is het enige spoor van een run waar niemand naar keek.
  • Maak opnieuw draaien veilig. Een nieuwe poging draait het hele programma opnieuw, dus een script dat publiceert zou moeten controleren of het al gepubliceerd heeft in plaats van aan te nemen dat het bij nul begint.
  • Eén script, één klus. Gelijktijdigheid geldt per apparaat, dus tien kleine taken op tien telefoons zijn veel eerder klaar dan één script dat in een lus tien telefoons afgaat.

Opmerkingen en grenzen

  • De opdracht wordt rechtstreeks uitgevoerd, niet via een shell, dus && en | gelden als argumenten en niet als operatoren. Registreer cmd /c "..." (Windows) of sh -c "..." (macOS) als je shell-gedrag wilt.
  • Zet paden met spaties tussen aanhalingstekens: "C:/Program Files/Python/python.exe" my_script.py.
  • Een script dat zijn time-out overschrijdt wordt afgebroken en de taak als mislukt gemarkeerd.
  • Een afsluitcode ongelijk aan nul markeert de taak als mislukt; alles wat het script naar stdout en stderr schrijft belandt in het takenlogboek.
  • Scripts draaien met dezelfde rechten als TikMatrix zelf. Registreer alleen programma's die je zelf schreef of vertrouwt.

Problemen oplossen

API access requires Pro or higher plan (403) De licentie op deze machine is Starter of inactief. Controleer Instellingen → Licentie.

Verbinding geweigerd op 127.0.0.1:50809 TikMatrix draait niet, of draait als een andere gebruiker. De server bestaat alleen zolang de app open is.

409 bij elke leasepoging Óf de telefoon is echt bezet — kijk bij Instellingen → Developer API → Actieve apparaatsessies — óf alle apparaatplekken in je abonnement zijn al bezet door lopende taken.

De lease verloopt midden in een lange stap De standaard-TTL is 120 s en de bibliotheek vernieuwt hem op de achtergrond, dus dit betekent meestal dat het script zijn hoofdthread langer blokkeerde dan de TTL. Verhoog ttl_secs (tot 600), of haal het langdurige werk uit die thread.

d.adb(...) mislukt met 403 ADB-toegang staat uit. Zet hem aan onder Instellingen → Developer API → ADB-opdrachten toestaan.

Een selector treft nooit iets print(d.hierarchy()) toont precies de boom die find doorzocht. Tekst wordt exact vergeleken, dus een spatie te veel of een vertaald label is de gebruikelijke oorzaak; zoeken op resource_id is stabieler dan op text.

De taak is mislukt maar de telefoon ziet er goed uit Lees het takenlogboek. Een afsluitcode ongelijk aan nul — ook een niet-afgevangen exceptie aan het eind van een geslaagde run — laat de taak mislukken, zelfs als de automatisering zelf werkte.

Volgende stappen