minute read

Tasks

You are reading our Automation1 API documentation for the C programming language.

The Basics

In the C API, Tasks lets you interact with and manage the Automation1 controller tasks.

The Automation1 controller has one or more tasks that execute AeroScript programs and AeroScript commands on the controller. Each task has a task name and a task index.

Task indices start at 1. Task index 0 is reserved and cannot be used.

How to Use

Tasks is part of the controller runtime. Thus the Automation1 controller must be running before you do work with tasks. For more information, see the Controller page.

All the C API functions that work with tasks accept a task index. You can use the Automation1_Controller_GetTaskIndexFromTaskName() function to get the task index for a task name.

You can get the status of a task to see if the task is running an AeroScript program or if there is an error on the task.

Copy
bool Automation1_Task_GetStatus(Automation1Controller controller, Automation1TaskStatus* taskStatusArrayOut, int32_t taskStatusArrayLength);

Manage AeroScript Programs

You can use tasks in the C API to run AeroScript programs on controller tasks. This is one of two ways to command your Automation1 controller, with the other being Commands.

Copy
bool Automation1_Task_ProgramRun(Automation1Controller controller, int32_t taskIndex, const char* controllerFileName);

The Automation1_Task_ProgramRun() function starts the execution of the AeroScript program, but it does not wait for the program to complete. The specified controller file can be an AeroScript source file (.ascript) or a compiled AeroScript file (.a1exe). If the controller file is an AeroScript source file, then the file will be compiled before it is executed.

To determine if an AeroScript program is still running, do the steps that follow:

  1. Get the status of the task by using the Automation1_Task_GetStatus() function and the Automation1TaskStatus struct.
  2. Examine the TaskState member that returns the Automation1TaskState enum. The value of this enum will give you information about your program:
    • The Automation1TaskState_ProgramRunning enum value tells you if an AeroScript program is currently running on that task.
    • The Automation1TaskState_ProgramComplete enum value tells you if an AeroScript program completed successfully on that task.
    • The Automation1TaskState_Error enum value tells you if an AeroScript program failed with some type of error that you can examine with the Error member.

To stop an AeroScript program that is running, use the Automation1_Task_ProgramStop() function.

Copy
bool Automation1_Task_ProgramStop(Automation1Controller controller, int32_t taskIndex, int32_t millisecondsTimeout);

Handle AeroScript Callbacks

AeroScript programs that run on a controller task can use the Callback() AeroScript function to send information or to pass execution to a custom C application. When the Callback() function is executed from AeroScript, program execution on that task waits for a registered C callback handler to execute. When the C callback handler completes, the AeroScript program will continue. Each callback is identified by a unique identifier, which is a callback ID. This ID is used when you register for the callback and when you execute the Callback() AeroScript function. You can give these handlers data from AeroScript and they can return data to AeroScript. To learn more, see the Callback Functions page.

Inputs into a C callback handler and outputs out of a C callback handler can be AeroScript integers, AeroScript reals, and AeroScript strings. AeroScript integers are 64-bit. They are represented in C by the int64_t data type. AeroScript reals are double-precision floating-point numbers. They are represented in C by the double data type.

When called, your callback handler is given two arguments, an Automation1TaskCallbackArguments handle and an Automation1TaskCallbackReturn handle. To get the AeroScript inputs from the Automation1TaskCallbackArguments handle, use the Automation1_Task_CallbackGetArguments() function. Then do one of the options that follow:

  • If your callback handler was successful, use the Automation1_Task_CallbackSetReturn() function to set the AeroScript outputs on the Automation1TaskCallbackReturn handle.
  • If your callback handler was not successful, use the Automation1_Task_CallbackSetErrorMessage() function to set the error message on the Automation1TaskCallbackReturn handle.

Each callback handler that you register will execute on a new thread when the callback is raised by an AeroScript program.

You can use the Automation1_Task_CallbackRegister() function to register a handle for the Callback() AeroScript function. When you register a handler for this function, you must specify a function pointer of the Automation1TaskCallback type that will be invoked when the Callback() function is executed. You can register a callback ID one time per task.

To change the registration of the callback ID, you must unregister the handler that you are currently using. Then register a new handler.

Copy
Automation1_Task_CallbackRegister(Automation1Controller controller, int32_t taskIndex, int32_t callbackId, Automation1TaskCallback handler);
Automation1_Task_CallbackUnregister(Automation1Controller controller, int32_t taskIndex, int32_t callbackId);

Example Code

Copy
bool myCallback(Automation1TaskCallbackArguments callbackArguments, Automation1TaskCallbackReturn callbackReturn)
{
    // Call the Automation1_Task_CallbackGetArguments() function one time to get the size of each array.
    int32_t taskIndex;
    int32_t callbackId;
    int32_t integerInputsLen;
    int32_t realInputsLen;
    int32_t stringInputsLen;
    int32_t maxStringInputLen;
    if (!Automation1_Task_CallbackGetArguments(callbackArguments,
        &taskIndex, &callbackId,
        NULL, &integerInputsLen,
        NULL, &realInputsLen,
        NULL, &stringInputsLen, &maxStringInputLen))
    {
        /* handle error */
    }

    // Allocate space for the arrays and call the Automation1_Task_CallbackGetArguments() function again to populate them. AeroScript strings are stored in succession based on the stringInputsLen and maxStringInputLen values. The total space that an array of AeroScript strings requires is stringInputsLen * maxStringInputLen.
    int64_t* integerInputs = (int64_t*)malloc(sizeof(int64_t) * integerInputsLen);
    double* realInputs = (double*)malloc(sizeof(double) * realInputsLen);
    char* stringInputs = (char*)malloc(sizeof(char) * stringInputsLen * maxStringInputLen);
    if (!Automation1_Task_CallbackGetArguments(callbackArguments,
        NULL, NULL,
        integerInputs, &integerInputsLen,
        realInputs, &realInputsLen,
        stringInputs, &stringInputsLen, &maxStringInputLen))
    {
        /* handle error */
    }

    // Loop over and print the results.
    for (int i = 0; i < integerInputsLen; i++)
    {
        printf("%d\n", integerInputs[i]);
    }

    for (int i = 0; i < realInputsLen; i++)
    {
        printf("%f\n", realInputs[i]);
    }

    for (int i = 0; i < stringInputsLen; i++)
    {
        printf("%s\n", &stringInputs[i * maxStringInputLen]);
    }

    free(integerInputs);
    free(realInputs);
    free(stringInputs);

    // Set the values to return to an AeroScript program.
    int64_t integerOutputs[4] = { 5, 2, 9, 102 };
    double realOutputs[5] = { 1.1, 2.2, 3.3, 4.4, 5.5 };
    const char* stringOutputs[3] = { "Hello", "From", "C!" };
    if (!Automation1_Task_CallbackSetReturn(callbackReturn,
        integerOutputs, 4,
        realOutputs, 5,
        stringOutputs, 3))
    {
        /* handle error */
    }

    return true;
}

void registerMyCallback()
{
    Automation1Controller controller;
    if (!Automation1_Connect(&controller)) { /* handle error */ }
    if (!Automation1_Task_CallbackRegister(controller, 1, 1, my_callback)) { /* handle error */ }
    
    /* Do something else here, such as sleep or a long-running operation. The callback will be handled on a background thread. */

    if (!Automation1_Task_CallbackUnregister(controller, 1, 1)) { /* handle error */ }
    if (!Automation1_Disconnect(controller)) { /* handle error */ }
}

Task Variables

In the C API, Task Variables lets you get and set task variables on a task on an Automation1 controller. You can use task variables to share information between iterations of a program running on the same task.

IMPORTANT: Refer to Task Variables to learn how to use Task variables in the C API.

Thread Safety

All the Automation1_Task_ functions are thread safe. You can call them from two or more threads without interference.

Only one thread at a time can compile an AeroScript program.

For Example

Let's say that you call the Automation1_Task_ProgramRun() or Automation1_Task_ProgramLoad() function concurrently from two or more threads. The AeroScript programs that you specified also need to be compiled. As a result, all the threads will be blocked until one of the threads is done compiling.

Each callback handler that you register executes on a new thread when the callback is raised by an AeroScript program.

The C API is thread safe. But the controller might not be able to manage all the task operations that you do on separate threads. A single controller task can run only one AeroScript program at a time. You must synchronize or coordinate your process to prevent controller errors from occurring.

For Example

You can make a single C thread responsible for a single controller task.

Full Reference

For more information about the structs and functions that are available for Tasks, refer to the lists that follow.

Automation1TaskStatus struct

Represents the status of a controller task on an Automation1 controller.

Functions