AddOn 插件开发技术文档
概述
本文档旨在为开发者提供节卡(JAKA)机器人 AddOn 插件的开发指导,包括插件的基本结构、开发流程、API 使用说明以及常见问题解决方案。
适用对象
节卡机器人二次开发工程师
第三方插件开发者
系统集成工程师
插件简介
节卡 AddOn 是一种可扩展的功能模块,允许开发者基于 AddOn API 开发自定义功能,并集成到 JAKA 机器人的控制系统中。插件可以实现诸如任务调度、数据采集、外部设备通信等功能。
开发环境准备
硬件要求
支持运行 JAKA 控制系统的工业计算机
可选:连接外部传感器或执行器的硬件接口(如串口、网口等)
软件依赖
操作系统:Debian 9(节卡机器人 V1.7.2.x 控制版本)/ Debian 12(节卡机器人 V3.3.x 控制器版本)
编程语言:Python 2.7(节卡机器人 V1.7.2.x 控制版本)/ Python 3.11(节卡机器人 V3.3.x 控制器版本)/ C++(根据项目需求选择)
IDE 工具:Visual Studio Code
开发工具:jaka-addon-plugin.vsix
安装步骤
配置 Python/C++ 开发环境
打开Visual Studio Code,在扩展中栏的更多选择中选择从vsix安装...,安装jaka-addon-plugin.vsix扩展。
插件开发流程
插件目录结构
一个标准的 AddOn 插件应包含以下目录和文件:
::
jaka_addon/
├── client/ # AddOn前端网页文件(可选)
├── config/ # 配置文件目录 (名称和数量由开发者自由定义)
├── src # 功能模块(C++/Python)(名称和数量由开发者自由定义)
├── requirement/ # python第三方库安装包
├── docs/ # 文档目录
├── main.py # 主程序入口(Python)
├── **_config.ini # AddOn项目配置文件
├── requirement.list # 依赖库列表
└── README.md # 插件说明文档
核心组件说明
配置文件(**_config.ini)
用于存储插件启动所需的参数,例如 AddOn 插件类型、端口号、版本、插件描述等。
::
[AddOnInfo]
convention = 2.0
name = JAKA_AddOn
description = "A JAKA AddOn plugin"
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:插件信息
convention:插件规范版本号,推荐使用2.0或3.0
name:插件名称
description:插件描述
version:插件版本号
type:插件类型,可选值有1、2、3。 1表示插件是后台进程类型插件,2表示插件是带前端网页的服务插件,3表示插件带前端服务又包含自定义指令。
portal:插件服务端口号,该端口号有JAKA控制器管理分配,主要用于处理前端访问和自定义指令请求
url:插件服务端URL,用于前端访问。格式为
http://localhost/{AddOn_name}/{前端网页路径}languagetype:插件语言类型,取决于项目实际开发语言,可选值有python、 python3 、node-red。
service:插件服务入口文件,该文件为插件的启动入口,通常为
main.py。serviceenabled:插件服务是否自启动,1表示开机自启动,0表示手动启动。
Requirement:插件依赖库列表(节卡机器人V3.3.x控制器版本)
dir:插件依赖库目录,该目录为插件依赖的库文件目录,通常为requirement。
list:插件依赖库列表,该列表为插件依赖的库文件列表,通常为requirement.list。一般由pip freeze命令生成。
入口文件 (main.py)
负责初始化插件逻辑并与 JAKA 系统交互。 示例代码如下:
import argparse
import shutil
shutil.copy("../grpc_status/libs/jkzuc3.so","./jkzuc3.so")
import jkzuc3 # noqa: E402
def get_token():
# 获取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()) # 创建机器人控制对象
RobotStatus = jkzuc3.stat() # 创建机器人状态对象
RobotStatus.poll() # 刷新机器人状态
...
if __name__ == "__main__":
main()
jkzuc3 是JAKA提供的与JAKA控制器交互的接口, 通常默认安装在AddOn部署目录中,在启动时主动将jkzuc3.so复制到AddOn插件目录中即可使用。在启动插件时,JAKA控制器中的AddOn Manager会注入一个token。在传教机器人控制器对象时,需要传入token,否则将被视为非法登录。token的生命周期与插件的生命周期一致,插件退出时,token将自动失效。
使用jaka-addon-plugin快速开始
创建AddOn插件的开发目录
Visual Studio Code打开此开发目录
通过
Ctrl+Shift+P打开命令面板,输入以下命令:输入命令
addon-plugin:new addon创建AddOn项目 ##根据提示,按照要求填写插件信息。
jaka-addon-plugin 会生成一个插件项目的基本配置。
jkzuc3 API 使用说明
本节描述了JAKA控制器提供的API接口,以及如何使用这些接口。 示例版本:grpc_status v1.5.3
数据结构
# 扩展IO基本信息配置
class ExtioConfig:
submod_name:str # 扩展IO名称
submod:int # 扩展IO在控制器中的唯一标识
# 外部轴状态
class ExtAxisStatus:
is_powered:bool # 是否已上电
is_powering:bool # 是否正在上电`
is_enabled:bool # 是否已使能
is_enabling:bool # 是否正在使能
is_inpos:bool # 是否运动已到位
is_on_limit:bool # 是否已到达限位
pos_cmd:float # 轴指令位置
pos_fdb:float # 轴反馈位置
x:float # 轴位置X
y:float # 轴位置Y
z:float # 轴位置Z
a:float # 轴位置A
b:float # 轴位置B
c:float # 轴位置C
# 外部轴组状态
class ExtGroupStatus:
group_id:int # 轴组ID
is_powered:bool # 是否已上电
is_enabled:bool # 是否已使能
机器人控制类(jkzuc3.command)
创建机器人控制对象
import jkzuc3
RobotControl = jkzuc3.command(hostname="host.docker.internal",token="")
关机
jkzuc3.command.shutdown() -> int:...
设置DO信号
type:IO类型,参考附录控制-系统IO类型
index:IO索引
value:DO信号值
设置AO信号
type:IO类型,参考附录控制-系统IO类型
index:IO索引
value:AO信号值
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:...
获取扩展IO配置列表
jkzuc3.command.get_extio_config()->list[ExtioConfig]:...
运行程序
program_name:程序名称
jkzuc3.command.program_run(program_name:str)->int:...
暂停程序
jkzuc3.command.program_pause()->int:...
恢复程序
jkzuc3.command.program_resume()->int:...
停止程序
jkzuc3.command.program_abort()->int:...
设置程序运行倍率
rapid_rate:倍率,取值范围:
0[STRIKEOUT:1,对应比例关系:0%]100%##
jkzuc3.command.set_rapidrate(rapid_rate:float)->int:...
设置手自动模式
mode:模式,0-手动模式,1-自动模式
jkzuc3.command.set_automanualmode(mode:int)->int:...
运动学正解
jkzuc3.command.kine_forward(joint_pos:list[float])->list[float]:...
运动学逆解
jkzuc3.command.kine_inverse(ref_pos:list[float],cartesian_pose:list[float])->list[float]:...
示教运动接口
aj_num:运动轴索引号,空间运动对应为x,y,z,a,b,c,关节运动对应的1~6关节
move_mode:运动模式,0-绝对运动,1-连续运动,2-相对运动
coord_type:运动坐标系类型,0-关节坐标系,1-用户坐标系,2-工具坐标系
vel_cmd:运动速度
pos_cmd:运动位置
jog运动需持续下发以保证接口存活,否则控制器将认为指令中断而停止运动。下发周期推荐10ms。
jkzuc3.command.jog(aj_num:int,move_mode:int,coord_type:int,vel_cmd:float,pos_cmd:float)->int:...
关节运动到目标位置
jkzuc3.command.joint_move(joint_pos:list[float],speed:float)->int:...
直线运动到目标位置
jkzuc3.command.linear_move(end_pos:list[float],speed:float)->int:...
退出碰撞保护模式
intid:内部机械臂ID,用于多臂场景控制,单臂场景下 intid=0 jkzuc3.command.exit_protect(intid:int)->int:...
切换工具坐标系ID
jkzuc3.command.set_tool_id(intid:int)->int:...
设置工具坐标系参数
jkzuc3.command.set_multi_tool_offsets(tool_offsets:list[float],method:int,id:int,name:str)->int:...
获取当前工具坐标系参数
jkzuc3.command.get_current_tool_offsets(self)->list[float]:...
切换用户坐标系ID
jkzuc3.command.set_user_id(intid:int)->int:...
设置用户坐标系参数
jkzuc3.command.set_multi_user_offsets(user_offsets:list[float],method:int,id:int,name:str)->int:...
获取当前用户坐标系参数
jkzuc3.command.get_current_user_offsets(self)->list[float]:...
外部轴使能
ext_id:外部轴ID, 默认为0
jkzuc3.command.ExtEnable(ext_id:int=0) -> int:...
外部轴下使能
ext_id:外部轴ID, 默认为0
jkzuc3.command.ExtDisable(ext_id:int=0) -> int:...
外部轴 jog
ext_id:外部轴ID, 默认为0
vel_scale: jog速度比例,取值范围:
0[STRIKEOUT:10,对应比例关系:0%]1000%##is_abs: jog模式,0-相对 jog,1-绝对
step: jog步进,取值范围:0.1~1000
jkzuc3.command.ExtJog(ext_id:int = 0,vel_scale:float=2,is_abs:int=1,step:float=1) -> int:...
机器人状态对象(jkzuc3.stat)
class stat:
joint_position: list[float] # 关节位置
position:list[float] # 笛卡尔位置
errtype:int # 错误类型
errcode:int # 错误码
powered_on:int # 是否已上电
enabled:int # 是否已使能
protective_stop:int # 是否处于保护停止
emergency_stop:int # 是否处于急停
interp_state:int # 插补状态
inpos:int # 是否已到位
rapidrate:float # 运行倍率
current_tool_id:int # 当前工具ID
current_user_id:int # 当前用户ID
percentage_mode_level:int # 运行模式等级
extio_mode:int # 外部IO模式
installation_angle:list[float] # 安装角度
joint_actual_position:list[float] # 关节实际位置
actual_position:list[float] # 笛卡尔实际位置
joint_position:list[float] # 笛卡尔关节位置
position_desired:list[float] # 下一周期笛卡尔规划位置
cab_din:list[bool] # 电控柜DI信号
cab_dout:list[bool] # 电控柜DO信号
cab_ain:list[float] # 电控柜AI信号
cab_aout:list[float] # 电控柜AO信号
tio_din:list[bool] # 工具IO DI信号
tio_dout:list[bool] # 工具IO DO信号
tio_ain:list[float] # 工具IO AI信号
tio_aout:list[float] # 工具IO AO信号
extio_din:list[bool] # 扩展IO DI信号
extio_dout:list[bool] # 扩展IO DO信号
extio_ain_uint:list[int] # 扩展IO 无符号整型AI信号
extio_ain_int:list[int] # 扩展IO 有符号整型AI信号
extio_ain_float:list[float] # 扩展IO 浮点型AI信号
extio_aout_uint:list[int] # 扩展IO 无符号整型AO信号
extio_aout_int:list[int] # 扩展IO 有符号整型AO信号
extio_aout_float:list[float] # 扩展IO 浮点型AO信号
mb_slave_din:list[bool] # Modbus从站DI信号
mb_slave_dout:list[bool] # Modbus从站DO信号
mb_slave_ain_uint:list[int] # Modbus从站无符号整型AI信号
mb_slave_ain_int:list[int] # Modbus从站有符号整型AI信号
mb_slave_ain_float:list[float] # Modbus从站浮点型AI信号
mb_slave_aout_uint:list[int] # Modbus从站无符号整型AO信号
mb_slave_aout_int:list[int] # Modbus从站有符号整型AO信号
mb_slave_aout_float:list[float] # Modbus从站浮点型AO信号
ext_axis_num:int # 外部轴数量
ext_axis_status:list[ExtAxisStatus] # 外部轴状态
ext_group_num:int # 外部轴组数量
ext_group_status:list[ExtGroupStatus] # 外部轴组状态
# 刷新
def poll(self, mode=0) -> int: ...
自定义指令开发
自定义指令是指开发者根据自己的需求,在符合 JAKA 脚本规则的情况下,开发出的除 JAKA App 内标准程序指令之外的其他指令。
自定义指令的作用
当机器人末端连接了新的第三方工具,或是应用于具体工作场景中去操作具体工艺时,往往需要在 JAKA App 编程界面编写繁杂的指令、设置繁多的参数。这一步骤较复杂,且不易于二次复用,所以此时就需要把这些繁、杂、多的指令和参数封装为一条直接易懂、简单易用的指令块,以节约时间成本、提升操作效率。
自定义指令的工作过程
Coboπ通过自定义指令描述文件生成指令块
用户在编程界面中,将自定义指令拖入程序中
在保存程序时,Coboπ根据每个自定义指令描述文件中的URL,向AddOn插件发送GET请求。
在GET请求中,将指令块中的参数发送给AddOn插件,AddOn插件根据参数生成jks脚本,并返回给App。
Coboπ将从AddOn插件返回的jks脚本拼接到主程序文件中,并保存。
自定义指令设计
由于AddOn框架中对自定义指令的描述过于复杂。jaka-addon-plugin新增了对自定义指令的图形化界面设计支持,开发者需要做的是在可视化界面中编辑自定义指令的描述内容,保存后请参考7. 插件部署与调试进行项目压缩和JAKA App导包,随后即可在编程界面刷新出设计的自定义指令
自定义指令的设计步骤
Visual Studio Code打开AddOn插件的开发目录
通过
Ctrl+Shift+P打开命令面板,输入以下命令:输入命令
addon-plugin:open scratch editor进入自定义指令设计界面根据界面提示并按照实际需求编辑自定义指令名称、外观、文本内容和指令参数等信息
保存后,jaka-addon-plugin会在开发目录中生成自定义图形指令的描述配置文件
./CustomCommand.json可以通过jaka-addon-plugin的
addon-plugin:make custom programs或者addon-plugin:build addon自动扫描当前AddOn开发目录的./CustomCommand.json文件,生成自定义图形指令的标准描述文件./OldToNew_CustomPrograms.json
./CustomCommand.json自定义指令块描述配置文件中允许放入多个自定义指令描述,其中包含存储所有自定义编程方块的界面样式、输入参数、类型标识等 ./OldToNew_CustomPrograms.json描述配置文件是控制器正式加载运行标准文件,其中包含自定义图形指令的全局唯一标识、完整渲染配置、后端接口路由jksUrl等
指令块列表管理
执行 addon-plugin:open scratch editor 命令后,首先进入的是指令块列表管理界面。该界面以表格形式展示当前 AddOn 项目中已创建的所有自定义指令块,并提供创建、编辑和删除操作。

指令块列表包含以下列信息:
列名 |
说明 |
|---|---|
名称 |
自定义指令块的标识名称,推荐使用英文字母、数字和下划线命名 |
类型 |
指令块的类型,默认为"指令块" |
语言 |
指令块的默认语言,如 |
字段数 |
指令块中包含的参数(属性)数量 |
操作 |
提供"编辑"和"删除"两个操作按钮 |
点击界面右上角的"创建新块"按钮,即可进入自定义指令的编辑界面。若已有指令块,可点击对应行的"编辑"按钮进入编辑,或点击"删除"按钮移除指令块。
指令块编辑界面
点击"创建新块"或"编辑"按钮后,进入指令块编辑界面。该界面分为左侧预览区和右侧配置面板两部分。

左侧预览区(编辑块):
预览区以网格为背景,实时展示指令块的可视化外观。
指令块以带颜色的圆角图形呈现,图形形状由指令块类型决定。
预览区右侧提供缩放工具按钮(放大、缩小、居中视图),方便开发者查看指令块细节。
右侧配置面板:
右侧配置面板自上而下分为以下区域:
(1)指令基本信息
配置项 |
说明 |
|---|---|
名称 |
指令块的唯一标识名称,推荐使用英文字母、数字和下划线组合,如 |
指令块类型 |
决定指令块的执行返回类型,详见下方"指令块类型"说明 |
颜色 |
指令块在编程界面中的显示颜色,通过颜色选择器设置 |
指令界面 |
可选配置,用于关联指令的前端交互界面 |
语言 |
指令块的默认语言,支持中文(zh)、英语(en)、日语(ja) |
(2)指令块类型说明
根据指令执行后的返回结果,指令块分为以下五种类型,不同类型对应不同的外形:

类型 |
外形 |
说明 |
|---|---|---|
指令块(statement) |
矩形带缺口(标准积木形状) |
无返回值,作为独立语句执行,是最常用的指令类型 |
布尔值(boolean) |
菱形 |
返回布尔值(true/false),可嵌入条件判断中 |
字符串(string) |
椭圆形 |
返回字符串结果,可嵌入到其他指令的参数中 |
数字(number) |
椭圆形 |
返回数字结果,可嵌入到其他指令的数值参数中 |
数组(array) |
椭圆形 |
返回数字数组结果,可嵌入到其他指令的数组参数中 |
说明: 指令块(statement)类型用于执行操作但不需要返回值;其余四种类型均为值类型(value),执行后会产生对应类型的返回值,可在其他指令中作为参数使用。
(3)指令参数(属性)配置
指令参数以表格形式配置,每个参数代表指令块上的一个可输入项。参数表格包含以下列:
列名 |
说明 |
|---|---|
属性名 |
参数的标识名称,在 GET 请求中作为参数键名传递给 AddOn 后端,建议使用有意义的英文命名 |
类型 |
参数的输入类型,详见下方"参数类型"说明 |
默认值 |
参数的初始值。文本类型支持多语言配置(zh/en/ja),其他类型为单值 |
隐藏 |
开关控制,开启后该参数在编程界面中不可见,但仍会传递给后端 |
操作 |
提供"删除"按钮,移除该参数 |
点击配置面板右上角的 "+" 按钮可添加新的参数行。
参数类型说明:
类型 |
说明 |
默认值 |
|---|---|---|
文本(text) |
纯标签文本,用于在指令块上显示说明性文字。支持多语言(zh/en/ja)配置 |
无 |
布尔(boolean) |
布尔值输入,在编程界面中以下拉框形式呈现 |
false |
字符串(string) |
字符串输入,在编程界面中可输入文本或拖入字符串变量 |
空字符串 |
数字(number) |
数值输入,在编程界面中可输入数字或拖入数字变量 |
0 |
数组(array) |
数组输入,在编程界面中可拖入数组变量 |
不支持默认值 |
下拉框(dropdown) |
下拉选择框,需要配置选项列表 |
第一个选项 |
自定义指令设计示例——加法指令
以下以一个"加法指令"为例,完整说明自定义指令的设计过程。

设计目标: 创建一个加法指令块,接收两个数字输入,计算并返回它们的和。
步骤一:配置指令基本信息
名称:
commandtest指令块类型:指令块(statement),因为加法结果通过变量输出,指令本身无需返回值
颜色:选择青绿色(如
#64f2c7)语言:中文(zh)
步骤二:配置指令参数
加法指令共需要5个参数,按从左到右的排列顺序配置如下:
序号 |
属性名 |
类型 |
默认值 |
说明 |
|---|---|---|---|---|
1 |
|
文本(text) |
加法指令 |
指令块的标题标签,显示在指令块最左侧 |
2 |
|
字符串(string) |
(空) |
第一个加数输入,用户可输入数值或拖入变量 |
3 |
|
数字(number) |
0 |
第二个加数输入,用户可输入数值或拖入变量 |
4 |
|
文本(text) |
结果: |
结果标签文字,用于标识输出结果的位置 |
5 |
|
数字(number) |
0 |
计算结果输出变量,AddOn后端会将计算结果写入此变量 |
步骤三:预览与保存
在左侧预览区可以实时查看指令块的外观效果。预览区中,指令块以设定的颜色显示,文本类型的参数作为标签直接显示在指令块上,字符串和数字类型的参数显示为可输入的圆形端口。
确认配置无误后,点击右下角的"确定"按钮保存指令块。点击"取消"则放弃当前修改。
步骤四:生成描述文件
保存后,jaka-addon-plugin 会在开发目录中生成 ./CustomCommand.json 文件。该文件的结构示例如下:
{
"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"
}
各字段说明如下:
字段 |
说明 |
|---|---|
|
指令块的唯一ID,由系统自动生成 |
|
指令块名称,与配置中的"名称"对应 |
|
指令块种类, |
|
输出形状, |
|
指令块颜色,十六进制色值 |
|
默认语言 |
|
参数列表,每个参数包含 |
|
可选,关联的前端界面URL |
|
指令块选中的类型标识 |
随后通过 addon-plugin:make custom programs 或 addon-plugin:build addon 命令,将 CustomCommand.json 转换为控制器可识别的标准描述文件 ./OldToNew_CustomPrograms.json。该文件中包含每条指令的全局唯一标识(BLOCK_TYPE)、完整渲染配置(JAKA_BLOCK_DATA)、后端接口路由(jksUrl)等信息。
注意:
jksUrl的格式为connected_robot/{指令块名称},AddOn 插件需要在 Flask 服务中创建与该名称对应的 GET 路由来处理指令请求。例如指令名称为commandtest,则 Flask 路由应为/commandtest。
多语言文本配置
出于多语言场景考虑,文本类型(text)参数在默认值配置中提供了中文(zh)、日语(ja)、英语(en)三种语言选项。在 CustomCommand.json 中,文本类型的 defaultValue 以对象形式存储各语言版本的文本内容:
"defaultValue": {
"zh": "加法指令",
"en": "Addition",
"ja": "加法命令"
}
当用户在 Coboπ 中切换系统语言时,指令块上显示的文本会自动对应到相应语言的版本。若某种语言未配置内容(留空),则显示为空文本。
非文本类型的参数(如字符串、数字等)的 defaultValue 为单一字符串值,不支持多语言配置。
隐藏参数
每个参数均支持"隐藏"开关。开启隐藏后,该参数在 Coboπ 编程界面的指令块上将不可见,但在保存程序时,该参数的值仍然会通过 GET 请求传递给 AddOn 后端。
隐藏参数适用于以下场景:
需要在后端使用但不希望用户修改的内部参数
固定不变配置项
用于版本标识或功能开关等
AddOn插件处理指令
在自定义指令的工作过程中,AddOn插件需要接收来自JAKA App的GET请求,并根据请求参数生成相应的JKS脚本。以下是具体的实现步骤和技术细节:
使用 flask 框架处理GET请求
为了处理来自Coboπ的GET请求,推荐使用Python的Flask框架搭建HTTP服务。Flask轻量、灵活,适合快速构建RESTful API接口。
在创建Flask服务时,需使用AddOn配置文件中的端口号。
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)
GET请求中的参数格式为:
{
"param1": { "value": "value1", "type": 0 },
"param2": { "value": "value2", "type": 1 }
}
若参数的type为0,则参数值为字符串,内容是用户在自定义指令块中的输入值。 若参数的type为1,则参数值为jks变量名,内容是用户在自定义指令块中放入的变量。
JKS脚本拼接
JKS(JAKA Script)是JAKA机器人使用的脚本语言。在生成JKS脚本时,需注意以下几点:
语法正确性:确保生成的脚本符合JKS语法规则。 参数映射:将GET请求中的参数正确映射到JKS指令中。 动态逻辑:根据不同参数组合生成不同的脚本内容。
GET请求的返回格式
JAKA App期望AddOn插件返回特定格式的响应数据。返回的数据必须是JSON格式:\
{
"error_code": 0,
"errormsg": "",
"jks_str": {
"jks": [],
"jks_return": ""
},
"line": []
}
error_code: 错误码,0表示成功,非0表示失败,为了避免与Coboπ的错误码冲突,请使用大于0xAF0000的错误码。errormsg: 错误信息,用于提示用户。jks_str: JKS脚本对象,用于保存生成的JKS脚本。jks_str: JKS脚本字符串本身,需要放入列表中传回。return_value: 返回变量名,用于数字型、字符串型、数组型的自定义指令,将运行自定义时,某个jks变量视为自定义指令的结果。
line: jks脚本的行号,通过计算换行符"n"的个数确定。
AddOn插件的前端界面开发
插件开发过程中,需要为插件提供相应的前端界面,用于用户配置插件参数。
前端界面开发
我们推荐使用Vue框架开发前端界面。Vue是一个基于Vue.js的Web应用程序开发框架,它提供了一套完整的组件库,用于构建用户界面。
AddOn后端交互
为了安全考虑,AddOn后端的端口号是不能被外部直接访问的。所以,前端界面向后端服务发出的请求,需要通过跨域代理来解决。 URL 格式为:https://${机器人的IP}/addonApi/{port}/${路由方法}
由此,引申出一个新的问题:AddOn的端口号是由AddOn Manager配置的,前端界面如何获取到AddOn的端口号? 其实,可以直接通过跨域代理获取到AddOn插件的配置文件信息。只需要访问https://${机器人的IP}/addon/${addon名字}/${addon配置文件}即可。如:
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];
跨域问题
在开发 AddOn 插件的前端界面时,由于浏览器的安全策略限制,前端页面无法直接访问不同域名或端口的后端服务,这就产生了跨域问题。
为了解决这一问题,通常采用以下方式:
使用 OPTIONS 方法预检请求
现代浏览器在发送跨域请求之前,会先发送一个 OPTIONS 请求(也称为“预检请求”),用于确认服务器是否允许该跨域请求。服务器需要正确响应这个 OPTIONS 请求,才能让后续的实际请求顺利发送。 实现方式: 在 Flask 后端中,可以通过添加 CORS(跨域资源共享)中间件来支持 OPTIONS 请求。以下是使用 Flask-CORS 扩展的示例代码:
import configparser
from flask import Flask, request
from flask_cors import CORS
app = Flask(__name__)
CORS(app, supports_credentials=True, resources=r'/*') # 启用全局 CORS 支持
@app.route('/myMethod', methods=['POST', 'OPTIONS'])
def myMethod():
if request.method == 'OPTIONS':
# 处理 OPTIONS 预检请求
return '', 200
else:
# 处理实际的 GET 请求
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"))
关键点说明:
CORS(app):启用全局跨域支持,自动处理 OPTIONS 请求。
对于 OPTIONS 请求,直接返回空响应体和 200 状态码即可。
实际业务逻辑放在非 OPTIONS 请求的处理分支中。
手动设置响应头
如果不使用 Flask-CORS, 也可以手动设置响应头来支持跨域请求:
import configparser
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route('/myCommand', methods=['GET', 'OPTIONS'])
def myCommand():
# 设置跨域响应头
response_headers = {
'Access-Control-Allow-Origin': '*', # 允许所有来源访问
'Access-Control-Allow-Methods': 'GET, POST, OPTIONS', # 允许的方法
'Access-Control-Allow-Headers': 'Content-Type' # 允许的请求头
}
if request.method == 'OPTIONS':
# 处理 OPTIONS 预检请求
return '', 200, response_headers
else:
# 处理实际的 GET 请求
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"))
关键响应头说明:
Access-Control-Allow-Origin:指定允许访问的源(* 表示允许所有源)。
Access-Control-Allow-Methods:指定允许的 HTTP 方法。
Access-Control-Allow-Headers:指定允许的请求头字段。
插件部署与调试
AddOn打包流程
方案一:
AddOn 插件开发完成后,将前端界面打包,放入AddOn目录下。
将AddOn目录压缩成tar.gz文件。
方案二:
jaka-addon-plugin在创建插件时,会自动生成一个打包配置文件
package_log_pro.json,里面配置了AddOn的打包信息。再次执行
addon-plugin:make new addon命令,jaka-addon-plugin如果识别到当前工作目录是一个AddOn开发目录,则会自动读取python脚本,将相关文件加入到打包配置中。检查
package_log_pro.json文件,确认no_transform和transform参数中包含了所有需要打包的文件,若有缺失,推荐手动添加到no_transform参数中。执行
addon-plugin:build addon命令,将AddOn目录的./output路径下打包成tar.gz文件。
AddOn部署流程
打开Coboπ并登录机器人。
在应用界面,上传AddOn压缩包。
AddOn调试方法
AddOn在运行时,AddOn Manager会在AddOn的目录下自动创建一个log目录。 目录中包含两个日志文件:
AddOnerrlog.log: AddOn抛出的异常记录。AddOnlog.log: addon运行的日志记录。
可在浏览中,通过跨域代理下载。 URL: https://${机器人IP}/addon/${AddOn名称}/log/AddOnerrlog.log和https://${机器人IP}/addon/${AddOn名称}/log/AddOnlog.log
附录
控制系统IO类型
IO类型 |
类型代码 |
描述 |
|---|---|---|
控制柜IO |
0 |
面板IO,兼容Modbus从站IO,Profinet从站IO |
TIO |
1 |
随TIO版本 |
Modbus扩展IO |
2 |
控制器做Modbus主站 |
继电器IO |
3 |
目前仅CAB V3支持D0 |
Modbus从站IO |
4 |
原Modbus从站IO从0索引 |
Profinet从站IO |
5 |
原Profinet从站IO从O索引 |
EtherNet/IP从IO |
6 |
新增EtherNet/IP从站IO从0索引 |