Task Creation, Execution, and Result Retrieval


Please refer to JavaScript Modules for more information.


How to Use

Introduction:

This example demonstrates how to fully manage the lifecycle of an automation task using the Tasks API.
The script sequentially performs task creation (tasksCreate), task record confirmation (tasksGet), and continuously polls the task status until execution completes (RUNNING → STOPPED_*), finally outputting the task execution results and key information.
The example includes standardized step logs (start / end / duration statistics), and in failure scenarios automatically collects foreground app information, Activity, battery level, device details, and screenshots as evidence, making troubleshooting and result auditing easier.
It is suitable for scenarios such as automated test scheduling, batch task execution, platform integration, and execution result monitoring, and can be copied and run directly.

Before Running:

  1. Download and install Total Control 11.0 (Update 20) or later (Download)
  2. Connect Android devices (supports USB connection or TCP connection)
  3. Select the test devices in the Total Control interface (note: getDevices() in the script only returns the currently selected devices)
  4. [Important] File preparation: please prepare a task script file in advance
    • Path: place it in the Total Control default script directory
    • File name: test.js
    • Content example:
      sleep(10000);
      print('-tasks-test-');
  5. Save the example code as a .js file (e.g., TaskCreateSubmitPoll.js) and place it in the Total Control default script directory
  6. Open the Script Terminal (Main Panel → Script → Terminal) and execute:
    >> sigmaLoad("TaskCreateSubmitPoll.js");
    

Notes:

  • tasksCreate() validates that the script path must exist; otherwise, it will return "Script path not found"
  • The task “executor” may not start immediately; if planTime is in the future, it will remain in SCHEDULED(-6)
  • This example uses polling with tasksGet to obtain the final status (-2 / -3 / -5, etc.)


Source Code

/** 
 * ============================================================
 * [TASK] Create -> Submit -> Get results
 * ============================================================
 * Objective:
 *  1) Create task tasksCreate(...)
 *  2) Confirm task is recorded tasksGet(...)
 *  3) Poll tasksGet(...) until task finishes (RUNNING -> STOPPED_*)
 *  4) Print results (status / errorMessage / execDevice / sigmaTestStatus, etc.)
 *
 * Output requirements:
 *  - Print "start / end / duration" for each step
 *  - On failure: write context (foreground package + activity + battery + device info)
 *    + screenshot + write log file (if fs is available)
 *
 * Key notes:
 *  - tasksCreate() validates that the script path must exist, otherwise "Script path not found"
 *  - The task "executor" may not start immediately; if planTime is in the future,
 *    it will remain in SCHEDULED(-6)
 *  - This example uses polling with tasksGet to obtain the final status (-2 / -3 / -5, etc.)
 */

// ===================== Imports & injections =====================
var { getDevices } = require("sigma/device");
var tasks = require("sigma/tasks"); // tasks module

// ===================== Configuration =====================
var LOG_DIR = "C:/tc_logs";

var IMG_TYPE = tcConst.IMG_JPG || tcConst.IMG_PNG;

// Task name must be unique (recommended to include a timestamp)
function pad2(n) {
    return (n < 10 ? "0" : "") + n;
}
function ts() {
    var d = new Date();
    return (
        d.getFullYear() +
        pad2(d.getMonth() + 1) +
        pad2(d.getDate()) +
        "_" +
        pad2(d.getHours()) +
        pad2(d.getMinutes()) +
        pad2(d.getSeconds())
    );
}

var TASK_NAME = "demo_task_" + ts();

// Script must exist and the extension must be .js / .tst / .scp
// Example: var SCRIPT_PATH = "c:/file/test.js" or just test.js;
var SCRIPT_PATH = "test.js";
// Execution count (iteration / iterCount) >= 1
var ITERATION = 1;

// Execution time strategy:
// 1) Create immediately (now): time = undefined, repeat = undefined
// 2) One-time scheduled execution: time = "YYYY-MM-DD HH:mm[:ss]"
// 3) Recurring: time="HH:mm[:ss]" + repeat=[0..6]
var TIME_MODE = "now"; // "now" | "runOnce" | "weekly"

// runOnce example (future time)
// var ONE_SHOT_TIME = "2026-01-14 23:50";

// weekly example: every Monday, Wednesday, Friday at 08:30
// var WEEKLY_TIME = "08:30";
// var WEEKLY_REPEAT = [1,3,5];

// Polling max wait time (milliseconds)
var WAIT_TIMEOUT_MS = 3 * 60 * 1000; // 3 minutes
var POLL_INTERVAL_MS = 1500;

// ===================== Utilities =====================
function nowMs() {
    return Date.now();
}
function safeFilePart(s) {
    return String(s).replace(/[^\w\-.]+/g, "_");
}
function devName(d) {
    return d.name || (d.getName && d.getName()) || d.SN || "UnknownDevice";
}
function safeGet(fn, fallback) {
    try {
        return fn();
    } catch (e) {
        return fallback;
    }
}

// fs (write logs / locks if available)
var fs = null;
try {
    fs = require("fs");
} catch (e) {
    fs = null;
}

function ensureDir(path) {
    if (!fs) return false;
    try {
        if (!fs.existsSync(path)) fs.mkdirSync(path, { recursive: true });
        return true;
    } catch (e) {
        return false;
    }
}
function appendFile(path, text) {
    if (!fs) return false;
    try {
        fs.appendFileSync(path, text, { encoding: "utf8" });
        return true;
    } catch (e) {
        return false;
    }
}

// ===================== Log context =====================
function makeCtx() {
    var canWrite = fs != null && ensureDir(LOG_DIR);
    var logFile =
        LOG_DIR + "/TASK__" + safeFilePart(TASK_NAME) + "__" + ts() + ".log";

    return {
        logFile: logFile,
        canWrite: canWrite,
        log: function (line) {
            var msg = "[TASK] " + line;
            print(msg);
            if (this.canWrite) appendFile(this.logFile, msg + "\n");
        },
    };
}

// ===================== stepRun: start / end / duration =====================
function stepRun(ctx, stepName, fn) {
    var start = nowMs();
    ctx.log(">> START  " + stepName);
    try {
        var ret = fn();
        ctx.log(
            "<< END    " + stepName + "  (cost " + (nowMs() - start) + " ms)",
        );
        return { ok: true, ret: ret };
    } catch (e) {
        ctx.log(
            "<< FAIL   " +
                stepName +
                "  (cost " +
                (nowMs() - start) +
                " ms)  err=" +
                String(e && e.message ? e.message : e),
        );
        return { ok: false, err: String(e && e.message ? e.message : e) };
    }
}

// ===================== Failure context + screenshot =====================
function writeFailContext(ctx, d, stepName, errText) {
    ctx.log("---- FAIL CONTEXT (" + devName(d) + ") BEGIN ----");
    ctx.log("step=" + stepName);
    ctx.log("error=" + (errText || ""));
    ctx.log(
        "foregroundApp=" +
            (safeGet(function () {
                return d.getForegroundApp();
            }, "") || ""),
    );
    ctx.log(
        "activity=" +
            (safeGet(function () {
                return d.getActivity();
            }, "") || ""),
    );
    ctx.log(
        "battery=" +
            (safeGet(function () {
                return d.battery;
            }, "") || ""),
    );
    ctx.log(
        "manufacturer=" +
            safeGet(function () {
                return d.manufacturer;
            }, ""),
    );
    ctx.log(
        "model=" +
            safeGet(function () {
                return d.model;
            }, ""),
    );
    ctx.log(
        "SN=" +
            safeGet(function () {
                return d.SN;
            }, ""),
    );
    ctx.log(
        "IP=" +
            safeGet(function () {
                return d.IP;
            }, ""),
    );
    ctx.log(
        "DPI=" +
            safeGet(function () {
                return d.DPI;
            }, ""),
    );
    ctx.log(
        "resolution=" +
            safeGet(function () {
                return d.width;
            }, "") +
            "x" +
            safeGet(function () {
                return d.height;
            }, ""),
    );
    ctx.log(
        "androidVersionRelease=" +
            safeGet(function () {
                return d.androidVersionRelease;
            }, ""),
    );
    ctx.log(
        "androidVersionSdkInt=" +
            safeGet(function () {
                return d.androidVersionSdkInt;
            }, ""),
    );
    ctx.log("---- FAIL CONTEXT (" + devName(d) + ") END ----");
}

function screenshotOne(ctx, d, tag) {
    var file =
        LOG_DIR +
        "/" +
        safeFilePart(devName(d)) +
        "__" +
        safeFilePart(tag) +
        "__" +
        ts() +
        ".jpg";
    var ret = d.screenshot(file, IMG_TYPE);
    if (ret === 0) ctx.log("!! Screenshot saved: " + file);
    else ctx.log("!! Screenshot failed (" + devName(d) + "): " + lastError());
}

// ===================== task status helper =====================
function statusToText(code) {
    var S = tasks.STATUS || {};
    // Common values (from documentation)
    if (code === 0) return "FILE_NOT_FOUND(0)";
    if (code === S.RUNNING || code === -1) return "RUNNING(-1)";
    if (code === S.STOPPED_NORMAL || code === -2) return "STOPPED_NORMAL(-2)";
    if (code === S.STOPPED_ERROR || code === -3) return "STOPPED_ERROR(-3)";
    if (code === S.PAUSED || code === -4) return "PAUSED(-4)";
    if (code === S.USER_TERMINATED || code === -5)
        return "USER_TERMINATED(-5)";
    if (code === S.SCHEDULED || code === -6) return "SCHEDULED(-6)";
    return String(code);
}

function isTerminalStatus(code) {
    return code === -2 || code === -3 || code === -5 || code === 0;
}

// ===================== main =====================
function main() {
    var ctx = makeCtx();

    // Optional: get devices, mainly for failure context / screenshots
    var devices = getDevices();
    var list = [];
    if (devices && devices.length)
        devices.forEach(function (d) {
            list.push(d);
        });
    ctx.log("Selected devices: " + list.length);

    // Step0: prepare script path existence info
    stepRun(ctx, "Step0 Check script path string", function () {
        ctx.log("TASK_NAME=" + TASK_NAME);
        ctx.log("SCRIPT_PATH=" + SCRIPT_PATH);
        ctx.log("ITERATION=" + ITERATION);
        ctx.log("TIME_MODE=" + TIME_MODE);
    });

    // Step1: Create task
    var s1 = stepRun(ctx, "Step1 tasksCreate()", function () {
        var ret;

        if (TIME_MODE === "now") {
            // Immediate (omit time / repeat)
            ret = tasks.tasksCreate(TASK_NAME, SCRIPT_PATH, ITERATION);
        } else if (TIME_MODE === "runOnce") {
            if (typeof ONE_SHOT_TIME === "undefined")
                throw new Error("ONE_SHOT_TIME is not set");
            // One-time scheduled execution
            ret = tasks.tasksCreate(
                TASK_NAME,
                SCRIPT_PATH,
                ITERATION,
                ONE_SHOT_TIME,
            );
        } else if (TIME_MODE === "weekly") {
            if (typeof WEEKLY_TIME === "undefined")
                throw new Error("WEEKLY_TIME is not set");
            if (typeof WEEKLY_REPEAT === "undefined")
                throw new Error("WEEKLY_REPEAT is not set");
            // Recurring execution
            ret = tasks.tasksCreate(
                TASK_NAME,
                SCRIPT_PATH,
                ITERATION,
                WEEKLY_TIME,
                WEEKLY_REPEAT,
            );
        } else {
            throw new Error("Unknown TIME_MODE: " + TIME_MODE);
        }

        if (ret !== true && typeof ret !== "number") {
            // tasksCreate docs: success -> true; failure -> false (check lastError)
            throw new Error("tasksCreate FAIL: " + lastError());
        }

        ctx.log("tasksCreate OK, ret=" + ret);
        return ret;
    });

    if (!s1.ok) {
        ctx.log("[CREATE] Task create FAIL: " + TASK_NAME);
        ctx.log("[CREATE] err=" + s1.err);

        // On failure: add context + screenshot for each device
        for (var i = 0; i < list.length; i++) {
            writeFailContext(ctx, list[i], "tasksCreate", s1.err);
            screenshotOne(ctx, list[i], "FAIL__tasksCreate");
        }

        // Extra: print recent tasks to help troubleshooting
        var s1b = stepRun(ctx, "Step1b tasksList(recent 5)", function () {
            var recent = tasks.tasksList({
                limit: 5,
                orderBy: "updatedAt DESC",
            });
            ctx.log("recent tasks:\n" + JSON.stringify(recent, null, 2));
        });

        return;
    }

    // Step2: Get task record (submit / confirm)
    var taskRow = null;
    var s2 = stepRun(ctx, "Step2 tasksGet(taskName)", function () {
        var t = tasks.tasksGet(TASK_NAME);
        if (!t) throw new Error("tasksGet returned null (not found)");
        taskRow = t;
        // tasksGet may return object or [object] (implementation-dependent)
        if (Array.isArray(taskRow)) taskRow = taskRow[0];
        ctx.log("task snapshot:\n" + JSON.stringify(taskRow, null, 2));
        return taskRow;
    });
    if (!s2.ok) return;

    // Step3: Poll until terminal
    var s3 = stepRun(
        ctx,
        "Step3 Poll task until terminal or timeout",
        function () {
            var deadline = nowMs() + WAIT_TIMEOUT_MS;
            var lastStatus = null;

            while (nowMs() < deadline) {
                var t = tasks.tasksGet(TASK_NAME);
                if (Array.isArray(t)) t = t[0];
                if (!t) throw new Error("tasksGet null during polling");

                var st = t.status;
                if (st !== lastStatus) {
                    ctx.log(
                        "poll: status=" +
                            statusToText(st) +
                            " startTime=" +
                            t.startTime +
                            " endTime=" +
                            t.endTime,
                    );
                    lastStatus = st;
                }

                if (isTerminalStatus(st)) {
                    taskRow = t;
                    return t;
                }

                sleep(POLL_INTERVAL_MS);
            }

            // Timeout: may still be SCHEDULED / RUNNING
            throw new Error(
                "Timeout waiting task finish. lastStatus=" +
                    statusToText(lastStatus),
            );
        },
    );

    // Step4: Print result summary
    stepRun(ctx, "Step4 Print result summary", function () {
        var t = taskRow;
        if (Array.isArray(t)) t = t[0];

        ctx.log("===== RESULT =====");
        ctx.log("taskName=" + t.taskName);
        ctx.log("taskID=" + t.taskID);
        ctx.log("status=" + statusToText(t.status));
        ctx.log("errorMessage=" + (t.errorMessage || ""));
        ctx.log("execDevice=" + (t.execDevice || "-"));
        ctx.log("startTime=" + t.startTime);
        ctx.log("endTime=" + t.endTime);
        ctx.log(
            "sigmaTestStatus=" +
                (t.sigmaTestStatus || t.sigma_test_status || ""),
        );

        // If failed: add device context + screenshots
        if (t.status === -3 || t.status === 0) {
            ctx.log("Task ended with error, collecting device evidence...");
            for (var i = 0; i < list.length; i++) {
                writeFailContext(
                    ctx,
                    list[i],
                    "taskResult(" + statusToText(t.status) + ")",
                    t.errorMessage || "",
                );
                screenshotOne(ctx, list[i], "FAIL__taskResult");
            }
        }
    });

    // Step5: Optional - show recent list
    stepRun(ctx, "Step5 tasksList(recent 5)", function () {
        var recent = tasks.tasksList({ limit: 5, orderBy: "updatedAt DESC" });
        ctx.log("recent tasks:\n" + JSON.stringify(recent, null, 2));
    });

    ctx.log("DONE.");
}

main();


Execution Result

[TASK] Selected devices: 2
[TASK] >> START  Step0 Check script path string
[TASK] TASK_NAME=demo_task_20260127_184910
[TASK] SCRIPT_PATH=test.js
[TASK] ITERATION=1
[TASK] TIME_MODE=now
[TASK] << END    Step0 Check script path string  (cost 155 ms)
[TASK] >> START  Step1 tasksCreate()
[TASK] tasksCreate OK, ret=true
[TASK] << END    Step1 tasksCreate()  (cost 165 ms)
[TASK] >> START  Step2 tasksGet(taskName)
[TASK] task snapshot:
{
  "id": 7,
  "autoConnect": false,
  "autoSelect": false,
  "startTime": 1769510950415,
  "endTime": null,
  "errorMessage": "",
  "execCount": 1,
  "execDevice": "-",
  "expiration": -31,
  "iterCount": 1,
  "reExec": false,
  "options": [
    {
      "device_names": [],
      "device_sn": [],
      "path": "C:\\Users\xxx\\Documents\\Scripts\\test.js"
    }
  ],
  "status": -1,
  "taskID": 17695109504181,
  "taskName": "demo_task_20260127_184910",
  "planTime": 1769510950415,
  "weekJson": null,
  "createdAt": 1769510950415,
  "updatedAt": 1769510950452,
  "timezone": "Asia/Shanghai",
  "sigmaTestStatus": null
}
[TASK] << END    Step2 tasksGet(taskName)  (cost 67 ms)
[TASK] >> START  Step3 Poll task until terminal or timeout
[TASK] poll: status=RUNNING(-1) startTime=1769510950415 endTime=null
[TASK] poll: status=STOPPED_NORMAL(-2) startTime=1769510950415 endTime=1769510960615
[TASK] << END    Step3 Poll task until terminal or timeout  (cost 10639 ms)
[TASK] >> START  Step4 Print result summary
[TASK] ===== RESULT =====
[TASK] taskName=demo_task_20260127_184910
[TASK] taskID=17695109504181
[TASK] status=STOPPED_NORMAL(-2)
[TASK] errorMessage=
[TASK] execDevice=-
[TASK] startTime=1769510950415
[TASK] endTime=1769510960615
[TASK] sigmaTestStatus=
[TASK] << END    Step4 Print result summary  (cost 310 ms)
[TASK] >> START  Step5 tasksList(recent 5)
[TASK] recent tasks:
[
  {
    "id": 7,
    "autoConnect": false,
    "autoSelect": false,
    "startTime": 1769510950415,
    "endTime": 1769510960615,
    "errorMessage": "",
    "execCount": 1,
    "execDevice": "-",
    "expiration": -10200,
    "iterCount": 1,
    "reExec": false,
    "options": [
      {
        "device_names": [],
        "device_sn": [],
        "path": "C:\\Users\xxx\\Documents\\Scripts\\test.js"
      }
    ],
    "status": -2,
    "taskID": 17695109504181,
    "taskName": "demo_task_20260127_184910",
    "planTime": 1769510950415,
    "weekJson": null,
    "createdAt": 1769510950415,
    "updatedAt": 1769510960619,
    "timezone": "Asia/Shanghai",
    "sigmaTestStatus": null
  },
  {
    "id": 6,
    "autoConnect": false,
    "autoSelect": false,
    "startTime": 1769520600000,
    "endTime": null,
    "errorMessage": "",
    "execCount": 1,
    "execDevice": "-",
    "expiration": 12714486,
    "iterCount": 1,
    "reExec": false,
    "options": [
      {
        "device_names": [
          "T110",
          "TestDevice03"
        ],
        "device_sn": [
          "GDB6R19819001063",
          "GDB6R19A18005229"
        ],
        "path": "C:/Users/XXX/Documents/Scripts/TaskCreateSubmitPoll.js"
      }
    ],
    "status": -6,
    "taskID": 17695078855150,
    "taskName": "form_fill_demo_20260127_175805",
    "planTime": 1769520600000,
    "weekJson": "[\"2\",\"4\"]",
    "createdAt": 1769507885514,
    "updatedAt": 1769507885514,
    "timezone": "Asia/Shanghai",
    "sigmaTestStatus": null
  },
  {
    "id": 5,
    "autoConnect": false,
    "autoSelect": false,
    "startTime": 1769520600000,
    "endTime": null,
    "errorMessage": "",
    "execCount": 1,
    "execDevice": "-",
    "expiration": 13809711,
    "iterCount": 1,
    "reExec": false,
    "options": [
      {
        "device_names": [
          "T110",
          "TestDevice03"
        ],
        "device_sn": [
          "GDB6R19819001063",
          "GDB6R19A18005229"
        ],
        "path": "C:/Users/XXX/Documents/Scripts/TaskCreateSubmitPoll.js"
      }
    ],
    "status": -6,
    "taskID": 17695067902980,
    "taskName": "form_fill_demo_20260127_173950",
    "planTime": 1769520600000,
    "weekJson": "[\"2\",\"4\"]",
    "createdAt": 1769506790289,
    "updatedAt": 1769506790289,
    "timezone": "Asia/Shanghai",
    "sigmaTestStatus": null
  },
  {
    "id": 4,
    "autoConnect": false,
    "autoSelect": false,
    "startTime": 1769520600000,
    "endTime": null,
    "errorMessage": "",
    "execCount": 1,
    "execDevice": "-",
    "expiration": 14652852,
    "iterCount": 1,
    "reExec": false,
    "options": [
      {
        "device_names": [
          "T110",
          "TestDevice03"
        ],
        "device_sn": [
          "GDB6R19819001063",
          "GDB6R19A18005229"
        ],
        "path": "C:/Users/XXX/Documents/Scripts/TaskCreateSubmitPoll.js"
      }
    ],
    "status": -6,
    "taskID": 17695059471538,
    "taskName": "form_fill_demo_20260127_172547",
    "planTime": 1769520600000,
    "weekJson": "[\"2\",\"4\"]",
    "createdAt": 1769505947148,
    "updatedAt": 1769505947148,
    "timezone": "Asia/Shanghai",
    "sigmaTestStatus": null
  },
  {
    "id": 3,
    "autoConnect": false,
    "autoSelect": false,
    "startTime": 1769504982779,
    "endTime": 1769504992938,
    "errorMessage": "",
    "execCount": 1,
    "execDevice": "-",
    "expiration": -10158,
    "iterCount": 1,
    "reExec": false,
    "options": [
      {
        "device_names": [],
        "device_sn": [],
        "path": "C:\\Users\xxx\\Documents\\Scripts\\test.js"
      }
    ],
    "status": -2,
    "taskID": 17695049827861,
    "taskName": "demo_task_20260127_170942",
    "planTime": 1769504982780,
    "weekJson": null,
    "createdAt": 1769504982779,
    "updatedAt": 1769504992940,
    "timezone": "Asia/Shanghai",
    "sigmaTestStatus": null
  }
]
[TASK] << END    Step5 tasksList(recent 5)  (cost 73 ms)
[TASK] DONE.
0

TCHelp