# 2.3 Callback Protocol

MaaFramework sends various status notifications and event messages to upper-layer applications through the `MaaEventCallback` callback function. All callback messages follow a unified format: message type (message) + detailed data (details).

## Message Format

```cpp
typedef void(MAA_CALL* MaaEventCallback)(void* handle, const char* message, const char* details_json, void* trans_arg);
```

- **handle**: Handle of the related object
  - MaaTasker* for MaaTasker event
  - MaaResource* for MaaResource event
  - MaaController* for MaaController event
  - MaaContext* for MaaContext event
- **message**: Message type string that identifies the event type
- **details_json**: JSON-formatted detailed data containing specific event information
- **trans_arg**: User-defined callback parameter

## Message Types

### Resource Loading Messages

Used to notify changes in resource loading status.

#### `Resource.Loading.Starting`

Sent when resource loading begins.

**details_json structure:**

```json
{
    "res_id": 12345,
    "path": "/path/to/resource",
    "type": "Bundle",
    "hash": "abc123def456"
}
```

- `res_id`: Resource ID (number)
- `path`: Resource path (string)
- `type`: Loading type (string)
  - `"Bundle"`: Complete resource directory (loaded via `post_bundle`)
  - `"OcrModel"`: OCR model directory (loaded via `post_ocr_model`)
  - `"Pipeline"`: Pipeline directory or single json/jsonc file (loaded via `post_pipeline`)
  - `"Image"`: Image directory or single image file (loaded via `post_image`)
- `hash`: Resource hash value (string)

#### `Resource.Loading.Succeeded`

Sent when resource loading succeeds. Same data structure as above.

#### `Resource.Loading.Failed`

Sent when resource loading fails. Same data structure as above.

### Controller Action Messages

Used to notify the status of controller action execution.

#### `Controller.Action.Starting`

Sent when the controller begins executing an action.

**details_json structure:**

```json
{
    "ctrl_id": 12345,
    "uuid": "550e8400-e29b-41d4-a716-446655440000",
    "action": "Click",
    "param": {
        "x": 100,
        "y": 200
    },
    "info": {
        "type": "adb",
        "adb_path": "/usr/bin/adb",
        "adb_serial": "127.0.0.1:5555"
    }
}
```

- `ctrl_id`: Controller ID (number)
- `uuid`: Unique identifier (string)
- `action`: Action type (string)
- `param`: Action parameters (object)
- `info`: Controller information (object). See [MaaControllerGetInfo](2.2-IntegratedInterfaceOverview.md#maacontrollergetinfo)

#### `Controller.Action.Succeeded`

Sent when controller action execution succeeds. Same data structure as above.

#### `Controller.Action.Failed`

Sent when controller action execution fails. Same data structure as above.

### Task Messages

Used to notify task execution status.

#### `Tasker.Task.Starting`

Sent when task execution begins.

**details_json structure:**

```json
{
    "task_id": 12345,
    "entry": "MyTask",
    "uuid": "550e8400-e29b-41d4-a716-446655440000",
    "hash": "abc123def456"
}
```

- `task_id`: Task ID (number)
- `entry`: Entry task name (string)
- `uuid`: Unique identifier (string)
- `hash`: Task hash value (string)

#### `Tasker.Task.Succeeded`

Sent when task execution succeeds. Same data structure as above.

#### `Tasker.Task.Failed`

Sent when task execution fails. Same data structure as above.

### Node Next List Messages

Used to notify the recognition of next node list.

#### `Node.NextList.Starting`

Sent when a node begins recognizing its next node list.

**details_json structure:**

```jsonc
{
    "task_id": 12345,
    "name": "NodeA",
    "list": [
        {
            "name": "NodeB",
            "jump_back": false,
            "anchor": false
        },
        {
            "name": "NodeC",
            "jump_back": true,
            "anchor": false
        },
        {
            "name": "LastHandler",
            "jump_back": false,
            "anchor": true
        }
    ],
    "focus": any,
}
```

- `task_id`: Task ID (number)
- `name`: Node name (string)
- `list`: Next node list (object array)
  - `name`: Node name or anchor name (string)
  - `jump_back`: Whether to jump back (boolean)
  - `anchor`: Whether this is an anchor reference (boolean). If true, name is an anchor name
- `focus`: Focus-related data (any type)

#### `Node.NextList.Succeeded`

Sent when a node successfully recognizes its next node list. Same data structure as above.

#### `Node.NextList.Failed`

Sent when a node fails to recognize its next node list. Same data structure as above.

### Node Recognition Messages

Used to notify the status of node recognition processes.

#### `Node.Recognition.Starting`

Sent when node recognition begins.

**details_json structure:**

```jsonc
{
    "task_id": 12345,
    "reco_id": 67890,
    "name": "NodeA",
    "focus": any,
    "anchor": "AnchorName", // optional
}
```

- `task_id`: Task ID (number)
- `reco_id`: Recognition ID (number)
- `name`: Node name (string)
- `focus`: Focus-related data (any type)
- `anchor`: Anchor reference name (string, optional). Present when this recognition was initiated via an `[Anchor]` node attribute, with the value being the anchor name

#### `Node.Recognition.Succeeded`

Sent when node recognition succeeds. Same data structure as above.

#### `Node.Recognition.Failed`

Sent when node recognition fails. Same data structure as above.

### Node Action Messages

Used to notify the status of node action execution.

#### `Node.Action.Starting`

Sent when a node begins executing an action.

**details_json structure:**

```jsonc
{
    "task_id": 12345,
    "node_id": 67890,
    "action_id": 11111,
    "name": "NodeA",
    "focus": any,
}
```

- `task_id`: Task ID (number)
- `action_id`: Action ID (number)
- `name`: Node name (string)
- `focus`: Focus-related data (any type)

#### `Node.Action.Succeeded`

Sent when node action execution succeeds. Same data structure as above.

#### `Node.Action.Failed`

Sent when node action execution fails. Same data structure as above.

### Node Wait Freezes Messages

Used to notify the status of `wait_freezes` execution (pre/post/repeat/context phases).

#### `Node.WaitFreezes.Starting`

Sent when `wait_freezes` begins.

**details_json structure:**

```jsonc
{
    "task_id": 12345,
    "wf_id": 600000001,
    "name": "NodeA",
    "phase": "pre",
    "roi": [0, 0, 1280, 720],
    "param": {
        "time": 3000,
        "threshold": 0.95,
        "method": 5,
        "rate_limit": 1000,
        "timeout": 20000
    },
    "focus": any,
}
```

- `task_id`: Task ID (number)
- `wf_id`: Wait Freezes ID (number). Can be used to query details via `MaaTaskerGetWaitFreezesDetail`
- `name`: Node name (string). Empty for `Context.wait_freezes`
- `phase`: Wait phase (string)
  - `"pre"`: `pre_wait_freezes`
  - `"post"`: `post_wait_freezes`
  - `"repeat"`: `repeat_wait_freezes`
  - `"context"`: `Context.wait_freezes`
- `roi`: Actual ROI used by comparison (`[x, y, width, height]`)
- `param`: Wait parameters (object)
  - `time`: Required freeze time in milliseconds (number)
  - `threshold`: Compare threshold (number)
  - `method`: OpenCV template match method (number)
  - `rate_limit`: Sampling interval in milliseconds (number)
  - `timeout`: Timeout in milliseconds; negative means infinite wait (number)
- `focus`: Focus-related data (any type)

#### `Node.WaitFreezes.Succeeded`

Sent when `wait_freezes` succeeds.

Compared with `Starting`, it additionally contains:

- `reco_ids`: Recognition ID list generated during each frame-to-frame comparison (number array)
- `elapsed`: Total elapsed time in milliseconds (number)

#### `Node.WaitFreezes.Failed`

Sent when `wait_freezes` fails (such as timeout or empty image).

Data structure is the same as `Succeeded`.

### Pipeline Node Messages

Used to notify the status of pipeline node execution. Pipeline node messages are sent when executing full pipeline tasks through `post_task` or `run_task`.

#### `Node.PipelineNode.Starting`

Sent when a pipeline node begins executing.

**details_json structure:**

```jsonc
{
    "task_id": 12345,
    "node_id": 67890,
    "name": "NodeA",
    "focus": any,
}
```

- `task_id`: Task ID (number)
- `node_id`: Node ID (number)
- `name`: Node name (string)
- `focus`: Focus-related data (any type)

#### `Node.PipelineNode.Succeeded`

Sent when pipeline node execution succeeds. Same data structure as above.

#### `Node.PipelineNode.Failed`

Sent when pipeline node execution fails. Same data structure as above.

### Recognition Node Messages

Used to notify the status of recognition node execution. Recognition node messages are sent only when executing recognition-only tasks through `run_recognition`.

#### `Node.RecognitionNode.Starting`

Sent when a recognition node begins executing.

**details_json structure:**

```jsonc
{
    "task_id": 12345,
    "node_id": 67890,
    "name": "NodeA",
    "focus": any,
}
```

- `task_id`: Task ID (number)
- `node_id`: Node ID (number)
- `name`: Node name (string)
- `focus`: Focus-related data (any type)

#### `Node.RecognitionNode.Succeeded`

Sent when recognition node execution succeeds. Same data structure as above.

#### `Node.RecognitionNode.Failed`

Sent when recognition node execution fails. Same data structure as above.

### Action Node Messages

Used to notify the status of action node execution. Action node messages are sent only when executing action-only tasks through `run_action`.

#### `Node.ActionNode.Starting`

Sent when an action node begins executing.

**details_json structure:**

```jsonc
{
    "task_id": 12345,
    "node_id": 67890,
    "name": "NodeA",
    "focus": any,
}
```

- `task_id`: Task ID (number)
- `node_id`: Node ID (number)
- `name`: Node name (string)
- `focus`: Focus-related data (any type)

#### `Node.ActionNode.Succeeded`

Sent when action node execution succeeds. Same data structure as above.

#### `Node.ActionNode.Failed`

Sent when action node execution fails. Same data structure as above.

## Usage Example

```cpp
void MyCallback(void* handle, const char* message, const char* details_json, void* callback_arg)
{
    // Parse message type
    if (strcmp(message, "Tasker.Task.Starting") == 0) {
        // Parse JSON to get task details
        // Update UI to show task starting status
    }
    else if (strcmp(message, "Node.Recognition.Succeeded") == 0) {
        // Handle recognition success event
        // Update recognition result display
    }
    // ... handle other message types
}

// Set callback
MaaTaskerAddSink(tasker, MyCallback, nullptr);
MaaTaskerAddNodeSink(tasker, MyCallback, nullptr);
```

## Important Notes

1. **JSON Parsing**: The `details_json` parameter is always a valid JSON string. It's recommended to use a mature JSON library for parsing
2. **Thread Safety**: Callback functions may be called from different threads, so thread safety considerations are necessary
3. **Performance**: Callback functions should return quickly to avoid blocking the framework's execution flow
4. **Error Handling**: It's recommended to add exception handling in callback functions to prevent callback exceptions from affecting framework operation
