VisualHMI - Lua 脚本API函数接口
本文档适用于VisualHMI平台,Lua脚本语言为V5.3版本,配合工程可以完成大部分的内部逻辑处理, MCU可以只参与数据传输部分,不参与逻辑处理。点击菜单工程栏→脚本编程, 默认在工程目录下生成main.lua,且自动定义变量的数据类型,假设工程当前为modbus协议,如下所示:
ENCRYPT_=0 --LUA脚本加密
--数据类型定义
VT_LW = 1 --变量地址
VT_RW = 2 --FLASH存储
VT_0x = 10 --线圈
VT_1x = 11 --输入点
VT_3x = 12 --输入寄存器
VT_4x = 13 --保持寄存器
function on_init()
end
function on_run(screen)
end
function on_update(slave,vtype,addr)
end
function on_draw(screen_id,control_id)
end
定义的数据类型:VT_0x线圈、VT_1x离散输入、VT_3x输入寄存器,VT_4x保持寄存器。在读(get_uint16/get_int16...)、写(set_uint16/set_int16)、on_update中vtype的变量类型,对应定义的变量,如下所示:
--数据类型定义
VT_LW = 1 --变量地址
VT_RW = 2 --FLASH存储
VT_0x = 10 --线圈
VT_1x = 11 --输入点
VT_3x = 12 --输入寄存器
VT_4x = 13 --保持寄存器
function on_init()
set_bit(VT_0x,0x0000,1) --modbus 协议,设置线圈0x0000地址的值为1
local val = get_bit(VT_1x,0x0000) --modbus 协议,获取离散输入0x0000地址的值
set_uint16(VT_4x,0x1000, 1) --modbus 协议,设置保持寄存器0x1000地址的值为1
local val = get_uint16(VT_3x,0x1000) --modbus 协议,获取输入寄存器0x1000的值
end
function on_update(slave,vtype,addr)
if slave == 0
then
if vtype == VT_4x
then
.....
end
end
end
1 常用回调函数
1.1 on_init()
系统加载LUA脚本文件之后,立即调用此回调函数,通常用于执行初始化操作
ENCRYPT_=0 --LUA脚本加密
--数据类型定义
VT_LW = 1 --变量地址
VT_RW = 2 --FLASH存储
VT_0x = 10 --线圈
VT_1x = 11 --输入点
VT_3x = 12 --输入寄存器
VT_4x = 13 --保持寄存器
function on_init()
dofile('test.lua')--分多文件编辑,加载其他lua文件
set_uint16(VT_4x, 0x0000, 1)--初始化寄存
end
1.2 on_run(screen)
系统不断循环调用该函数
set_run_cycle(cycle)可设置执行周期(毫秒单位)
screen:当前画面ID
[!note|tip:注意]
错误用法1:系统默认周期,不断设置从机寄存器,导致堵塞
正确用法:on_run周期长,如set_run_cycle(1000),或有条件限制,成立后才设置值
ENCRYPT_=0 --LUA脚本加密
--数据类型定义
VT_LW = 1 --变量地址
VT_RW = 2 --FLASH存储
VT_0x = 10 --线圈
VT_1x = 11 --输入点
VT_3x = 12 --输入寄存器
VT_4x = 13 --保持寄存器
function on_run(screen)
set_uint16(VT_4x, 0x0000, 1) --不恰当用法
------------------------------------------------------------------------
------------------------------------------------------------------------
--正确用法
local start = get_uint16(VT_4x, 0x1000) --开机状态
local dstVol = get_uint16(VT_4x, 0x1001) --设置电压
local curVol = get_uint16(VT_4x, 0x1001) --当前电压
if dstVol > curVol and start == 1 --设备开启后,当前电压不等于目标电压,设置当前电压值
then
set_uint16(VT_4x, 0x1002, 1) --设置频率
end
end
1.3 on_update(slave, vtype, addr)
变量被设置、更改后,自动执行此函数
slave:站号索引,0开始
vtype:变量类型,生成main.lua,自动定义变量的数据类型
addr:变量地址
[!note|tip:注意]
1.串口指令修改寄存器值,不会触发on_update回调
2.在on_update函数里,调用set_uit16(set_int16/set_uint32...), 不会在触发on_update回调
3.在其他系统回调函数,如on_init ,执行set_uit16(set_int16/set_uint32...) ,会触发on_update回调
4.用户点击屏幕,修改控件状态(寄存器值),会触发on_update回调
如下所示,以Modbus 协议为例,当其他回调函数设置寄存器,均不想触发on_update回调,可以定义全局变量如下处理:
ENCRYPT_=0 --LUA脚本加密
EN_ON_UPDATE_API_CB = 1 --全局变量,其他回调函数设置寄存器时,为1执行,为0直接退出
--数据类型定义
VT_LW = 1 --变量地址
VT_RW = 2 --FLASH存储
VT_0x = 10 --线圈
VT_1x = 11 --输入点
VT_3x = 12 --输入寄存器
VT_4x = 13 --保持寄存器
function on_init()
EN_ON_UPDATE_API_CB = 0
--user code
set_uint16(VT_LW, 0x1000,0x55AA)
EN_ON_UPDATE_API_CB = 1
end
function on_run(screen)
EN_ON_UPDATE_API_CB = 0
--user code
EN_ON_UPDATE_API_CB = 1
end
function on_update(slave, vtype, addr)
if EN_ON_UPDATE_API_CB == 0
then
return
end
if slave == 0
then
if vtype == VT_4x --保持寄存器
then
if addr == 0x1000
then
local val = get_uint16(VT_4x, addr)
if val == 1
then
set_uint16(VT_4x, 0x0001, val)
end
end
elseif vtype == VT_0x --线圈
then
if addr == 0x0000
then
local val = get_uint16(VT_0x, addr)
if val == 1
then
set_uint16(VT_0x, 0x0001, val)
end
end
end
end
if vtype == VT_LW --内部寄存器
then
if addr == 0x1000
then
local val = get_uint16(VT_LW, addr)
if 0x55AA == val
then
set_uint16(VT_4x, 0x0000, val)
end
end
end
end
function on_draw(screen_id,control_id)
EN_ON_UPDATE_API_CB = 0
--user code
EN_ON_UPDATE_API_CB = 1
end
function on_screen_change(screen)
EN_ON_UPDATE_API_CB = 0
--user code
if screen == 1
then
set_bit(VT_0x, 0x0000, 1)
end
EN_ON_UPDATE_API_CB = 1
end
1.4 on_screen_change(screen)
当画面切换时,自动执行此函数
screen:目标画面ID
1.5 on_press(state, x, y)
点击屏幕触发坐标通知,100ms回调一次
state:1-按下,2-长按,0-弹起
x:x轴坐标
y:y轴坐标通知
1.6 on_usb_inserted(driver)
U盘插入时,执行此回调函数,dirver为U盘的盘符
1.7 on_usb_removed()
U盘拔出时,执行此回调函数
1.8 on_sd_inserted(dir)
SD卡插入通知,dir盘符路径
1.9 on_sd_removed()
SD卡拔出通知
1.10 on_parse_timestamp(screen,control,timestamp)
告警/数据记录,表格告警时间回调。用于自定义时间显示格式
screen:画面ID
control:控件ID
timestamp:时间戳,32位
function on_parse_timestamp(screen,control,timestamp)
local year,mon,day,hour,min,sec = make_datetime(timestamp)
local new_timestamp = ''
if screen == 0 and control == 1
then
return (string.format('%04d-%02d-%02d %02d:%02d:%02d', year,mon,day,hour,min,sec))
elseif screen == 2 and control == 1
then
return (string.format('%04d-%02d-%02d %02d:%02d:%02d', year,mon,day,hour,min,sec))
end
end
2 读写寄存器函数
2.1 set_notify(enable)
使能串口通知,启用后设置变量的值可触发串口命令发送。
enable:0禁止,1使能(默认值)
--如DCBUS协议下,设置0x1000地址,不通过串口下发给主板:
set_notify(0) -- 禁止通知
set_uint16(VT_LW, 0x1000, 1)--设置参数
set_notify(1)-- 启用通知
2.2 select_slave(slave_id)
选择从站地址,用于多从机模式,如MODBUS、FX2N协议
slave_id:从机索引
如modbus 协议中,总线有2个从机,第一个从机站号10,第2个从机站号为33,可封装如下函数:
--读取保持寄存器
function mb_read_reg_03(slave, addr)
local onlineState = get_uint16(VT_LW, 0x01A3) --从机在线掩码,bitx = 1在线
if (onlineState >> slave) & 0x01 == 0x01
then
select_slave(slave) --选择从机
return get_uint16(VT_4x, addr)--获取寄存器值
else
return false
end
end
--设置保持寄存器
function mb_write_reg_06(slave, addr, value)
local onlineState = get_uint16(VT_LW, 0x01A3) --从机在线掩码,bitx = 1在线
if (onlineState >> slave) & 0x01 == 0x01
then
feed_dog()--喂狗
select_slave(slave)--选择从机
set_uint16(VT_4x, addr, value)--设置寄存器值
end
end
local val1 = mb_read_reg_03(0, 0x1000)--读取从机1,站号10,寄存器地址0x1000
local val2 = mb_read_reg_03(1, 0x1000)--读取从机2,站号33,寄存器地址0x1000
mb_write_reg_06(0, 0x2000,val1)--设置从机1,站号10,寄存器地址0x1000值为val1
mb_write_reg_06(1, 0x2000,val2)--设置从机1,站号33,寄存器地址0x1000值为val2
2.3 set_endian(en)
设置变量的大小端,在主从机模式下生效
en:0-大端(默认值),1-小端
2.4 set_bit(vtype, addr, value)
设置位寄存器:如Modbus的线圈、Fx2N的X、Y、S、M寄存器
vtype:数据类型
addr:变量地址
value:写入的值
set_bit(VT_0x, 0x0000, 1) --设置线圈0x0000地址的状态1
2.5 get_bit (vtype, addr)
读取位寄存器:如Modbus的线圈、Fx2N的X、Y、S、M寄存器,返回数值
vtype:数据类型
addr:变量地址
local state = get_bit(VT_0x, 0x0000) --获取线圈0x0000地址的状态
2.6 set_uint16(vtype, addr, value)
设置无符号短型(uint16)寄存器
vtype:数据类型
addr:变量地址
value:写入的值
set_uint16(VT_LW, 0x1000, 12345) --设置屏幕内部寄存器0x1000地址为12345
2.7 get_uint16(vtype, addr)
读取无符号短型(uint16)寄存器
vtype:数据类型
addr:变量地址
local val = get_uint16 (VT_LW, 0x1000) --获取屏幕内部寄存器0x1000地址的值
2.8 set_int16(vtype, addr, value)
设置有符号短型(int16)寄存器
vtype:数据类型
addr:变量地址
value:写入的值
set_int16(VT_LW, 0x1000, 12345) --设置屏幕内部寄存器0x1000地址为-12345
2.9 get_int16(vtype, addr)
读取有符号短型(int16)寄存器
vtype:数据类型
addr:变量地址
local val = get_int16 (VT_LW, 0x1000)--获取屏幕内部寄存器0x1000地址的值
2.10 set_uint32(vtype, addr, value)
设置无符号短型(uint32)寄存器
vtype:数据类型
addr:变量地址
value:写入的值
set_uint32(VT_LW, 0x1000, 123456) --设置屏幕内部寄存器0x1000地址为123456
2.11 get_uint32(vtype, addr)
获取无符号短型(uint32)寄存器
vtype:数据类型
addr:变量地址
local val = get_uint32 (VT_LW, 0x1000)--获取屏幕内部寄存器0x1000地址的值
2.12 set_int32(vtype, addr, value)
设置有符号短型(int32)寄存器
vtype:数据类型
addr:变量地址
value:写入的值
set_uint32(VT_LW, 0x1000, -123456) --设置屏幕内部寄存器0x1000地址为-123456
2.13 get_int32 (vtype, addr)
读取有符号整型(int32)寄存器
vtype:数据类型
addr:变量地址
local val = get_int32(VT_LW, 0x1000)--获取屏幕内部寄存器0x1000地址的值
2.14 set_uint64(vtype, addr, value)
设置无符号长整型(uint64)寄存器
vtype:数据类型
addr:变量地址
value:写入的值
set_uint64(VT_LW, 0x1000, 1234567890) --设置屏幕内部寄存器0x1000地址为1234567890
2.15 get_uint64 (vtype, addr)
读取无符号整型(int64)寄存器
vtype:数据类型
addr:变量地址
local val = get_uint64(VT_LW, 0x1000)--获取屏幕内部寄存器0x1000地址的值
2.16 set_int64 (vtype, addr, value)
设置有符号长整型(int64)寄存器
vtype:数据类型
addr:变量地址
value:写入的值
set_int64(VT_LW, 0x0000, -1234567890)--设置屏幕内部寄存器0x1000地址为-1234567890
2.17 get_int64 (vtype, addr)
读取有符号整型(int64)寄存器
vtype:数据类型
addr:变量地址
local value = get_int64(VT_LW, 0x1000)--获取屏幕内部寄存器0x1000地址的值
2.18 set_float(vtype, addr, value)
设置单精度浮点数(float)寄存器
vtype:数据类型
addr:变量地址
value:写入的值
set_float(VT_LW, 0x1000,1.234)--设置屏幕内部寄存器0x1000地址为1.234
2.19 get_float (vtype, addr)
读取单精度浮点数(float)寄存器
vtype:数据类型
addr:变量地址
local val = get_float(VT_LW, 0x1000)--获取屏幕内部寄存器0x1000地址的值
2.20 set_double(vtype, addr, value)
设置双精度浮点数(doubule)寄存器
vtype:数据类型
addr:变量地址
value:写入的值
set_double(VT_LW, 0x1000,1.23456789)--设置屏幕内部寄存器0x1000地址为1.23456789
2.21 get_double (vtype, addr)
设置双精度浮点数(doubule)寄存器
vtype:数据类型
addr:变量地址
local value = get_double(VT_LW, 0x1000)--获取屏幕内部寄存器0x1000地址的值
2.22 set_string(vtype, addr, strings)
设置字符串类型寄存器
vtype:数据类型
addr:变量地址
value:写入的值
set_string(VT_LW, 0x1000,'https://www.gz-dc.com/')--设置屏幕内部寄存器0x1000地址为https://www.gz-dc.com/
2.23 get_string(vtype, addr)
读取字符串变量
vtype:数据类型
addr:变量地址
local string = get_string (VT_LW, 0x1000)--获取屏幕内部寄存器0x1000地址的值
2.24 set_uint16_ex(vtype, addr, value1,value2, …, value120)
vtype:数据类型
addr:变量起始地址,最大可以写120个连续寄存器
value1:寄存器1的值
value2:寄存器2的值
……
value120: 寄存器120的值
local r_addr = 0x6060
set_uint16_ex(vtype, r_addr,
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,
21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,
41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,
61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,
81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100, 101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120)
2.25 set_array(vtype, addr, buff)
vtype:数据类型
addr:变量起始地址,最大可以写120个连续寄存器
buff:word(字)数组,最大120个字
local buff = {}
local r_addr = 0x6060
local index = 120
local data = 0
for i = 1, 120
do
buff[i] = i
end
set_array(vtype, r_addr, buff)
2.26 start_read(index,vtype, addr,quantity,cycle,clcye_run,mode)
开始读取多个连续的变量,系统自动发指令读取变量地址
[!note|tip:注意]
1.只能用于主机模式,例如Modbus-Master、FX2N等
2.调用一次,屏幕会周期性发指令请求,停止需要调用stop_read
3.该函数没有返回值,需要配合get_xx获取寄存器的值
4.当前画面用到的变量地址或者有配置告警、资料采集,系统会自动读取,无需使用start_read。
5.若当前画面的控件绑定变量地址或者有配置告警、资料采集,脚本调用的start_read和前者有交叉部分,系统会优化读取指令,重新整合指令请求
index:索引,通常和停止读取搭配stop_read
vtype:数据类型
addr:开始读取的地址
quantity:读取的个数,最大120
cycle: 选填,指令周期
clcye_run:选填,运行在那个指令周期
mode:选填,读模式,若初始化调用create_resp_que() ,该参数为1可以支持只读1次,为0要一直
ENCRYPT_=0 --LUA脚本加密
--数据类型定义
VT_LW = 1 --变量地址
VT_RW = 2 --FLASH存储
VT_0x = 10 --线圈
VT_1x = 11 --输入点
VT_3x = 12 --输入寄存器
VT_4x = 13 --保持寄存器
function on_init()
start_read(0, VT_4x, 0x0000, 10)--任意界面均会发送指令请求4x0000~4x000A寄存器指令
end
cycle、clcye_run用法
HMI一个循环,是把当前需要读取的指令进行出队列发送,当某些指令参数需要高频读取,更快的刷新显示时候,就需要用到这个api,这个的目的是把其他指令降低读取频率
如start_read(0,VT_4x, 0x1000, 10) --做个表示每个周期都会发指令,默认cycle,clcye_run都是0
start_read(1,VT_4x, 0x2000, 10, 3,2) --做个表示3周期发一次指令,发在第3个周期(3-1 = 2),指令显示将是
01 03 1000 000A... 第1个指令周期
01 03 1000 000A... 第2个指令周期
01 03 1000 000A... 第3个指令周期
01 03 2000 000A...
01 03 1000 000A... 第1个指令周期
01 03 1000 000A... 第2个指令周期
01 03 1000 000A... 第3个指令周期
01 03 2000 000A...
2.27 stop_read(index)
停止读取多个连续的变量
[!note|tip:注意]
只能用于主机模式,例如Modbus-Master、FX2N等
index:索引,通常和开始读取搭配start_read
2.28 stop_all_read()
停止所有start_read开启的读取指令
[!note|tip:注意]
只能用于主机模式,例如Modbus-Master、FX2N等
2.29 set_auto_read(en)
使能画面控件绑定的寄存器自动读取
[!note|tip:注意]
1.只能用于主机模式,例如Modbus-Master、FX2N等
2.set_auto_read(0),禁止后,用start_read 控制读取
3.画面的控件绑定寄存器,默认自动读取
en:0-画面禁止自动读取,1-画面自动读取
2.30 create_resp_que()
创建队列,可以start_read可以只读1次
[!note|tip:注意]
1.只能用于主机模式,例如Modbus-Master、FX2N等
ENCRYPT_=0 --LUA脚本加密
--数据类型定义
VT_LW = 1 --变量地址
VT_RW = 2 --FLASH存储
VT_0x = 10 --线圈
VT_1x = 11 --输入点
VT_3x = 12 --输入寄存器
VT_4x = 13 --保持寄存器
function on_init()
set_auto_read(0) --脚本控制读
create_resp_que() --创建队列,可以只读1次存器指令
start_read(1, VT_4x, 0xA009, 30, 0, 0, 1) --只发一次读A009 ~ A01D 范围的数据
end
2.31 on_cmd_resp(slave,vtype,addr,count,ret,wr)
读写指令回调结果
slave : 从机索引
vtype : 寄存器类型
addr : 寄存器地址
count : 寄存器值
ret : 读写结果, 0-正常,1-异常
wr :0-读,1- 写
[!note|tip:注意]
1.只能用于主机模式,例如Modbus-Master、FX2N等
2.create_resp_que(),配合该API使用
ENCRYPT_=0 --LUA脚本加密
--数据类型定义
VT_LW = 1 --变量地址
VT_RW = 2 --FLASH存储
VT_0x = 10 --线圈
VT_1x = 11 --输入点
VT_3x = 12 --输入寄存器
VT_4x = 13 --保持寄存器
function on_init()
set_auto_read(0) --脚本控制读
create_resp_que() --创建队列,可以只读1次存器指令
start_read(1, VT_4x, 0xA009, 30, 0, 0, 1) --只发一次读A009 ~ A01D 范围的数据
end
function on_cmd_resp(slave,vtype,addr,count,ret,wr)
print('on_cmd_resp(vtype = '..vtype..', addr = '..(string.format('%04X', addr))..', count = '..count..', ret = '..ret..', wr ='..wr..')')
end
> 通讯成功 : on_cmd_resp(vtype = 13, addr = A009, count = 30, ret = 0, wr = 0)
>
2.32 set_slave_site(idx, slave_id)
修改从机地址
[!note|tip:注意]
1.只能用于主机模式,例如Modbus-Master、FX2N等
idx:从机索引,从0开始
slave_id: 从机站号
3 绘图函数
3.1 on_draw(screen,control)
控件自绘接口函数,要使用自绘功能,控件ID不能为0。
当界面的显示内容需要更新时,系统自动调用此函数,用户在此函数中添加自定义的绘图操作。
[!note|tip:注意]
1.该函数为系统回调函数,用户不要直接调用
2.相关draw_xx 图形,需要在该回调函数里面调用执行
下面几种情况会触发此函数:
界面有动画播放、视频播放、RTC时间显示的动态刷新;
用户操作屏幕控件控件;
通过LUA脚本或串口指令更新控件;
通过执行redraw
若要绘制的图形有上下图层关系,如图片1绘制到图片2上层,可通过建立不同“画板”id实现。如下所示,添加两个矩形框作为“画板”,其中层次关系,从下到上依次为文本控件→蓝色矩形→黄色矩形
结合Lua脚本,在on_draw(...)判读对应的画面、对于控件id,即可绘制到“控件”上层或“已绘制的图形”上。如绘制“水果图片”到蓝色画板上,绘制“小岛图片”到黄色背景上,如下所示
function on_draw(screen_id, control_id)
if screen_id == 0 and control_id == 1
then
draw_surface(surface[1], 293, 88, 222, 353, 0, 0) --裁剪显示
elseif screen_id == 0 and control_id == 2
then
draw_surface(surface[2], 314, 158, 180, 250, 0, 0) --裁剪显示
end
end
“画布”的大小、位置、类型可以任意,若控件ID、层叠顺序确定好后,一般情况建议如下所示:
[!note|tip:注意]
1.控件类型:静态的控件,如文字、直线、矩形、圆形等,防止被误触或者设置
2.画布大小:1*1大小
3.画布位置:放在不显眼的角落、或编辑区外
3.2 redraw()
发起重绘请求,触发on_draw的执行。
3.3 set_pen_color(color)
设置画笔的颜色,RGB565,用于指定线、矩形、圆等的颜色
color:RGB565颜色值
3.4 draw_line(x0,y0,x1,y1,width)
绘制直线
x0,y0:起始点坐标
x1,y1:结束点坐标
width:为线条的厚度,1~10
draw_type = 0
mode = { --绘制类型表
line = 1,
}
function on_update(slave,vtype,addr)
if addr == 0x1000
then
draw_type = get_uint16(VT_LW, addr) --获取字设置按钮键值
redraw()--绘图
end
end
function on_draw(screen_id,control_id)
local switch = {
[mode.line] = function(control)
if screen_id == 0 and control == 1
then
--设置画笔黄色划线
set_pen_color(0xFFE0)
draw_line(225, 253, 405, 253)
--设置画笔红色,划线
set_pen_color(0xF800)
draw_line(508, 128, 508, 378, 5)
end
end,
end
if switch[draw_type]
then
switch[draw_type](control)
end
end
3.5 draw_rect(x0,y0,x1,y1,fill)
绘制矩形
x0,y0:左上角坐标
x1,y1:右下角坐标
fill:1填充,00为不填充
draw_type = 0
mode = { --绘制类型表
rect = 2,
}
function on_update(slave,vtype,addr)
if addr == 0x1000
then
draw_type = get_uint16(VT_LW, addr)--获取字设置按钮键值
redraw()--绘图
end
end
function on_draw(screen_id,control_id)
local switch = {
[mode.rect] = function(control)
if screen_id == 0 and control == 1
then
--绘制矩形
draw_rect(225, 128, (225+180), (128+250), 0)
draw_rect(418, 163, (418+180), (128+180), 1)
end
end,
end
if switch[draw_type]
then
switch[draw_type](control)
end
end
3.6 draw_rect_alpha(x0,y0,x1,y1,alpha)
绘制实心的半透明矩形,F系列不支持
x0,y0:左上角坐标
x1,y1:右下角坐标
alpha:透明度0全透明~255不透明
draw_type = 0
mode = { --绘制类型表
rect_alpha = 3,
}
function on_update(slave,vtype,addr)
if addr == 0x1000
then
draw_type = get_uint16(VT_LW, addr)--获取字设置按钮键值
redraw()--绘图
end
end
function on_draw(screen_id,control_id)
local switch = {
[mode.rect_alpha] = function(control)
if screen_id == 0 and control == 1
then
--绘制半透矩形
draw_rect_alpha(225, 128, (225+180), (128+250), 30)
draw_rect_alpha(418, 163, (418+180), (128+180), 60)
end
end,
end
if switch[draw_type]
then
switch[draw_type](control)
end
end
3.7 draw_circle(x,y,r,fill)
绘制圆形
x,y:圆的中心坐标
r:圆的半径
fill:0填充,非0为不填充,表示圆形线条厚度
draw_type = 0
mode = { --绘制类型表
circle = 4,
}
function on_update(slave,vtype,addr)
if addr == 0x1000
then
draw_type = get_uint16(VT_LW, addr)--获取字设置按钮键值
redraw()--绘图
end
end
function on_draw(screen_id,control_id)
local switch = {
[mode.circle] = function(control)
if screen_id == 0 and control == 1
then
--绘制圆形
draw_circle(300, 253, 100, 0)
draw_circle(450, 253, 150, 1)
end
end,
end
if switch[draw_type]
then
switch[draw_type](control)
end
end
3.8 draw_ellipse(x0,y0,x1,y1,fill)
绘制椭圆
x0,y0:左上角坐标
x1,y1:右下角坐标
fill:0填充,非0为不填充,表示椭圆线条厚度
draw_type = 0
mode = { --绘制类型表
ellipse = 5,
}
function on_update(slave,vtype,addr)
if addr == 0x1000
then
draw_type = get_uint16(VT_LW, addr)--获取字设置按钮键值
redraw()--绘图
end
end
function on_draw(screen_id,control_id)
local switch = {
[mode.ellipse] = function(control)
if screen_id == 0 and control == 1
then
--绘制椭圆
draw_circle(300, 253, 100, 0)
draw_circle(450, 253, 150, 1)
end
end,
end
if switch[draw_type]
then
switch[draw_type](control)
end
end
3.9 draw_image(image_id,frame_id,dstx,dsty,width,height,srcx,srcy)
绘制图片
image_id图片资源的ID
frame_id对应图标,可以设置帧ID,其他图片固定为0
dstx图片显示X坐标
dsty图片显示Y坐标
width图片显示宽度
height图片显示高度
srcx图片裁剪X坐标
srcy图片裁剪Y坐标
[!note|tip:如何确定image_id]
1.在工程目录下的../build/文件夹,打开image.xml文件,image id = "xx"表示第一个参数
draw_type = 0
mode = { --绘制类型表
imageId = 6,
}
function on_update(slave,vtype,addr)
if addr == 0x1000
then
draw_type = get_uint16(VT_LW, addr)--获取字设置按钮键值
redraw()--绘图
end
end
function on_draw(screen_id,control_id)
local switch = {
[mode.imageId] = function(control)
if screen_id == 0 and control == 1
then
--绘制图片
draw_image(1, 0, 225, 128, (225+180), (128+250), 0, 0)
draw_image(2, 0, 418, 163, (418+180), (128+180), 0, 0)
end
end,
end
if switch[draw_type]
then
switch[draw_type](control)
end
end
3.10 draw_text(text,x,y,w,h,font_id,size,color,align,charcode)
显示文字,text字符串
x:显示X坐标
y:显示Y坐标
w:显示宽度
h:显示高度
font_id:索引
size:字体大小
color:颜色RGB565
align对齐方式:bit0~bit1水平对齐方式,0左对齐,1居中对齐,2对齐;bit2~bit3垂直对齐方式,0上对齐,1居中对齐,3下对齐
charcode:选填。0 或不填,默认 1ua 文件 UTF-8 编码,1 位 GBK
draw_type = 0
mode = { --绘制类型表
text = 7,
}
function on_update(slave,vtype,addr)
if addr == 0x1000
then
draw_type = get_uint16(VT_LW, addr)--获取字设置按钮键值
redraw()--绘图
end
end
function on_draw(screen_id,control_id)
local switch = {
[mode.text] = function(control)
if screen_id == 0 and control == 1
then
--绘制文字
draw_text('广州大彩光电科技有限公司\nCopyright? gz-dc.com ', 195, 96, 408 ,318, 0, 32, 0xF800, 5, 1)
end
end,
end
if switch[draw_type]
then
switch[draw_type](control)
end
end
3.11 load_surface (filename)
加载图片到图层
filename:图片文件,支持JPEG/PNG
if surface > 0
then
destroy_surface(surface)
end
surface = load_surface('3:/test.jpg')
[!note|tip:注意]
1.工程有播放视频功能,不支持绘制jpg图片
2.一般用于替换logo,客户从U盘/SD卡拷贝到屏内,替换logo
3.png 比较占运行内存信息
3.12 destroy_surface (surface)
销毁图层
surface:图层资源指针
destroy_surface(surface)
3.13 destroy_all_surface()
销毁所有图层指针
3.14 draw_surface (surface,dstx,dsty,width,height,srcx,srcy)
绘制图层,支持绘制jpg、png格式的图片,在on_draw()系统函数里调用
surface:图层资源指针
dstx:图片显示X坐标
dsty:图片显示Y坐标
width:图片显示宽度[可选]
height:图片显示高度[可选]
srcx:图片裁剪X坐标[可选]
srcy:图片裁剪Y坐标[可选]
例如:
draw_type = 0
surface = 0
mode = { --绘制类型表
surface_path3 = 8,
}
function on_update(slave,vtype,addr)
if addr == 0x1000
then
if surface > 0
then
destroy_surface(surface)
end
surface = load_surface('3:/test.jpg')
--surface = load_surface('1:/test.jpg') --SD卡图片
--surface = load_surface('2:/test.jpg') --U盘图片
redraw()--绘图
end
end
function on_draw(screen_id,control_id)
local switch = {
[mode.surface_path3] = function(control)
if screen_id == 0 and control == 1
then
--绘制图片
draw_surface(surface, 175, 60, 222, 353, 0, 0)
end
end,
end
if switch[draw_type]
then
switch[draw_type](control)
end
end
3.15 get_surface_size (surface)
获取指定图层指针的图像大小,返回,宽度和高度
surface:图层资源指针
local cur_w,cur_h = get_surface_size (surface)
3.16 clear_image_buffer()
清除内部图片资源缓存
3.17 screen_shoot(filepath)
截取整个屏幕的内容,保存为jpg图片。
filepath:图片存储路径
4 数据记录
4.1 record_get_count(sn)
获取该笔资料的记录数
sn:资料记录索引,从0开始
local cnt = record_get_count(idx)
4.2 record_modify_data(sn, index, data)
修改数据记录的内容
[!note|tip:注意]
若开启存储模式,则不允许修改记录
sn:资料记录索引,从0开始
index:记录的行号,从0开始
data:字数组(word),下表从1开始
假设修改第0笔资料,为uint16,共100个数据,则修改第0行记录为1~100实例如下:
for i = 1, 100
do
dataTb[i] = i
end
record_modify_data(0, 0, data)
假设修改第0笔资料,为uint32,共100个数据,则修改第0行记录为1~100实例如下:
for i = 1, 200
do
if i % 2 == 0
then
dataTb[i] = i
else
dataTb[i] = 0
end
end
record_modify_data(0, 0, data)
uint32共100个参数,共占200个字,所有,data的大小为200。依次类推,64位寄存器为400
4.3 record_write_data(sn, data)
添加数据记录的内容
sn:资料记录索引,从0开始
data:字数组(word),下表从1开始
假设第0笔资料为uint16,共100个数据,添加一条记录,则添加内容为1~100实例如下:
for i = 1, 100
do
dataTb[i] = i
end
record_write_data(0, data)
假设第0笔资料为uint32,共100个数据,添加一条记录,则添加内容为1~100实例如下:
for i = 1, 200
do
if i % 2 == 0
then
dataTb[i] = i
else
dataTb[i] = 0
end
end
record_write_data(0, data)
4.4 record_read_data(sn, index)
读取数据记录的内容
sn:资料记录索引,从0开始
index:记录的行号,从0开始
返回两个参数:data, timestamp
data:字数组,数据内容,下标从1开始
timestamp:时间戳,32位
假设第0笔资料为uint16,共100个数据,读取第0笔资料,第1行数据
local data,timestamp = record_read_data(0, 0)
print('size'..(#data))
>size = 100
假设第0笔资料为uint32,共100个数据,读取第0笔资料,第1行数据
local data,timestamp = record_read_data(0, 0)
print('size'..(#data))
>size = 200
4.5 record_modify_string(sn, index, strings)
修改字符串类型的数据记录
[!note|tip:注意]
若开启存储模式,则不允许修改记录
sn:资料记录索引,从0开始
index:记录的行号,从0开始
strings:字符串。每一列用“;”隔开;
--修改第0笔资料,第1行数据的数据为‘item1;item2;item3;item4;item5;’
record_modify_string(0, 0,‘item1;item2;item3;item4;item5;’)
4.6 record_read_string(sn, index)
读取字符串类型的数据记录
sn:资料记录索引,从0开始
index:记录的行号,从0开始
返回两个参数:strings, timestamp
strings:字符串。每一列以“;”隔开
timestamp:时间戳
local strings, timestamp = record_read_string(0, 0)
print(‘strings = ’..strings)
> strings = item1;item2;item3;item4;item5;
4.7 record_write_string(sn, strings)
添加数据记录的内容
sn:资料记录索引,从0开始
strings:字符串,每一列参数以“;”隔开
--第0笔资料,添加一条记录‘item1;item2;item3;item4;item5;’
record_write_string( 0,‘item1;item2;item3;item4;item5;’)
4.8 record_clear(sn)
清除记录
sn:资料记录索引,从0开始
4.9 on_parse_record(index,export,datatb)
资料采样,表格回调。用于自定义格式显示内容
index:资料采集索引
export: 1-导出
datatb:word 数组
假设一个列头柜应用,该系统有144路支路,一个支路有电压(int16,,1位小数),电流(uint16,2位小数)、功率(uint32,3位小数)、电能(uint32,2位小数),4个参数的数据类型、缩放系数不统一,一个支路占用6个字,即144个支路,共占用864个字(连续寄存器地址)。资料采样配置,如下所示:
在Lua脚本回调中,datatb大小为864
若HMI当前没有导出记录,则赋值给全局变量g_switch_datatb = datatb,return nil,并在系统回调on_get_record_channel(index,channel)函数里处理表格显示内容。
若HMI当前需要导出记录,该回调函数会触发N次(当前记录N条记录),并处理144个支路参数的内容
--表格每通道回调
--index:资料采集索引
--channel:通道,显示当前第几通道
function on_get_record_channel(index,channel) --当下发滚动条拖动时候,channel实时变化
if index == 0
then
local val = 0
local byPass = (channel // 4) --1~144
local idx = (channel) % 4 --第几个参数
if idx == 0 --电压 INT16
then
val = g_switch_datatb[(byPass)*6 + 1]
val = ((val & 0x8000) == 0x8000) and ((0xFFFF - val - 1)*(-1)) or val
val = string.format('%0.1f', (val / 10))
elseif idx == 1 --电流 UINT16
then
val = g_switch_datatb[(byPass)*6 + 2]
val = string.format('%0.2f', (val / 100)
elseif idx == 2 --功率 UINT32
then
val = ((g_switch_datatb[(byPass)*6 + 3] << 16) | g_switch_datatb[(byPass)*6 + 4]) & 0xFFFFFFFF
val = string.format('%0.3f', (val / 1000))
elseif idx == 3 --电能 UINT32
then
val = ((g_switch_datatb[(byPass)*6 + 5] << 16) | g_switch_datatb[(byPass)*6 + 6]) & 0xFFFFFFFF --UINT32
val = string.format('%0.2f', (val / 100))
end
return val
end
end
function on_parse_record(index,export,datatb)
local record_msg = ''
if index == 0
then
if export == 0 --非导出
then
g_switch_datatb = datatb
return nil
else --导出,拼接每行数据导出
for i = 1, #datatb, 6
do
local u = datatb[i] --INT16
u = ((u & 0x8000) == 0x8000) and ((0xFFFF - u - 1)*(-1)) or u
local a = datatb[i + 1] --UINT16
local p = ((datatb[i + 2] << 16) | datatb[i + 3]) & 0xFFFFFFFF --UINT32
local e = ((datatb[i + 4] << 16) | datatb[i + 5]) & 0xFFFFFFFF --UINT32
u = string.format('%0.1f', (u / 10))..';'
a = string.format('%0.2f', (a / 100))..';'
p = string.format('%0.3f', (p / 1000))..';'
e = string.format('%0.2f', (e / 100))..';'
record_msg = record_msg..u..a..p..e
end
end
end
return record_msg
end
5 告警
一般情况使用告警设置对话框就可以满足告警需求,不需要使用下面的API。
此处的告警指通过脚本触发告警和动态显示告警内容
用于如下情形:
告警条目比较多,内容具有重复规律,只有细微差异
告警条件具有规律性
5.1 warning_set_mode(en)
开启告警模式之后,warning_set才能生效
en:0关闭,1开启告警触发模式
ENCRYPT_=0 --LUA脚本加密
--数据类型定义
VT_LW = 1 --变量地址
VT_RW = 2 --FLASH存储
function on_init()
warning_set_mode(1) --LUA解析告警
end
5.2 warning_set(warning_id,value,count)
触发或关闭指定id位置的告警,此功能需要提前设置warning_set_mode(1)
warning_id:起始告警id
value: 告警值,对应的bit为1触发告警,为0关闭告警。
count:连续告警个数
--读取寄存器值
local err_val = get_uint16(VT_V, 0x1D00)
--将寄存器值的每一个位,对应到告警0~15范围
warning_set(0, err_val , 16)
5.3 on_parse_warning(id, text)
告警解析回调函数,通过判断告警id,返回描述告警内容的字符串。
参数说明:
warning_id:告警ID
value: 告警内容
返回参数说明:
str:返回的字符串告警内容
encode:字符号编码。选填,默认为UTF8。若encode=1,则表示UTF8编码
_warningTb = {
--1~96
'翅片1温度探头故障',
'翅片2温度探头故障',
'翅片3温度探头故障',
'翅片4温度探头故障',
'回气1温度探头故障',
'回气2温度探头故障',
'回气3温度探头故障',
'回气4温度探头故障',
'排气1温度探头故障',
'排气2温度探头故障',
'排气3温度探头故障',
'排气4温度探头故障',
'蒸发1温度探头故障',
'蒸发2温度探头故障',
'蒸发3温度探头故障',
'蒸发4温度探头故障',
'冷凝1温度探头故障',
'冷凝2温度探头故障',
'冷凝3温度探头故障',
'冷凝4温度探头故障',
'房内温度探头故障',
...
...
...
'室内翅片1探头故障',
'室内翅片2探头故障',
'室内翅片3探头故障',
'室内翅片4探头故障',
}
function on_parse_warning(id, text)
--设备1:id0~id95
--...
--...
--...
--设备8:id673~id768
local slaveId = (id // 96) + 1 --第几个告警
local msgId = id % 96 --告警类型ID
local curWarnMsg = '' --告警描述
msgId = (msgId == 0) and 1 or (msgId + 1)
curWarnMsg = math.ceil(slaveId)..'device : '.._warningTb[msgId]
return curWarnMsg
end
5.4 on_filter_warning(warning_id)
告警过滤回调函数,通过判断告警,返回对应的告警控件。可对告警分类,显示到不同的页面
参数说明:
warning_id:告警ID
function on_filter_warning(warning_id)
print('on filter warning('..warning_id..')')
local ret = 0
local cur_page = get_screen()
if warning_id < 100 and cur_page == 0
then
ret = 1
end
if warning_id > 100 and cur_page == 2
then
ret = 1
end
return ret
end
6 定时器
6.1 start_timer(timer_id, timeout, countdown, repeat)
启动定时器,超时后系统自动调用on_timer
timer_id-定时器ID,0~31
timeout-超时时间,单位毫秒
countdown-0顺计时,1倒计时
repeat-重复次数,0表示无限重复
6.2 stop_timer(timer_id)
停止定时器
timer_id-定时器ID,0~31
6.3 on_timer(timer_id)
定时器超时回调函数
timer_id-定时器ID,0~31
如初始化开启1s超时,无限循环的定时器,则每秒输出“hello lua”
function on_timer(timer_id)
if timer_id == 0
then
print('hello lua!!!')
end
end
function on_init()
start_timer(0, 1000, 0, 0)
end
>hello lua!!!
>hello lua!!!
>...
6.4 get_timer_value(timer_id)
获取定时器当前计时时间,单位毫秒
timer_id-定时器ID,0~31
7 串口
7.1 uart_setup(ch,baudrate,databits,stopbit,parity)
串口参数设置
ch:串口通道,0-主串口
baudrate:波特率值
databits:数据位,7表示7位,8表示8位
stopbit:停止位,0-1bit,1-1.5bit
parity:0-无校验,1-ODD奇校验,2-EVEN 偶校验
[!note|tip:注意]
DCBUS、XGUS协议不支持设置停止位、校验位。固定1个停止位、无校验
7.2 on_uart_recv(ch,packet)
串口接收回调,自定义串口协议模式时才会触发
ch:串口通道,默认0
packet:字节数组,下标从1开始
[!note|tip:自由串口协议]
需要用户处理粘包、分包处理,该串口回调非中断触发
以下面指令格式为例:
HEAD
COMMAND
LENG
DATA1
DATA2
….
CHECKSUM
TIE
0x02
功能码
数据长度
数据1
数据2
…
校验值
0x03
说明:
HEAD:包头-固定值0x02
COMMAD:功能码
LEND:DATA的长度
DATA:N个字节
CHECKSUM:HEAD+COMMAND+LENG+DATA字段,求和后取低8位
TIE:包尾-固定值0x03
_Com_HEAD_ = 0x02 --BT协议数据包头
_Com_TAIL_ = 0x03 --BT协议数据包尾
--串口接收缓存表示
Com.cmd = {
head_tag = 0, --检测头标识
head = 0, --存放头字节
tail = 0, --存放尾字节
buff = {}, --指令缓存
len = 0, --指令长度
datalen = 0 --内容长度
}
-- 校验和
function CheckSum(data)
local result = 0
for i = 1, (#data - 2)
do
result = result + data[i]
end
result = result & 0xFF
return result
end
--BT协议数据包解析
function __ProtocolParse(data)
--用户代码区域,完整一帧指令提取出来,实现用户业务逻辑
end
function Com.dataRecv(packet)
--拼凑数据包
for i = 1, #(packet)
do
Com.cmd.head = packet[i] & 0xFF
if Com.cmd.head == _Com_HEAD_ and Com.cmd.head_tag == 0 --检测到BT帧头
then
Com.cmd.head_tag = 1
end
if Com.cmd.head_tag == 1 --已经检测到帧头
then
Com.cmd.len = Com.cmd.len + 1 --计算指令长度
Com.cmd.buff[Com.cmd.len] = packet[i] -- 填充buff
Com.cmd.tail = packet[i] & 0xFF
if Com.cmd.tail == _Com_TAIL_ ----检测到BT帧尾部
then
Com.cmd.datalen = Com.cmd.buff[3] -- LEND : HEAD + ComAND + DATA的长度
if Com.cmd.datalen == Com.cmd.len - 5 -- LEND = CMD_SIZE - (LENG + CRC_VALUE + TIE)
then
if CheckSum(Com.cmd.buff) == Com.cmd.buff[#Com.cmd.buff - 1]
then
--提取完整的一帧指令
__ProtocolParse(Com.cmd.buff)
end
Com.cmd = { --初始化,情况串口相关标识、缓存区
head_tag = 0,
tail = 0,
buff = {},
len = 0,
datalen = 0
}
end
end
end
end
end
function on_uart_recv(ch,packet)
Com.dataRecv(packet)
end
7.3 uart_send(ch,packet)
发送字节数组
ch:串口通道,默认0
packet:数组,下标从1开始
指令格式说明参考1.8.2章
_Com_HEAD_ = 0x02 --BT协议数据包头
_Com_TAIL_ = 0x03 --BT协议数据包尾
-- 校验和
function CheckSum(data)
local result = 0
for i = 1, (#data - 2)
do
result = result + data[i]
end
result = result & 0xFF
return result
end
function Com.dataSend(func, data)
local buff = {}
local dataLen = 0
if data ~= nil
then
dataLen = #(data)
else
dataLen = 0
end
buff[1] = _Com_HEAD_
buff[2] = func
buff[3] = dataLen
if dataLen > 0
then
for i = 1, #data
do
buff[3 + i] = data[i]
end
end
buff[#buff + 1] = 0xFF
buff[#buff + 1] = _Com_TAIL_
buff[#buff - 1] = CheckSum(buff)
uart_send(0, buff)
end
7.4 set_free_protocol(en)
自定义协议切换,使能后,串口收发通过on_uart_recv(ch,packet),uart_send(ch,packet)处理
en:1-自定义协议,0-源工程配置的协议
如:工程配置modbus协议,在某业务逻辑下,需要切换为私有协议进行通讯,调用set_free_protocol(1) 即可,若该业务逻辑执行完,需要切换为modbus协议,调用set_free_protocol(0) 即可
8 音视频
8.1 play_sound(filename)
播放指定的声音文件,例如播放屏内音频文件
filename:路径
--屏内路径播放:
M:play_sound("3:/sound/welcome.wav")
--SD路径播放:
M:play_sound("1:/welcome.wav")
--U盘路径播放:
M:play_sound("2:/welcome.wav")
8.2 stop_sound()
停止播放
8.3 play_video(file,left,top,width,height)
播放视频,满足如下格式
播放视频
MP4文件
H264编码
音频流为MP3或AAC格式
视频最大分辨率<1280*768
最大帧数<30ps
最大码率<1400
pathname为视频路径
left:起始坐标x
top:起始坐标y
width:视频显示的宽度
height:视频显示的高度
--屏内路径播放:
M:play_sound("3:/video/welcome.mp4")
--SD路径播放:
M:play_sound("1:/welcome.mp4")
--U盘路径播放:
M:play_sound("2:/welcome.mp4")
8.4 pause_video()
暂停视频播放
8.5 resume_video()
恢复视频播放
8.6 stop_video()
停止视频播放
8.7 on_video_notify(msg,v1, v2)
视频播放回调函数
msg:1-播放中,0-播放完毕
v1:当前播放进度,当前已播时长,单位s
v2:播放总进度, 当前视频总时长,单位s
8.8 av_init(show,channel,left,top,width,height)
av 输入初始化
show:0隐藏,1显示
channel:通道编号0/1
left:起始坐标x
top:起始坐标y
width:视频显示的宽度
height:视频显示的高度
8.9 av_get_status()
获取AV播放状态
status = av_get_status()
8.10 av_select(ch)
切换AV通道
ch:0-切换到通道1,1-切换到通道2
av_select(0) --切换到通道1
av_select(1) --切换到通道2
8.11 av_show(show)
显示/隐藏AV播放
show:0-隐藏,1-显示
8.12 video_shoot(filepath, width, height)
截取视频/AV窗口的内容,保存为bmp图片。
注意,默认支持AV截图,视频截图需要特定固件
filepath:图片存储路径
width:宽度
height:高度
8.13 set_color_key(Min_Color,Max_Color,Match)
针对M型系列的视频播放/AV输入功能时,视频图层会一直显示在最上层,此时如果我们将文字等其他图形叠加放在视频控件上显示时,视频图层会将其他图形都覆盖,导致只能显示出视频,而无法显示视频上叠放的其他文字和图形。为此,我司针对有此类需求的客户开发了对应的M系列视频底层播放API接口,来满足此类客户的需求,api函数接口如下所示
参数说明:
Min_Color:24位RGB颜色范围的最小值,例如0x00BFBFBF,R-BF/G-BF/B-BF;
Min_Color:24位RGB颜色范围的最大值,例如0x00C8C8C8,R-C8/G-C8/B-C8;
Match:6位的比较规则101010(2A);10-R/10-G/10-B,代表颜色范围在0x00BFBFBF—0x00C8C8C8之间的颜色值经过比较后会被过滤。(0x00BFBFBF <= color <= 0x00C8C8C8之间的颜色会被过滤,其他颜色会显示出来)
function on_init()
set_color_key(0x00BFBFBF,0x00C8C8C8,0x0000002A)
endCopy
注:set_color_key(Min_Color,Max_Color,Match),此API接口函数必须要放在on_init()系统初始化函数中使用,默认在初始时配置的属性
9 文件系统操作
9.1 dofile(name)
加载lua文件,用于lua脚本分模块编辑,创建的*.lua文件放在工程目录下,在on_init()里调用即可
function on_init()
dofile(‘test.lua’)
end
9.2 list_dir(path)
list_dir('1:') --遍历SD卡文件
list_dir('2:') --遍历U盘文件
list_dir('3:') --遍历屏内文件
遍历指定目录下的文件和文件夹
path:文件路径
filename:文件名称
type:0-文件夹,1-文件
fsize:文件大小
通过以下回调函数返回文件的内容
on_list_dir(path,filename,type,fsize)
9.3 on_list_dir(path,filename,type,fsize)
path-文件路径
filename-文件名称
type-0 文件夹, 1 文件
fsize-文件大小
function on_list_dir(path, filename, type, fsize)
local msg = ''
if type == 0 --文件夹
then
else --文件
msg = path..'/'..file_name --文件路径
end
end
9.4 file_open(path,mode)
打开文件,成功返回true,失败false
path-文件路径
mode-打开模式,如下组合方式
FA_READ
FA_WRITE
FA_WRITE_ADD
0x00
0x01
0x02
--打开文件读(没有文件创建文件):
file_open(path, 0x00)
--打开文件覆盖写(没有文件创建文件):
file_open(path, 0x01)
--打开文件末尾写(没有文件创建文件):
file_open(path, 0x02)
9.5 file_close()
关闭文件,成功返回true,失败false
9.6 file_size()
获取当前文件大小,返回字节数
local file_fd = file_open(path, 0x00)
local filesize = file_size()
9.7 file_seek(offset)
定位文件读取位置,成功返回true,失败false
offset:文件偏移位置
9.8 file_read(count)
读取文件内容,成功返回table数组,字节数组,下标从1开始,失败返回nil
count:读取字节数,最大读取2048个字节
local tb = file_read(2048)
[!note|tip:注意]
每次读取2048个字节,实际使用中,不能将整个文件读出来放在buff缓存在处理,每读一次,处理数据。否者,读取的文件内容大,屏幕内存不够,会重启
9.9 file_write(data)
写文件内容,成功返回true,失败返回false
data-待写入的table数组,索引从1开始,最大一次性写2048个字节
local ret = file_write(write_byte_Tb) -- 1 ≤ data 数组大小 ≤ 2048
return ret
9.10 file_delete(path)
path:待删除的文件路径
file_delete('1:/1.txt')
9.11 file_copy(src_path, dst_path)
src_path:源文件路径
dst_path:目标文件路径
file_copy('1:/1.txt', '1:/1_copy.txt') --从SD卡目录下,复制1.txt为1.copy.txt
9.12 on_copy_file_process(status,filesize,transfersize)
文件拷贝进度,配合 file_copy(src_path, dst_path)使用,当调用 file_copy,自动回调到on_copy_file_process函数
status:状态.0-失败,1-拷贝中,2-拷贝完成
filesize:被拷贝的文件大小
transfersize:当前回调拷贝的字节数
function on_copy_file_process(status,filesize,transfersize)
local progress = 0
if status == 0 -- 复制失败
then
elseif status == 1 --复制中
then
local prg = ((transfersize*100) // filesize) --计算百分比进度
elseif status == 2 -- 复制成功
then
end
refresh_screen()-- 刷新界面
end
10 CAN 接口
10.1 canbus_open(index,baudrate,listen_mode,loop_back)
打开 CANBUS 接口
index:索引号 0~1
baudrate:波特率(单位 K), 可选 125,250,500,1000
listen_mode:只读模式
loop_back:自发自收(环回/自测)
10.2 canbus_close(index)
关闭 CANBUS 接口
index:索引号 0~1
10.3 canbus_write(index,identifier,dlc,rtr,ide,data)
发送 CAN 报文
index:索引号 0~1
identifier:报文 ID
dlc:数据长度
rtr:远程帧
ide:扩展帧
data:数据, table 格式,下标从1开始,table最大8个字节
10.4 on_canbus_recv(index,identifier,dlc,rtr,ide,data)
CAN 报文回调函数, 收到报文后, 系统自动调用
index:索引号 0~1
identifier:报文 ID
dlc:数据长度
rtr:远程帧
ide:扩展帧
data:数据, table 格式,下标从1开始,table最大8个字节
11 设置窗口
API函数中的screen、control参数均表示为目标画面ID、目标组态控件ID。控件ID需要用户编号,默认为0,需要设置非0才生效
11.1 set_screen(screen)
设置当前画面,执行画面切换
screen:目标画面ID
11.2 get_screen()
获取当前画面ID
--EG:
local page = get_screen()
11.3 show_dialog(screen, x, y, alpha)
设置对话框,执行切换对话框操作
screen:画面ID
x,y:左上角起始位置
alph:透明度
show_dialog(0, 184, 108, 50) --显示对话框,坐标(184,105),50%的透明度
show_dialog(-1, 184, 108, 50) ---1,表示关闭对话框,后面参数任意
11.4 wgt_set_pos(screen,control,x,y,w,h)
设置控件的位置
screen:画面ID
control:控件ID
x,y:左上角起始位置
w,h:控件的宽度、高度
--设置画面0控件ID10显示在(476,70)位置,大小为120,36
wgt_set_pos(0,10,476,70,120,36)
11.5 wgt_set_fcolor(screen,control, color)
设置控件的前景色:如文本控件、进度条控件
screen:画面ID
control:控件ID
color:颜色RGB565
--设置画面0控件ID10的前景色
wgt_set_fcolor(0,10,0xF800) --红色
wgt_set_fcolor(0,10,0x07E0) --绿色
wgt_set_fcolor(0,10,0xFFE0) --黄色
11.6 wgt_set_bcolor(screen,control, color)
设置控件的背景色:如文本控件、进度条控件
screen:画面ID
control:控件ID
color:颜色RGB565
--设置画面0控件ID10的背景色
wgt_set_bcolor(0,10,0xF800) --红色
wgt_set_bcolor(0,10,0x07E0) --绿色
wgt_set_bcolor(0,10,0xFFE0) --黄色
11.7 wgt_set_param(screen,control, param,value)
设置控件的属性接口,保留扩展接口
screen:画面ID
control:控件ID
param:设置标识码
0x28:表示数据记录控件的通道翻页
0x31:表示曲线控件的Y轴最小值
0x32:表示曲线控件的Y轴最大值
0x33:GIF播放速度
value:数据内容
--设置画面0,控件ID10的曲线控件最大值、最小值
wgt_set_param(0,10, 0x32,100) --最大值100
wgt_set_param(0,10, 0x31,0) --最小值10
wgt_set_param(0,11, 0x28,-400) --表格向左滚动400个像素
wgt_set_param(0,11, 0x28,400) --表格向右滚动400个像素
wgt_set_param(0,12, 0x33,100) --帧间隔为100ms
11.8 on_wgt_event(screen_id,widget_id,event,value)
窗口设置触发回调,控件id不为0,触碰控件,自动触发该函数
设置控件的属性接口,保留扩展接口
screen:画面ID
control: 控件ID
event:触发的事件
value:单位控件绑定寄存器的值
11.9 refresh_screen()
立即刷新画面
12 简易数据库
ViusualHMI 的数据库是以字符串写入flash,一般屏幕默认为16M。
用户计算需要存储的条数、一条数据的大小。推算出数据库的起始地址。如需要记录1000条记录,每条1000个字节,占用大小为976.5625 k(不满1M)
其中工程4.36M;引导程序(BOOT)+ 固件,一共 1M;至少在6M开始存储。
同时需要考虑资料采集、告警、操作记录等存储控件是否两两交叉。
定义如下:从第10M开始存储,若数据库不存在,新建打开。
db = {}
db.param = {
flashaddr = 10*1024*1024, --从falsh 10M开始存储
createIfNotExist = 1, --数据库不存在,新建
dataRowSize = 1000, --一条记录1000字节
maxCount = 1000, --记录1000条
}
12.1 easydb_open(flashaddr,createIfNotExist,dataRowSize,maxCount)
打开数据库
flashaddr:Flash 地址
createIfNotExist: 0-打开,1-文件不存在创建打开
dataRowSize:一条数据的大小
maxCount:最大数据数
--返回句柄
local dbhandle = easydb_open(flashaddr,createIfNotExist,dataRowSize,maxCount)
12.2 easydb_close(db)
关闭数据库
db:数据库句柄
easydb_close(dbhandle)
12.3 easydb_get_count(db)
获取数据库当前条数
db:数据库句柄
--获取数据库的总条数
function db.getCnt()
local dbhandle = easydb_open(db.param.flashaddr, db.param.createIfNotExist, db.param.dataRowSize, db.param.maxCount)
local ret = easydb_get_count(dbhandle)
easydb_close(dbhandle)
return ret
end
12.4 easydb_get(db,idx)
读取指定行的数据库数据
db:数据库句柄
idx:指定行
--读取:数据库某一条内容
function db.get(idx)
local ret
local dbhandle = easydb_open(db.param.flashaddr, db.param.createIfNotExist, db.param.dataRowSize, db.param.maxCount)
local count = easydb_get_count(dbhandle)
if idx <= count
then
ret = easydb_get(dbhandle, idx-1)
end
return ret
end
12.5 easydb_add(db,dataset)
db:数据库句柄
dataset:添加的内容
--写入:一条数据内容
function db.add(msg)
local ret
local dbhandle = easydb_open(db.param.flashaddr, db.param.createIfNotExist, db.param.dataRowSize, db.param.maxCount)
local count = easydb_get_count(dbhandle)
if count < db.param.maxCount
then
ret = easydb_add(dbhandle, msg)
end
return ret
end
12.6 easydb_update(db,idx,dataset)
修改数据库指定行内容
db:数据库句柄
idx:第几行
dataset:添加的内容
--修改:数据库某一条内容
function db.modify(idx, msg)
local ret
local dbhandle = easydb_open(db.param.flashaddr, db.param.createIfNotExist, db.param.dataRowSize, db.param.maxCount)
local count = easydb_get_count(dbhandle)
if idx <= count
then
ret = easydb_update(dbhandle, (idx - 1), msg)
else
ret = -1
end
return ret
end
12.7 easydb_del(db,idx)
删除数据库指定行内容
db:数据库句柄
idx:第几行
--删除:数据库某一条内容
function db.del(idx)
local ret
local dbhandle = easydb_open(db.param.flashaddr, db.param.createIfNotExist, db.param.dataRowSize, db.param.maxCount)
local count = easydb_get_count(dbhandle)
if idx <= count
then
ret = easydb_delete(dbhandle, idx-1)
else
ret = -1
end
return ret
end
12.8 easydb_clear(db)
清除数据库
db:数据库句柄
--清除:清除数据库
function db.clear(idx)
local dbhandle = easydb_open(db.param.flashaddr, db.param.createIfNotExist, db.param.dataRowSize, db.param.maxCount)
easydb_clear(dbhandle)
end
13 GPIO控制
GPIO控制,需要看硬件是否引出IO引脚,以HMI48272KM043 硬件为例,PD20、PD21,IO定义如下:
16进制的高八位表示IO组,低八位表示引脚
LED1 = 0x0314
LED2 = 0x0315
13.1 gpio_set_in (pin)
PIN引脚设置为输入模式
gpio_set_in(LED1)
gpio_set_in(LED2)
13.2 gpio_set_out (pin)
PIN引脚设置为输出模式
13.3 gpio_set_value (pin,value)
设置输出PIN引脚为(高电平1/低电平0)
gpio_set_value(LED1,0) --IO输出0
gpio_set_value(LED2,1) --IO输出1
13.4 gpio_get_value (pin)
获取输入PIN引脚电平(高电平1/低电平0)
local val = gpio_get_value (LED1)
> val = 1 --逻辑1
> val = 0 --逻辑0
14 其他
14.1 get_platform()
获取屏幕芯片信息,返回字符串类型,设备型号
local device = get_platform()
14.2 get_version()
获取固件版本号,返回数值
local ver= get_version()
14.3 get_device_uuid()
获取设备唯一表示符号,返回长度为20的数字字符串
14.4 reboot()
屏幕复位
14.5 feed_dog()
在某个操作执行耗时超过5秒,需要执行喂狗
for i = 0, 10000 --某循环体大
do
feed_dog()
--do user code
end
14.6 delay_ms(ms)
延时函数,单位ms,延时不宜过长,超过5秒回复位
14.7 set_run_cycle(cycle)
设置on_run的执行周期,毫秒单位。
[!note|tip:注意]
不要在on_run 里面调用set_run_cycle(cycle)
function on_init()
set_run_cycle(1000) --on_run(screen) 1s回调一次
end
14.8 update_system()
立刻加载、写入系统参数。如声音、多语言、音频音量大小、背光设置、用户密码、分期使用参数、配方等
例如:加载系统语言:
function on_init()
set_uint16(VT_LW, 0x011B, (1<<1)) -- 选择需要加载的掩码,bit1,多语言
set_uint16(VT_LW, 0x011A, 0x5502) -- 加载选中的系统参数
update_system()
end
function on_update(slave,vtype,addr)
if vtype == VT_LW
then
if addr == 0x119
then
set_uint16(VT_LW, 0x011B, (1<<1)) -- 选择需要加载的掩码,bit1,多语言
set_uint16(VT_LW, 0x011A, 0x5501) -- 保存选中的系统参数
update_system()
end
end
end
例如:配方清0
for i = 0, 41
do
feed_dog()
set_uint16(VT_LW, 0x1000, i)
update_system()--立刻加载
local recoveryTb = {}
for j = 1, 32
do
recoveryTb[j] = 0
end
set_array(VT_LW, 0x1001, recoveryTb)
set_uint16(VT_LW, 0x1100, 2)
update_system()--立刻写入
end
14.9 get_date_time ()
获取当前日期时间
local year,mon,day,hour,min,sec,week = get_date_time()
14.10 set_date_time (year,mon,day,hour,min,sec)
设置当前日期时间
set_date_time(2023,8,8,8,8,8)
14.11 make_datetime(timestamp)
时间戳转年月日时分秒
local year,mon,day,hour,min,sec = make_datetime(timestamp)
14.12 make_timestamp(year,mon,day,hour,min,sec)
年月日时分秒转时间戳
local timestamp = make_timestamp(year,mon,day,hour,min,sec)
14.13 set_pwd(level,pwd,len)
设置对应等级用户的密码
level: 用户等级0~7
pwd: 用户数字密码
len:选填,前导0,如设置4,密码为123,正确需要输入0123
无前导零,设置修改1级密码并存储,如下所示:
set_pwd(0,123)
set_uint16(VT_LW, 0x011B, (1<<4))-- 选择用户密码系统参数
set_uint16(VT_LW, 0x011A, 0x5501)-- 保存密码
前导零,设置修改1级密码并存储,如下所示:
set_pwd(0,123,4)
set_uint16(VT_LW, 0x011B, (1<<4)) --选择用户密码系统参数
set_uint16(VT_LW, 0x011A, 0x5501) --保存密码
上电加载安全等级密码
function on_init()
set_uint16(VT_LW, 0x011B, (1<<4)) --选择用户密码系统参数
set_uint16(VT_LW, 0x011A, 0x5502) --加载密码
update_system()
end
14.14 set_stage_pwd(level,pwd)
设置对应的分期密码
level: 用户等级0~9
pwd: 用户数字密码
无前导零,设置修改1级密码并存储,如下所示:
set_stage_pwd(0,1234)
set_uint16(VT_LW, 0x011B, (1<<5))-- 选择分期密码系统参数
set_uint16(VT_LW, 0x011A, 0x5501)-- 保存密码
上电加载分期密码
function on_init()
set_uint16(VT_LW, 0x011B, (1<<5)) --选择分期密码系统参数
set_uint16(VT_LW, 0x011A, 0x5502) --加载密码
update_system()
end
14.15 flash_sync()
立刻写入flash
function writeMsgToRw()
rwMsgAddr = 0x4000
for i = 1, 300
do
set_string(VT_RW, rwMsgAddr, fileMsgTb[i])
rwMsgAddr = rwMsgAddr + 16
feed_dog()
end
flash_sync()
end
14.16 md5(text, key)
基于Hash函数和密钥进行消息认证的方法,通过这个算法可以保证通信双方之前交互的消息来自对方并且没有被篡改,返回一个长度为32的16进制字符
text:目标字符串
key:双方规约的密钥
Copyright ©Dacai all right reserved,powered by Gitbook该文件修订时间:
2025-06-23 09:45:08