IO 控制案例
该教程会实现控制吸盘吸取和释放的插件。
该插件的工作流程如下:
创建插件
# 需要使用 node v20 及以上版本
dpt create
在初始化插件时,需要提供
- 插件的名字,必填,当前文件夹下不得有同名文件夹
- 插件的描述,非必填,可以后续在配置文件中进行修改
- 插件的版本号,默认是
1-0-0
- 机械臂控制器的IP地址,默认是
192.168.5.1
,可在配置文件中修改
$ dpt create
? Please input plugin name: io
? Please input plugin description: A plugin demo for io control
? Please input plugin version: 1-0-0
? Please input device IP: 192.168.5.1
在完成基础信息的配置和填写后,程序会自动执行安装程序
Packages: +587
Downloading antd@5.20.3: 9.80 MB/9.80 MB, done
Progress: resolved 588, reused 582, downloaded 5, added 587, done
dependencies:
+ @dobot-plus/components 0.0.0
+ antd 5.20.3
+ axios 1.7.5
+ i18next 23.14.0
+ pubsub-js 1.9.4
+ react 18.3.1
+ react-dom 18.3.1
+ react-i18next 15.0.1
+ react-redux 9.1.2
+ redux 5.0.1
devDependencies:
+ @types/node 20.16.1 (22.5.0 is available)
+ @types/pubsub-js 1.8.6
+ @types/react 18.3.4
+ @types/react-dom 18.3.0
+ @types/react-redux 7.1.33
+ @typescript-eslint/eslint-plugin 7.18.0 (8.3.0 is available)
+ @typescript-eslint/parser 7.18.0 (8.3.0 is available)
+ add 2.0.6
+ css-loader 7.1.2
+ eslint 8.57.0 (9.9.1 is available)
+ eslint-plugin-react-hooks 4.6.2
+ eslint-plugin-react-refresh 0.4.11
+ postcss-loader 8.1.1
+ sass 1.77.8
+ sass-loader 16.0.1
+ style-loader 4.0.0
+ ts-loader 9.5.1
+ typescript 5.5.4
+ url-loader 4.1.1
+ webpack 5.94.0
Done in 39.7s
⚠️注意: 在插件文件夹初始化完成后,vscode 会根据配置进行一些插件的安装,请允许该安装过程,并确保该过程顺利,否则会影响后续的Lua脚本调试。
当命令行输出类似上面的内容后,表示一个插件项目的文件夹已经创建完毕。
目录结构如下
io
├── Resources
│ ├── document
│ │ └── config.json
│ ├── i18n
│ │ ├── client
│ │ │ ├── de.json
│ │ │ ├── en.json
│ │ │ ├── es.json
│ │ │ ├── hk.json
│ │ │ ├── ja.json
│ │ │ ├── ko.json
│ │ │ ├── ru.json
│ │ │ └── zh.json
│ │ └── plugin
│ │ ├── de.json
│ │ ├── en.json
│ │ ├── es.json
│ │ ├── hk.json
│ │ ├── ja.json
│ │ ├── ko.json
│ │ ├── ru.json
│ │ └── zh.json
│ └── images
│ └── pallet.svg
├── configs
│ ├── Blocks.json
│ ├── Main.json
│ ├── Scripts.json
│ └── Toolbar.json
├── dpt.json
├── lua
│ ├── daemon.lua
│ ├── httpAPI.lua
│ ├── userAPI.lua
│ └── utils
│ ├── await485.lua
│ ├── mqtt.lua
│ ├── num_convert.lua
│ ├── util.lua
│ └── variables.lua
├── package.json
├── pnpm-lock.yaml
├── tsconfig.json
└── ui
├── Blocks.tsx
├── Main.tsx
└── Toolbar.tsx
机械臂&末端控制
机械臂和末端的控制逻辑主要在 userApi.lua
文件中进行编写。
针对该插件的场景,实际需要对外提供三个函数:
- 吸取函数
- 释放函数
- 获取状态函数
针对这三个函数,我们需要依次编写 userApi.lua
、httpApi.lua
和对应的 UI 文件。
-
编辑
userAPI.lua
-- 定义函数grip用于控制吸取操作
function userApiModule.grip()
-- 设置第一个端子的输入信号为 ON
ToolDO(1, 1)
end
-- 定义函数release用于释放操作
function userApiModule.release()
-- 设置第一个端子的输入信号为 OFF
ToolDO(1, 0)
end
-- 定义函数getStatus用于获取吸盘的状态
function userApiModule.getStatus()
local status = 'ERROR'
local STATUS = {
ERROR = 'error',
GRIPPING = 'gripping',
IDLE = 'idle'
}
-- 读取末端数据
local di1 = ToolDI(1)
local di2 =ToolDI(2)
-- 根据末端端子的输出,判断当前设备状态
if di1 == nil or di2 == nil or di2 == 1 then
status = STATUS.ERROR
elseif di1 == 1 then
status = STATUS.IDLE
elseif di1 == 0 then
status = STATUS.GRIPPING
end
return status
end
function userApiModule.OnRegist()
EcoLog(" --- OnRegist .... --- ")
-- 0. 接口导出
-- 将 grip、release、getStatus 三个函数导出该模块
local isErr = ExportFunction("[export name you want]", userApiModule.grip) or
ExportFunction("[export name you want]", userApiModule.release) or
ExportFunction("[export name you want]", userApiModule.getStatus)
-- 1. 错误的 处理
if isErr then
EcoLog(" --- ERR to register .... --- ", isErr)
dobotTool.SetError(0)
end
end
return userApiModule当鼠标悬停到函数上时,会出现函数的说明、参数类型和返回值
-
编写
httpAPI.lua
-- 添加一个名为 grip 的 http post 请求的处理函数
httpModule.grip = function()
userAPI.grip()
return {
--- Your responce data
--- example: status = true
}
end
-- 添加一个名为 release 的 http post 请求的处理函数
httpModule.release = function()
userAPI.release()
return {
--- Your responce data
--- example: status = true
}
end
httpModule.status = function()
local status = userAPI.getStatus()
-- http 接口返回io状态
return {
status = status
--- Your responce data
--- example: status = true
}
end -
编写
daemon.lua
文件local mqtt = require('utils.mqtt')
local function handleInLoop()
local data = {}
mqtt.publish(data)
end
local function EventLoop()
while true do
handleInLoop()
Wait(1000)
end
end
local thread = systhread.create(EventLoop, 1)
thread:wait()控制器和末端的状态同步通过mqtt协议发送给远端,在lua的进程中,会执行一个轮询操作,每隔一秒执行一次,开发者可以将需要进行状态同步和消息发送的操作加入
handleInLoop
函数。如果当前的开发环境工作正常时,在编写代码的过程中会有自动代码提示和说明,如下所示:
⚠️在编码过程中会对
Lua
进行静态的代码检查,包括但不限于参数异常、类型不匹配、未声明的变量就使用等异常情况,请在编码的过程中注意这些黄色的波浪线告警,这会导致Lua执行的失败。 -
Lua 预调试
- 在当前项目根目录下运行
dpt lua
- 根据提示选择要在本地执行的 lua 脚本
- 开发者可自行打印日志,查看调试的 lua 脚本的模块引入、语法、逻辑等是否存在问题
- 在当前项目根目录下运行
控制界面
接口请求
在正常情况下会根据开发者在 lua/httpAPI.lua
模块中编写的方法,自动的生成一个前端请求文件,开发者使用
import * as http from '@dobot/http/http'
的方式引入,之后使用同名函数的形式就可以发起 http 请求。
// 函数名与 httpAPI.lua 对应函数同名
http.grip()
http.release()
⚠️如果用户想自行编写请求配置,可编写 ui/http/api.json
文件
{
"requestGrip": {
"method": "post",
"url": "grip"
},
"requestRelease": {
"method": "post",
"url": "release"
},
"requestStatus": {
"method": "get",
"url": "status"
}
}
⚠️请求参数中URL部分需要和 httpAPI.lua
模块中的函数名称对应,表示控制器需要调用的是 httpAPI.lua
模块中对应的方法
-
编写
ui/pages/Main.tsx
import { Button } from '@dobot-plus/components'
import { useState } from 'react'
import { useTranslation } from 'react-i18next'
import * as http from '@dobot/http/http'
import { DobotPlusApp } from '@dobot/index'
function App() {
const { t } = useTranslation()
const [text, setText] = useState('Test')
function handleButton1Click() { http.grip() }
function handleButton2Click() { http.release() }
function handleMessage(topic: string, msg: Buffer) {
http.status().then(res => {
const { data } = res
setText(data)
})
}
return (
<div className="app">
<DobotPlusApp useMqtt={true} onMessage={handleMessage}>
<h1>{t('testKey')}</h1>
<Button type="primary" onClick={handleButton1Click}>
Grip
</Button>
<Button type="primary" onClick={handleButton2Click}>
Release
</Button>
<span>{text}</span>
</DobotPlusApp>
</div>)
}
export default App-
http
模块根据lua/httpAPI.lua
自动生成,开发者使用同名函数即可调用,也可以自行创建ui/http/api.json
的配置{
"requestName": {
"url": "/testURL",
"method": "post"
}
}调用时,使用如下方式
import { http } from '@dobot/http/api'
http.requestName() -
DobotPlusApp
是一个 react 的高阶组件,内部执行了 Websocket 的建立和插件端口的获取操作
-
调试和验证
调试插件指令可进行以下两种情形的开发工作:
- 仅调试页面
- 连接真机进行调试
dpt dev
在执行上述命令时,命令行会提示开发者是否连接真机进行测试
$ dpt dev
? Debug lua on real device? Yes
? Please check the device IP: 192.168.5.1 and port: 22001 (y/n)
开发者需要确定:
- 控制器的真实IP是否正确,默认是
192.168.5.1
- 控制器服务端口是否正确,默认 是
22001
- SFTP 服务相关配置是否正确
上述配置的详细信息请查看 dpt.json
配置文件
{
"ip": "192.168.5.1", // 控制器 IP
"port": 22001, // 控制器端口
"pluginPort": 22100 // 插件端口号
}
在连接真机进行调试时,保存lua文件会自动同步至控制器,开发者可在浏览器的界面交互中对机械表末端进行控制。