JAKA AddOn Development Guide

Overview

This document provides development guidance for JAKA AddOn development, including the basic AddOn structure, development workflow, API usage, and solutions to common problems.

Intended Audience

JAKA robot application developers
Third-party AddOn developers
System integration engineers

AddOn Overview

JAKA AddOn is extensible software provided by JAKA. It allows developers to build custom functions based on the AddOn API and integrate them into the robot operating system. An AddOn can implement functions such as task scheduling, data acquisition, and communication with external devices.

Development Environment Setup

Hardware Requirements

  • An industrial computer capable of running the JAKA control system

  • Optional: Hardware interfaces for connecting external sensors or actuators, such as serial ports and Ethernet ports

Software Dependencies

  • Operating system: Debian 9 (JAKA robot V1.7.2.x controller versions) / Debian 12 (JAKA robot V3.3.x controller versions)

  • Programming language: Python 2.7 (JAKA robot V1.7.2.x controller versions) / Python 3.11 (JAKA robot V3.3.x controller versions) / C++ (select as required by the project)

  • IDE: Visual Studio Code

  • Development tool: jaka-addon-plugin.vsix

Installation

  1. Configure the Python/C++ development environment.

  2. Open Visual Studio Code. In the Extensions view, open the More Actions menu, select Install from VSIX…, and install the jaka-addon-plugin.vsix extension.

AddOn Development Workflow

AddOn File Structure

A standard AddOn package should contain the following directories and files:

jaka_addon/
├── client/                 # Frontend project files for custom webpages (optional)
├── config/                 # Configuration files (names and number are defined by the developer)
├── src                     # Functional modules (C++/Python; names and number are defined by the developer)
├── requirement/            # Installation packages for third-party Python libraries
├── docs/                   # Documentation
├── main.py                 # Main entry point (Python)
├── **_config.ini           # AddOn project configuration file
├── requirement.list        # Dependency list
└── README.md               # AddOn documentation

Core Components

Configuration File (**_config.ini)

The configuration file stores parameters required to start the AddOn, such as the AddOn type, service port, version, and description.

[AddOnInfo]
convention = 2.0
name = JAKA_AddOn
description = "A JAKA AddOn"
version = 1.0
type = 3
portal = 10007
url = http://localhost/JAKA_AddOn/client
languagetype = python
service = Main.py
serviceenabled = 1

[Requirement]
dir = requirement
list = requirement.list
  • AddOnInfo: AddOn information

    • convention: AddOn specification version. Version 2.0 or 3.0 is recommended.

    • name: AddOn name.

    • description: AddOn description.

    • version: AddOn version.

    • type: AddOn type. Available values are 1, 2, and 3:

      • 1: Background-process AddOn.

      • 2: AddOn with a custom service and custom webpage.

      • 3: Composite AddOn with a custom service, custom webpage, and custom commands.

    • portal: AddOn service port. The port is managed and assigned by the JAKA controller and is mainly used for custom webpage access and custom command requests.

    • url: URL used to access the AddOn custom webpage. Format: http://localhost/{AddOn_name}/{frontend_web_path}.

    • languagetype: AddOn development language, depending on the language used by the project. Available values are python, python3, and node-red.

    • service: AddOn service entry file. This file is the startup entry point of the AddOn and is typically main.py.

    • serviceenabled: Specifies whether the AddOn service starts automatically. 1 indicates automatic startup at controller startup; 0 indicates manual startup.

    • Requirement: AddOn dependency list (JAKA robot V3.3.x controller versions).

      • dir: Directory containing AddOn dependency packages, typically requirement.

      • list: File containing the AddOn dependency list, typically requirement.list. This file is generally generated using the pip freeze command.

Entry File (main.py)

The entry file initializes the AddOn logic and handles interaction with the JAKA system.

Example:

import argparse
import shutil

shutil.copy("../grpc_status/libs/jkzuc3.so","./jkzuc3.so")
import jkzuc3 # noqa: E402

def get_token():
    # Get the token
    token = ""
    parse = argparse.ArgumentParser()
    parse.add_argument("-T", "--token", help="token")
    args = parse.parse_args()
    if args.token:
        token = args.token
    return token

def main():
    RobotControl = jkzuc3.command(token=get_token()) # Create the robot control object
    RobotStatus = jkzuc3.stat() # Create the robot status object

    RobotStatus.poll() # Refresh robot status
    ...

if __name__ == "__main__":
    main()

jkzuc3 is an interface provided by JAKA for communication with the JAKA controller. It is typically installed in the AddOn deployment directory by default. When the AddOn starts, copy jkzuc3.so to the AddOn directory before using the interface. When an AddOn is started, the AddOn Manager on the JAKA controller injects a token. The token must be passed when creating the robot control object; otherwise, the connection is treated as an unauthorized login. The token remains valid for the lifetime of the AddOn and automatically becomes invalid when the AddOn exits.

Quick Start with jaka-addon-plugin

  1. Create a development directory for the AddOn.

  2. Open the development directory in Visual Studio Code.

  3. Press Ctrl+Shift+P to open the Command Palette.

  4. Run addon-plugin:new addon to create an AddOn project.

  5. Follow the prompts to enter the required AddOn information.

  6. jaka-addon-plugin generates the basic configuration for the AddOn project.

jkzuc3 API Reference

This section describes the APIs provided by the JAKA controller and how to use them.

Example version: grpc_status v1.5.3

Data Structures

# Extended I/O basic configuration
class ExtioConfig:
    submod_name:str   # Extended I/O name
    submod:int        # Unique identifier of the extended I/O in the controller

# External axis status
class ExtAxisStatus:
    is_powered:bool   # Whether power is on
    is_powering:bool  # Whether power-on is in progress`
    is_enabled:bool   # Whether the axis is enabled
    is_enabling:bool  # Whether enabling is in progress
    is_inpos:bool     # Whether the axis is in position
    is_on_limit:bool  # Whether the axis has reached a limit
    pos_cmd:float     # Commanded axis position
    pos_fdb:float     # Axis position feedback
    x:float           # Axis position X
    y:float           # Axis position Y
    z:float           # Axis position Z
    a:float           # Axis position A
    b:float           # Axis position B
    c:float           # Axis position C

# External axis group status
class ExtGroupStatus:
    group_id:int      # Axis group ID
    is_powered:bool   # Whether power is on
    is_enabled:bool   # Whether the group is enabled

Robot Control Class (jkzuc3.command)

  • Create a robot control object

import jkzuc3
RobotControl = jkzuc3.command(hostname="host.docker.internal",token="")
  • Shut down the controller

jkzuc3.command.shutdown() -> int:...
jkzuc3.command.set_digital_output(type:int, index:int, value:bool ,submod=0)->int:...
jkzuc3.command.set_analog_output(type:int, index:int, value:float ,submod=0)->int:...
  • Get the extended I/O configuration list

jkzuc3.command.get_extio_config()->list[ExtioConfig]:...
  • Run a program

    • program_name: Program name.

jkzuc3.command.program_run(program_name:str)->int:...
  • Pause a program

jkzuc3.command.program_pause()->int:...
  • Resume a program

jkzuc3.command.program_resume()->int:...
  • Stop a program

jkzuc3.command.program_abort()->int:...
  • Set the program speed override

    • rapid_rate: Speed override. Range: 0-1, corresponding to 0%-100%.

jkzuc3.command.set_rapidrate(rapid_rate:float)->int:...
  • Set Manual/Auto mode

    • mode: Operating mode. 0 - Manual mode; 1 - Auto mode.

jkzuc3.command.set_automanualmode(mode:int)->int:...
  • Forward kinematics

jkzuc3.command.kine_forward(joint_pos:list[float])->list[float]:...
  • Inverse kinematics

jkzuc3.command.kine_inverse(ref_pos:list[float],cartesian_pose:list[float])->list[float]:...
  • Jog interface

    • aj_num: Motion-axis index. For Cartesian motion, the corresponding axes are x, y, z, a, b, and c; for joint motion, the corresponding joints are 1-6.

    • move_mode: Motion mode. 0 - absolute motion; 1 - continuous motion; 2 - relative motion.

    • coord_type: Motion coordinate system. 0 - joint coordinate system; 1 - user coordinate system; 2 - tool coordinate system.

    • vel_cmd: Motion velocity.

    • pos_cmd: Motion position.

Jog commands must be sent continuously to keep the interface active. Otherwise, the controller treats the command stream as interrupted and stops the motion. A 10 ms command cycle is recommended.

jkzuc3.command.jog(aj_num:int,move_mode:int,coord_type:int,vel_cmd:float,pos_cmd:float)->int:...
  • Move to a target position in joint space

jkzuc3.command.joint_move(joint_pos:list[float],speed:float)->int:...
  • Move linearly to a target position

jkzuc3.command.linear_move(end_pos:list[float],speed:float)->int:...
  • Exit collision protection mode

    • intid: Internal robot arm ID used for multi-arm control. For a single-arm system, set intid=0. jkzuc3.command.exit_protect(intid:int)->int:...

  • Switch the tool coordinate system ID

jkzuc3.command.set_tool_id(intid:int)->int:...
  • Set tool coordinate system parameters

jkzuc3.command.set_multi_tool_offsets(tool_offsets:list[float],method:int,id:int,name:str)->int:...
  • Get the current tool coordinate system parameters

jkzuc3.command.get_current_tool_offsets(self)->list[float]:...
  • Switch the user coordinate system ID

jkzuc3.command.set_user_id(intid:int)->int:...
  • Set user coordinate system parameters

jkzuc3.command.set_multi_user_offsets(user_offsets:list[float],method:int,id:int,name:str)->int:...
  • Get the current user coordinate system parameters

jkzuc3.command.get_current_user_offsets(self)->list[float]:...
  • Enable an external axis

    • ext_id: External axis ID. Default: 0.

jkzuc3.command.ExtEnable(ext_id:int=0) -> int:...
  • Disable an external axis

    • ext_id: External axis ID. Default: 0.

jkzuc3.command.ExtDisable(ext_id:int=0) -> int:...
  • Jog an external axis

    • ext_id: External axis ID. Default: 0.

    • vel_scale: Jog speed scale. Range: 0-10, corresponding to 0%-1000%.

    • is_abs: Jog mode. 0 - relative jog; 1 - absolute jog.

    • step: Jog step. Range: 0.1-1000.

jkzuc3.command.ExtJog(ext_id:int = 0,vel_scale:float=2,is_abs:int=1,step:float=1) -> int:...

Robot Status Object (jkzuc3.stat)

class stat:
    joint_position: list[float]       # Joint position
    position:list[float]              # Cartesian position
    errtype:int                       # Error type
    errcode:int                       # Error code
    powered_on:int                    # Whether power is on
    enabled:int                       # Whether the robot is enabled
    protective_stop:int               # Whether the robot is in protective stop
    emergency_stop:int                # Whether the robot is in emergency stop
    interp_state:int                  # Interpolation state
    inpos:int                         # Whether the robot is in position
    rapidrate:float                   # Speed override
    current_tool_id:int               # Current tool ID
    current_user_id:int               # Current user ID
    percentage_mode_level:int         # Operating mode level
    extio_mode:int                    # Extended I/O mode
    installation_angle:list[float]    # Installation angle
    joint_actual_position:list[float] # Actual joint position
    actual_position:list[float]       # Actual Cartesian position
    joint_position:list[float]        # Cartesian joint position
    position_desired:list[float]      # Planned Cartesian position for the next cycle
    cab_din:list[bool]                # Control cabinet DI signals
    cab_dout:list[bool]               # Control cabinet DO signals
    cab_ain:list[float]               # Control cabinet AI signals
    cab_aout:list[float]              # Control cabinet AO signals

    tio_din:list[bool]                # Tool I/O DI signals
    tio_dout:list[bool]               # Tool I/O DO signals
    tio_ain:list[float]               # Tool I/O AI signals
    tio_aout:list[float]              # Tool I/O AO signals

    extio_din:list[bool]              # Extended I/O DI signals
    extio_dout:list[bool]             # Extended I/O DO signals
    extio_ain_uint:list[int]          # Extended I/O unsigned-integer AI signals
    extio_ain_int:list[int]           # Extended I/O signed-integer AI signals
    extio_ain_float:list[float]       # Extended I/O floating-point AI signals
    extio_aout_uint:list[int]         # Extended I/O unsigned-integer AO signals
    extio_aout_int:list[int]          # Extended I/O signed-integer AO signals
    extio_aout_float:list[float]      # Extended I/O floating-point AO signals

    mb_slave_din:list[bool]           # Modbus slave DI signals
    mb_slave_dout:list[bool]          # Modbus slave DO signals
    mb_slave_ain_uint:list[int]       # Modbus slave unsigned-integer AI signals
    mb_slave_ain_int:list[int]        # Modbus slave signed-integer AI signals
    mb_slave_ain_float:list[float]    # Modbus slave floating-point AI signals
    mb_slave_aout_uint:list[int]      # Modbus slave unsigned-integer AO signals
    mb_slave_aout_int:list[int]       # Modbus slave signed-integer AO signals
    mb_slave_aout_float:list[float]   # Modbus slave floating-point AO signals

    ext_axis_num:int                      # Number of external axes
    ext_axis_status:list[ExtAxisStatus]   # External axis status
    ext_group_num:int                     # Number of external axis groups
    ext_group_status:list[ExtGroupStatus] # External axis group status

    # Refresh
    def poll(self, mode=0) -> int: ...

Custom Command Development

A custom command is a command developed by a developer for specific requirements in compliance with JAKA Script rules, in addition to the standard programming commands provided in the JAKA App.

Purpose of Custom Commands

When a new third-party tool is connected to the robot flange, or when the robot is used for a specific process, developers may need to create complex command sequences and configure numerous parameters in the JAKA App programming interface. Such configurations can be difficult to create and reuse. Custom commands allow these commands and parameters to be encapsulated into an intuitive, easy-to-use command block, reducing configuration time and improving programming efficiency.

Custom Command Workflow

  1. Coboπ generates a command block from the custom command description file.

  2. In the programming interface, the user drags the custom command into the program.

  3. When the program is saved, Coboπ sends a GET request to the AddOn service based on the URL specified in each custom command description file.

  4. The GET request passes the parameters in the command block to the AddOn service. The AddOn service generates a JKS script based on the parameters and returns it to the App.

  5. Coboπ appends the JKS script returned by the AddOn service to the main program file and saves the program.

Custom Command Design

Because defining custom commands directly in the AddOn framework is relatively complex, jaka-addon-plugin provides a graphical editor for custom command design. Developers can define the custom command description in the visual editor. After saving the configuration, refer to 7. AddOn Deployment and Debugging to package the project and import the AddOn package into the JAKA App. The designed custom command can then be refreshed and displayed in the Programming interface.

Custom Command Design Procedure

  1. Open the AddOn development directory in Visual Studio Code.

  2. Press Ctrl+Shift+P to open the Command Palette.

  3. Run addon-plugin:open scratch editor to open the custom command design interface.

  4. Follow the UI prompts and configure the command name, appearance, text, command parameters, and other properties as required.

  5. After the command is saved, jaka-addon-plugin generates the custom graphical command description file ./CustomCommand.json in the development directory.

  6. Run addon-plugin:make custom programs or addon-plugin:build addon. jaka-addon-plugin automatically scans ./CustomCommand.json in the current AddOn development directory and generates the standard custom graphical command description file ./OldToNew_CustomPrograms.json.

The ./CustomCommand.json configuration file can contain descriptions for multiple custom command blocks, including the UI style, input parameters, type identifiers, and other properties of each block.

./OldToNew_CustomPrograms.json is the standard description file loaded and used by the controller. It contains information such as the globally unique identifier of each custom graphical command, the complete rendering configuration, and the AddOn service route jksUrl.

Command Block List

After you run addon-plugin:open scratch editor, the Command Block List is displayed first. This page lists all custom command blocks created in the current AddOn project in a table and provides operations for creating, editing, and deleting blocks.

The Command Block List contains the following columns:

Column

Description

Name

Identifier of the custom command block. Letters, numbers, and underscores are recommended.

Type

Command block type. The default is “statement”.

Language

Default language of the command block, such as zh (Chinese), en (English), or ja (Japanese).

Fields

Number of parameters (properties) contained in the command block.

Actions

Provides Edit and Delete actions.

Click Create New Block in the upper-right corner to open the custom command editor. For an existing command block, click Edit in the corresponding row to edit it, or click Delete to remove it.

Command Block Editor

After you click Create New Block or Edit, the command block editor opens. The interface consists of a preview pane on the left and a configuration panel on the right.

Preview pane (Edit Block):

  • The preview pane uses a grid background and displays the visual appearance of the command block in real time.

  • The command block is displayed as a colored shape with rounded corners. The shape depends on the command block type.

  • Zoom controls are provided on the right side of the preview pane, including zoom in, zoom out, and center view, allowing developers to inspect the block in detail.

Configuration panel:

The configuration panel on the right contains the following sections from top to bottom:

(1) Basic Command Information

Setting

Description

Name

Unique identifier of the command block. A combination of letters, numbers, and underscores is recommended, for example, commandtest or New_Block.

Command Block Type

Determines the return type of the command block. See Command Block Types below.

Color

Display color of the command block in the programming interface. Set the color using the color picker.

Command UI

Optional configuration used to associate the command with an AddOn custom webpage.

Language

Default language of the command block. Supported languages are Chinese (zh), English (en), and Japanese (ja).

(2) Command Block Types

Based on the result returned after command execution, command blocks are divided into the following five types. Each type has a different shape:

Type

Shape

Description

Statement (statement)

Rectangular block with notches (standard block shape)

Does not return a value and executes as an independent statement. This is the most commonly used command type.

Boolean (boolean)

Diamond

Returns a Boolean value (true/false) and can be embedded in a conditional expression.

String (string)

Oval

Returns a string and can be used as a parameter of another command.

Number (number)

Oval

Returns a numeric value and can be used as a numeric parameter of another command.

Array (array)

Oval

Returns a numeric array and can be used as an array parameter of another command.

Note: A statement block (statement) performs an operation without returning a value. The other four types are value blocks (value) that return a value of the corresponding type and can be used as parameters in other commands.

(3) Command Parameters (Properties)

Command parameters are configured in a table. Each parameter represents an input item on the command block. The parameter table contains the following columns:

Column

Description

Property Name

Parameter identifier. It is passed to the AddOn service as the parameter key in a GET request. Use a meaningful English name.

Type

Input type of the parameter. See Parameter Types below.

Default Value

Initial value of the parameter. Text parameters support multilingual values (zh/en/ja); other parameter types use a single value.

Hidden

Toggle that hides the parameter in the programming interface when enabled. The parameter is still passed to the AddOn service.

Actions

Provides a Delete button for removing the parameter.

Click + in the upper-right corner of the configuration panel to add a parameter row.

Parameter Types:

Type

Description

Default Value

Text (text)

Static label text displayed on the command block. Supports multilingual configuration (zh/en/ja).

None

Boolean (boolean)

Boolean input displayed as a drop-down list in the programming interface.

false

String (string)

String input. The user can enter text or drag a string variable into the input in the programming interface.

Empty string

Number (number)

Numeric input. The user can enter a number or drag a numeric variable into the input in the programming interface.

0

Array (array)

Array input. The user can drag an array variable into the input in the programming interface.

Default values are not supported

Dropdown (dropdown)

Drop-down list. An option list must be configured.

First option

Custom Command Design Example - Addition Command

The following example uses an Addition command to illustrate the complete custom command design process.

Design objective: Create an addition command block that accepts two numeric inputs, calculates their sum, and outputs the result.

Step 1: Configure the basic command information

  • Name: commandtest

  • Command Block Type: Statement (statement), because the addition result is output through a variable and the command itself does not need to return a value

  • Color: Select a turquoise color, such as #64f2c7

  • Language: Chinese (zh)

Step 2: Configure command parameters

The addition command requires five parameters. Configure them from left to right as follows:

No.

Property Name

Type

Default Value

Description

1

arg_1_rzicg2

Text (text)

加法指令

Title label of the command block, displayed at the far left of the block.

2

number1

String (string)

(empty)

First addend input. The user can enter a value or drag a variable into the input.

3

number2

Number (number)

0

Second addend input. The user can enter a value or drag a variable into the input.

4

resultdfsf

Text (text)

结果:

Result label indicating the location of the output value.

5

result

Number (number)

0

Output variable for the calculation result. The AddOn service writes the calculated result to this variable.

Step 3: Preview and save the command block

The appearance of the command block is updated in real time in the preview pane on the left. The block is displayed using the configured color. Text parameters are displayed directly on the block as labels, while string and number parameters are displayed as editable round input ports.

After confirming that the configuration is correct, click OK in the lower-right corner to save the command block. Click Cancel to discard the current changes.

Step 4: Generate the description file

After the command block is saved, jaka-addon-plugin generates ./CustomCommand.json in the development directory. The following is an example of the file structure:

{
  "id": "block_1778750188735",
  "name": "commandtest",
  "kind": "statement",
  "output": "shape_statement",
  "color": "#64f2c7",
  "lang": "zh",
  "fields": [
    {
      "label": "arg_1_rzicg2",
      "type": "text",
      "defaultValue": { "zh": "加法指令", "en": "", "ja": "" },
      "hidden": false
    },
    {
      "label": "number1",
      "type": "number",
      "defaultValue": "0",
      "hidden": false
    },
    {
      "label": "number2",
      "type": "number",
      "defaultValue": "0",
      "hidden": false
    },
    {
      "label": "resultdfsf",
      "type": "text",
      "defaultValue": { "zh": "结果:", "en": "", "ja": "" },
      "hidden": false
    },
    {
      "label": "result",
      "type": "number",
      "defaultValue": "0",
      "hidden": false
    }
  ],
  "openUrl": "",
  "selectedType": "statement"
}

The fields are described below:

Field

Description

id

Unique command block ID generated automatically by the system.

name

Command block name corresponding to Name in the configuration.

kind

Command block category. statement indicates a statement block; value indicates a value block.

output

Output shape. shape_statement corresponds to a statement block; output_string, output_number, output_boolean, and output_array correspond to string, number, Boolean, and array blocks, respectively.

color

Command block color in hexadecimal format.

lang

Default language.

fields

Parameter list. Each parameter contains label (property name), type (type), defaultValue (default value), and hidden (whether the parameter is hidden).

openUrl

Optional URL of the associated AddOn custom webpage.

selectedType

Selected command block type identifier.

Next, run addon-plugin:make custom programs or addon-plugin:build addon to convert CustomCommand.json into the standard controller-readable description file ./OldToNew_CustomPrograms.json. This file contains information such as the globally unique identifier (BLOCK_TYPE), complete rendering configuration (JAKA_BLOCK_DATA), and AddOn service route (jksUrl) for each command.

Note: The jksUrl format is connected_robot/{command_block_name}. The AddOn service must provide a corresponding GET route in Flask to process command requests. For example, if the command name is commandtest, the Flask route should be /commandtest.

Multilingual Text Configuration

To support multilingual applications, text (text) parameters provide Chinese (zh), Japanese (ja), and English (en) options for their default values. In CustomCommand.json, the defaultValue of a text parameter is stored as an object containing the text for each language:

"defaultValue": {
  "zh": "加法指令",
  "en": "Addition",
  "ja": "加法命令"
}

When the system language is changed in Coboπ, the text displayed on the command block automatically switches to the corresponding language. If no text is configured for a language (the value is empty), no text is displayed for that language.

For non-text parameters, such as strings and numbers, defaultValue is a single string value and does not support multilingual configuration.

Hidden Parameters

Each parameter provides a Hidden toggle. When Hidden is enabled, the parameter is not displayed on the command block in the Coboπ programming interface. However, when the program is saved, the parameter value is still passed to the AddOn service through the GET request.

Hidden parameters are useful in the following scenarios:

  • Internal parameters required by the AddOn service but not intended to be modified by users

  • Fixed configuration items

  • Version identifiers, feature switches, and similar parameters

Processing Custom Commands in an AddOn Service

During custom command processing, the AddOn service receives GET requests from the JAKA App and generates the corresponding JKS script based on the request parameters. The following sections describe the implementation procedure and technical details.

Handling GET Requests with Flask

To process GET requests from Coboπ, using the Python Flask framework to create an HTTP service is recommended. Flask is lightweight and flexible and is suitable for quickly building RESTful APIs.

When creating the Flask service, use the port number specified in the AddOn configuration file.

import configparser
import flask


FlaskServer = flask.Flask(__name__)
@FlaskServer.route('/myCommand', methods=['GET'])
def myCommand():
  jks = "# This is a test command\n"
  return {
    "error_code":0,
    "jks_str":[jks],
    "error_msg": ""
  }

addonConfig = configparser.ConfigParser()
addonConfig.read("./addon_config.ini")
flask_port = addonConfig.getint("AddOnInfo", "portal")

FlaskServer.run(host='0.0.0.0', port=flask_port)

Parameters in a GET request use the following format:

{
  "param1": { "value": "value1", "type": 0 },
  "param2": { "value": "value2", "type": 1 }
}

If the parameter type is 0, the parameter value is a string containing the value entered by the user in the custom command block.

If the parameter type is 1, the parameter value is the name of a JKS variable corresponding to the variable inserted by the user into the custom command block.

JKS Script Generation

JKS (JAKA Script) is the scripting language used by JAKA robots. When generating a JKS script, consider the following:

  • Syntax: Ensure that the generated script complies with JKS syntax.

  • Parameter mapping: Correctly map the parameters in the GET request to JKS commands.

  • Dynamic logic: Generate different script content according to different parameter combinations.

GET Response Format

The JAKA App expects the AddOn service to return response data in a specific format. The returned data must be in JSON format:\

{
  "error_code": 0,
  "errormsg": "",
  "jks_str": {
    "jks": [],
    "jks_return": ""
  },
  "line": []
}
  • error_code: Error code. 0 indicates success; a non-zero value indicates failure. To avoid conflicts with Coboπ error codes, use an error code greater than 0xAF0000.

  • errormsg: Error message displayed to the user.

  • jks_str: JKS script object used to store the generated JKS script.

    • jks_str: The JKS script string itself. It must be returned in a list.

    • return_value: Name of the return variable. This is used for number, string, and array custom commands to specify a JKS variable as the result of the custom command during execution.

  • line: Line numbers in the JKS script, determined by counting newline characters ("\n").

AddOn Custom Webpage Development

An AddOn can provide a custom webpage that allows users to configure AddOn parameters.

Custom Webpage Development

Vue is recommended for custom webpage development. Vue is a web application framework that provides a comprehensive component-based approach for building user interfaces.

Communication with AddOn Custom Services

For security reasons, the AddOn custom service port cannot be accessed directly from an external client. Therefore, requests from a custom webpage to the AddOn service must be routed through the proxy endpoint.

URL format: https://${robot_ip}/addonApi/{port}/${route}

Because the AddOn port is configured by the AddOn Manager, the custom webpage must first obtain the port number assigned to the AddOn. The AddOn configuration file can be retrieved through the proxy. Access the following URL:

https://${robot_ip}/addon/${addon_name}/${addon_configuration_file}

Example:

import axios from "axios";

const INIcontext = await axios.get(
  `https://${robot_ip.value}/addon/AddOnDemo/AddOnDemo_config.ini`,
);
const portMatch = INIcontext.data.match(/portal\s*=\s*(\d+)/);
const Port = portMatch[1];

Cross-Origin Requests

When developing an AddOn custom webpage, browser security policies prevent the webpage from directly accessing an AddOn service on a different origin or port. This results in a cross-origin request restriction.

The following methods can be used to handle cross-origin requests:

Handle OPTIONS Preflight Requests

Before sending a cross-origin request, modern browsers may first send an OPTIONS request, also known as a preflight request, to verify whether the server permits the cross-origin request. The server must respond correctly to the OPTIONS request before the actual request can be sent successfully.

Implementation:

In a Flask-based AddOn service, CORS (Cross-Origin Resource Sharing) middleware can be added to support OPTIONS requests. The following example uses the Flask-CORS extension:

import configparser
from flask import Flask, request
from flask_cors import CORS

app = Flask(__name__)
CORS(app, supports_credentials=True, resources=r'/*')  # Enable global CORS support

@app.route('/myMethod', methods=['POST', 'OPTIONS'])
def myMethod():
    if request.method == 'OPTIONS':
        # Handle the OPTIONS preflight request
        return '', 200
    else:
        # Handle the actual GET request
        jks = "# This is a test command\n"
        return {
            "error_code": 0,
            "jks_str": [jks],
            "error_msg": ""
        }

if __name__ == '__main__':
    addonConfig = configparser.ConfigParser()
    addonConfig.read('addon_config.ini')
    app.run(host='0.0.0.0', port=addonConfig.getint("AddOnInfo","portal"))

Key points:

  • CORS(app): Enables global CORS support and automatically handles OPTIONS requests.

  • For an OPTIONS request, returning an empty response body with HTTP status code 200 is sufficient.

  • Place the actual application logic in the branch that handles non-OPTIONS requests.

Set Response Headers Manually

If Flask-CORS is not used, CORS response headers can be set manually:

import configparser
from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route('/myCommand', methods=['GET', 'OPTIONS'])
def myCommand():
    # Set CORS response headers
    response_headers = {
        'Access-Control-Allow-Origin': '*',  # Allow requests from all origins
        'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',  # Allowed methods
        'Access-Control-Allow-Headers': 'Content-Type'  # Allowed request headers
    }

    if request.method == 'OPTIONS':
        # Handle the OPTIONS preflight request
        return '', 200, response_headers
    else:
        # Handle the actual GET request
        jks = "# This is a test command\n"
        return jsonify({
            "error_code": 0,
            "jks_str": [jks],
            "error_msg": ""
        }), 200, response_headers

if __name__ == '__main__':
    addonConfig = configparser.ConfigParser()
    addonConfig.read('addon_config.ini')
    app.run(host='0.0.0.0', port=addonConfig.getint("AddOnInfo","portal"))

Key response headers:

  • Access-Control-Allow-Origin: Specifies the origins that are allowed to access the resource (* allows all origins).

  • Access-Control-Allow-Methods: Specifies the allowed HTTP methods.

  • Access-Control-Allow-Headers: Specifies the allowed request header fields.

AddOn Deployment and Debugging

AddOn Packaging

Option 1:

  1. After AddOn development is complete, build the frontend project and place the generated files in the AddOn directory.

  2. Compress the AddOn directory into a tar.gz archive.

Option 2:

  1. When jaka-addon-plugin creates an AddOn, it automatically generates the packaging configuration file package_log_pro.json, which contains the AddOn packaging configuration.

  2. Run addon-plugin:make new addon again. If jaka-addon-plugin detects that the current working directory is an AddOn development directory, it automatically scans the Python scripts and adds the relevant files to the packaging configuration.

  3. Check package_log_pro.json and make sure the no_transform and transform parameters include all files to be packaged. If any files are missing, adding them manually to no_transform is recommended.

  4. Run addon-plugin:build addon to generate a tar.gz package in the ./output directory of the AddOn project.

AddOn Deployment

  1. Open Coboπ and log in to the robot.

  2. Upload the AddOn package from the application interface.

AddOn Debugging

While an AddOn is running, the AddOn Manager automatically creates a log directory under the AddOn directory.

The directory contains the following two log files:

  • AddOnerrlog.log: Records exceptions raised by the AddOn.

  • AddOnlog.log: Records AddOn runtime logs.

The log files can be downloaded in a browser through the proxy.

URLs: https://${robot_ip}/addon/${AddOn_name}/log/AddOnerrlog.log and https://${robot_ip}/addon/${AddOn_name}/log/AddOnlog.log

Appendix

Control System I/O Types

I/O Type

Type Code

Description

Control Cabinet I/O

0

Panel I/O; compatible with Modbus slave I/O and PROFINET slave I/O

TIO

1

Depends on the TIO version

Modbus Extended I/O

2

The controller operates as the Modbus master

Relay I/O

3

Currently, only CAB V3 supports D0

Modbus Slave I/O

4

Legacy Modbus slave I/O is indexed from 0

PROFINET Slave I/O

5

Legacy PROFINET slave I/O is indexed from O

EtherNet/IP Slave I/O

6

Newly added EtherNet/IP slave I/O is indexed from 0