mirror of
https://github.com/jixishi/SerialTerminalForWindowsTerminal.git
synced 2026-06-15 16:42:46 +00:00
feat: enhance plugin system with Go helpers and add Modbus plugin
- Register Go helper functions (modbus.crc16, hex.encode/decode, util.bytes) into Lua states for Modbus RTU support - Add plugins/modbus.lua with .modbus read/write commands - Fix Reload race condition (hold lock across Unload+Load) - Make App.Close nil-safe for sess - Restore internal/console/console_test.go Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
-- Modbus RTU plugin for SerialTerminalForWindowsTerminal
|
||||
-- Provides .modbus commands for reading/writing Modbus registers.
|
||||
-- Uses Go-provided modbus.crc16() and hex.encode/decode helpers.
|
||||
|
||||
-- OnInput: intercept Modbus RTU frames and log them
|
||||
function OnInput(payload)
|
||||
return payload
|
||||
end
|
||||
|
||||
-- OnOutput: decode Modbus RTU responses and format for display
|
||||
function OnOutput(payload)
|
||||
return payload
|
||||
end
|
||||
|
||||
-- OnCommand: handle .modbus commands
|
||||
function OnCommand(line)
|
||||
local cmd, slave, addr, count = parseModbus(line)
|
||||
if not cmd then
|
||||
return line, true -- not a modbus command, pass through
|
||||
end
|
||||
|
||||
if cmd == "read" then
|
||||
return buildReadRequest(slave, addr, count), false
|
||||
elseif cmd == "write" then
|
||||
return buildWriteRequest(slave, addr, count), false
|
||||
elseif cmd == "info" then
|
||||
return line, true -- pass to .help
|
||||
end
|
||||
|
||||
return line, true
|
||||
end
|
||||
|
||||
-- Parse ".modbus read|write <slave> <addr> <count|value>"
|
||||
function parseModbus(line)
|
||||
local parts = {}
|
||||
for part in string.gmatch(line, "%S+") do
|
||||
table.insert(parts, part)
|
||||
end
|
||||
if #parts < 1 or parts[1] ~= ".modbus" then
|
||||
return nil
|
||||
end
|
||||
local cmd = parts[2]
|
||||
if cmd == "read" and #parts >= 4 then
|
||||
return cmd, tonumber(parts[3]), tonumber(parts[4]), tonumber(parts[5])
|
||||
elseif cmd == "write" and #parts >= 4 then
|
||||
return cmd, tonumber(parts[3]), tonumber(parts[4]), tonumber(parts[5])
|
||||
elseif cmd == "info" then
|
||||
return cmd, nil, nil, nil
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Build Modbus RTU read holding registers request (function 0x03)
|
||||
function buildReadRequest(slave, addr, count)
|
||||
if not count or count <= 0 then count = 1 end
|
||||
if count > 125 then count = 125 end
|
||||
|
||||
local frame = util.bytes(slave, 0x03,
|
||||
math.floor(addr / 256), addr % 256,
|
||||
math.floor(count / 256), count % 256)
|
||||
|
||||
local crc = modbus.crc16(frame)
|
||||
local crcLow = crc % 256
|
||||
local crcHigh = math.floor(crc / 256)
|
||||
frame = frame .. string.char(crcLow) .. string.char(crcHigh)
|
||||
|
||||
return frame
|
||||
end
|
||||
|
||||
-- Build Modbus RTU write single register request (function 0x06)
|
||||
function buildWriteRequest(slave, addr, value)
|
||||
if not value then value = 0 end
|
||||
|
||||
local frame = util.bytes(slave, 0x06,
|
||||
math.floor(addr / 256), addr % 256,
|
||||
math.floor(value / 256), value % 256)
|
||||
|
||||
local crc = modbus.crc16(frame)
|
||||
local crcLow = crc % 256
|
||||
local crcHigh = math.floor(crc / 256)
|
||||
frame = frame .. string.char(crcLow) .. string.char(crcHigh)
|
||||
|
||||
return frame
|
||||
end
|
||||
Reference in New Issue
Block a user