This is the complete API manualfor the Lua script of the VisualHMI platform: 10 system callback functions + 32 read-write register functions + 10 drawing functions, totaling 52 interfaces. Before writing scripts, review this document, which is faster than going through the tutorials one by one. The platform is based on Lua 5.3.
0. Basics: The automatically generated main.lua
menu: Project → Script Programming. By default, main.lua is generated, automatically including the data type definitions corresponding to the protocol:
ENCRYPT_ = 0 -- LUA脚本加密开关 -- 数据类型定义(随协议变化,以下为 Modbus) 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
Under the FX3U protocol, there are also types such as VT_M (internal relay) and VT_D (D register). The first parameters of the vtype, get/set functions in on_update use these constants.
1. Common callback functions (10)
| Callback | Trigger timing | Key points |
|---|---|---|
on_init() | Immediately execute once after the system loads LUA | Initialize, dofile to load other Lua scripts, and write initial values |
on_run(screen) | Each main loop cycle automatically calls | core cycle scheduling. It is prohibited to use delay_ms/long loops/network synchronization/internal set_run_cycle(); when acting as a Modbus master, avoid high-frequency writes to slaves (bus congestion) |
on_update(slave,vtype,addr) | . Register/variable value changes trigger | data-driven non-polling. Serial port/Modbus master writes and set_xxx in on_update do not trigger (to prevent recursion); the global EN_ON_UPDATE_API_CB can be used to control the switch |
on_screen_change(screen) | . After the screen transition is complete, | initialization/state synchronization/resource loading |
on_press(state,x,y) | . Touch state changes are triggered at most once every 100ms | . state: 0 for lifted/1 for pressed/2 for long pressed (pressed only triggers once); underlying coordinates, tapping on empty space also triggers |
on_usb_inserted(driver) | . U-disk insertion recognition | . driver is the drive letter, M series is "2:", recorded using a global variable |
on_usb_removed() | . U-disk unplugged | . Clear the drive letter global variable |
on_sd_inserted(dir) | SD card insertion recognition | dir drive letter, M series is "1:" |
on_sd_removed() | SD card removal | clear drive letter global variable |
on_parse_timestamp(screen,control,timestamp) | format time field of alarm/data/operation record table | control must not be equal to 0; paired with make_datetime(timestamp) to return a custom time string |
2. Read-write register functions (32 in total)
2.0 First, let's discuss two key mechanisms (common to all set/get functions)
Mechanism 1: get_xxx() has zero communication overhead.The get series all read from the HMI local cache (memory mapping) without generating serial port frames. The HMI background task automatically reads communication variables (such as VT_3x/VT_4x of Modbus) from the PLC and caches them according to the polling period configured by the project. If a screen control is bound to a certain address, that address will automatically be added to the polling list; if a script needs to read an address not referenced by the project, it can explicitly request synchronization using start_read.
Mechanism 2: set_xxx() does not necessarily send serial port frames.Only when both conditions are met will a message be actively sent: ① the HMI is in host mode (Modbus Master/DCBUS/XGUS); ② serial port notifications have not been disabled by set_notify(0). In slave mode, set only updates the local mapping.
2.1 Communication Control
| Function | Parameter | Description |
|---|---|---|
set_notify(enable) | 0: Disable / 1: Enable (Default) | Global Serial Port Notification Switch. After setting_notify(0), set_xxx does not send serial port commands. To restore, set_notify(1) |
select_slave(slave_id) | Slave Index Starting from 0 | Switch the subsequent get/set access to the slave in multi-slave mode. slave_id is the index of the slave list array in the project, not the Modbus station number |
set_endian(en) | 0: Big-endian (Default) / 1: Little-endian | Byte order for multi-byte data (uint16/32/float) exchanged with the slave. Only effective when the communication protocol involves multi-byte data |
start_read(index,vtype,addr,quantity,cycle,cycle_run,mode) | index: 0~127; quantity: 1~120; cycle: polling multiplier (Default 0=every cycle); cycle_run: the number of times within the cycle (0-based); mode: 0: Continuous / 1: Only once | Host mode: Background automatic polling. No return value, data is read from the cache using get_xxx. mode=1 requires creating_resp_que() first |
stop_read(index) | Task Index | Stop specifying background read tasks, cache retains the last value |
stop_all_read() | - | Stop all script-initiated read tasks |
set_auto_read(en) | 1: Enabled (default)/0: Disabled | Overall switch for automatic polling of screen binding variables. 0: Fully managed by start_read |
create_resp_que() | - | Create a response queue, coordinate with start_read(mode=1) for single-time on-demand reading |
on_cmd_resp(slave,vtype,addr,count,ret,wr) | ret: 0 for success/1 for exception; wr: 0 for read/1 for write | Asynchronous callback for host mode communication results, triggered by receiving a response or timeout. Determine the success or failure of single read/write operations |
set_slave_site(idx,slave_id) | idx: Slave index; slave_id: New station number (Modbus 1~247) | Dynamically change the slave station number during runtime to adapt to on-site networking |
2.2-bit operation
| Function | Parameter | Description |
|---|---|---|
set_bit(vtype,addr,value,count) | value 16-bit unsigned, with the lower count bits corresponding to the target bits (bit0→addr, bit1→addr+1, etc.); count optional 1~16 | Batch bit write. Modbus coil, X/Y/S/M of FX3U are all supported. Write multiple switches in one communication |
get_bit(vtype,addr) | - | Read a single bit, return 0/1. Read from local cache, with zero communication overhead |
2.3 Numerical read and write (16/32/64 bits)
| Function | Numerical range | Address span |
|---|---|---|
set/get_uint16(vtype,addr,value) | 0~65535, truncated & 0xFFFF if exceeded | 1 register |
set/get_int16(vtype,addr,value) | -32768~+32767, truncated & 0xFFFF if exceeded | 1 register |
set/get_uint32(vtype,addr,value) | 0~4294967295, truncated & 0xFFFFFFFF | 2 registers |
set/get_int32(vtype,addr,value) | -2^31~2^31-1 | 2 registers |
set/get_uint64(vtype,addr,value) | 0~2^64-1 | 4 registers |
set/get_int64(vtype,addr,value) | -2^63~2^63-1 | 4 registers |
set/get_float(vtype,addr,value) | IEEE 754 single precision | 2 registers |
set/get_double(vtype,addr,value) | IEEE 754 double precision | 4 registers |
All get series read local cache; set series communication triggers refer to "Mechanism 2".
2.4 Strings and batching
| Functions | Parameters | Description |
|---|---|---|
set_string(vtype,addr,str) | str max 2K bytes, UTF-8 or GBK | Write string to address sequence |
get_string(vtype,addr,len) | len optional, default 128 bytes, max 2048 | Read string, automatically truncated |
set_uint16_ex(vtype,addr,value1,...,valueN) | up to 120 values | Variable parameter batch write to consecutive registers, suitable for fixed parameter sets |
set_array(vtype,addr,buff) | buff is a Lua table (word array) with a maximum of 120 characters. | Batch writing of tables, suitable for programmatic generation/dynamic data. The difference from set_uint16_ex lies in the parameter passing method. |
3. Drawing functions (10)
All draw_xxx functions must be called within theon_draw(screen_id,control_id)callback to take effect, and the control ID must be ≠ 0. Layers are managed according to the control Z-axis (editor stacking order), and drawing is layered based on the control_id. The active refresh callsredraw().
| function | with parameter | description |
|---|---|---|
set_pen_color(color) | RGB565: high 5 bits R (0~31)/middle 6 bits G (0~63)/low 5 bits B (0~31) | to set the brush (foreground) color. Red 0xF800, green 0x07E0, blue 0x001F, white 0xFFFF, black 0x0000 |
draw_line(x0,y0,x1,y1,width) | width 1~10 | draws a straight line, using the current brush color |
draw_rect(x0,y0,x1,y1,fill) | fill 1 filled/0 border | top left + bottom right coordinates |
draw_rect_alpha(x0,y0,x1,y1,alpha) | alpha 0~255 (0 transparent/255 opaque) | semi-transparent solid rectangle, commonly used in mask layers |
draw_circle(x,y,r,fill) | fill 0 solid/non-0 hollow (value as line thickness) | center + radius |
draw_ellipse(x0,y0,x1,y1,fill) | fill 0 solid/non-0 hollow | bounding rectangle defines ellipse |
draw_image(image_id,frame_id,dstx,dsty,width,height,srcx,srcy) | image_id check in build/image.xml; frame_id animation frame (non-animation=0) | draw image, supports scaling + cropping. image_id check in image.xml in the project build directory |
draw_text(text,x,y,w,h,font_id,size,color,align,charcode) | align 0 left/1 center/2 right; charcode 0=UTF-8 (default)/1=GBK | regional text drawing, supports multi-byte characters |
draw_surface(surface,x,y,w,h,srcx,srcy) | surface is a screen/canvas resource | for screen cropping display and multi-layer composition. |
4. Drawing Example: Switch Table-Driven
All drawing examples in the source text follow the same pattern: read button key values in on_update → redraw() → check the switch table for the key values in on_draw to select the drawing function. Taking drawing a line and a circle as an example:
draw_type = 0
mode = { line = 1, rect = 2, rect_alpha = 3, circle = 4, ellipse = 5, imageId = 6, 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.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,
[mode.circle] = function(control)
if screen_id == 0 and control == 1 then
draw_circle(300, 253, 100, 0) -- 实心圆
draw_circle(450, 253, 150, 1) -- 空心圆,线厚1
end
end,
}
if switch[draw_type] then switch[draw_type](control_id) end
endCompiled from VisualHMI development documentation of Guangzhou Dacai Technology (hmi-doc.gz-dc.com) LUA tutorial "Lua Script API Function Interface", copyright reserved by Dacai Technology.
Leave a Reply