Skip to content

11.6 批量导出所有设备的程序(程序归档 / AI 分析) ​

尊敬的电气工程师:前面 11.2~11.5 是把同一份程序写给一批设备。这一节反过来——把现场所有设备的程序读回来,每台一个文件夹,按序列号归档。

它适合:

  • 备份归档:把一批设备的 Lua 程序和梯形图整体留存,出问题时能比对、能还原。
  • 交给 AI 分析:比如想让 AI 分析各台设备的控制逻辑与数据,找出最优配方——第一步就是把程序都取回来(这正是本节例程的由来)。

批量导出:扫描全部设备 → 逐台读 Lua + 梯形图 → 按序列号存成子文件夹

想要更简洁的写法?

如果您是让 AI 写脚本,或只想用一个文件搞定,直接用 11.7 给 AI 与脚本的调用模板——它用 dev list 一条命令取设备清单,单个 .ps1 即可运行。本页侧重于讲清批量导出的场景与结果。

前置条件 ​

  • lpplc-manager.exe 版本 2026-09-29 或更新(ladder pull 子命令从该版本起提供)。用 lpplc-manager.exe --version 可查看版本;lpplc-manager.exe --commands 能列出全部子命令,看到 ladder pull 就说明支持。
  • 设备与电脑在同一网络(能正常搜索到设备)。云端设备需要先在云参数里配置并连上云。
  • 下面两个文件放在同一个文件夹,且和 lpplc-manager.exe 同目录。

第 1 步:参数文件 程序归档.bat ​

新建文本文档,粘入下面内容,另存为 程序归档.bat(编码 UTF-8)。日常使用只改这 4 行云服务参数(云端设备才需要;只导本地设备可保持默认不动):

bat
@echo off
chcp 65001 >nul
setlocal

REM ===== 云服务连接参数(云端设备才需要改;只导本地设备可不动)=====
set "CLOUD_ADDR=www.lpplc.cn"
set "CLOUD_PORT=5550"
set "CLOUD_USER=你的云用户名"
set "CLOUD_PASS=你的云密码"

REM ===== 主程序:与本 .bat 同目录的 lpplc-manager.exe =====
set "CLI_EXE=%~dp0lpplc-manager.exe"
if not exist "%CLI_EXE%" (
  echo [错误] 没找到 lpplc-manager.exe,请把本脚本放到它旁边。
  exit /b 1
)
set "OUT_DIR=%~dp0程序归档"

powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0程序归档.ps1"
pause

第 2 步:导出脚本 程序归档.ps1 ​

同一个文件夹里新建 程序归档.ps1(编码 UTF-8 带 BOM——中文必须带 BOM,否则 Windows PowerShell 会读成乱码报错)。内容:

powershell
$cli = [System.IO.Path]::GetFullPath($env:CLI_EXE)
$out = [System.IO.Path]::GetFullPath($env:OUT_DIR)
$td  = if ($env:TEMP) { $env:TEMP } else { 'C:\Windows\Temp' }
if (-not (Test-Path $out)) { New-Item -ItemType Directory -Force -Path $out | Out-Null }

# 调用 CLI(lpplc-manager.exe 是界面程序,必须 Start-Process -Wait 等它跑完,stdout 重定向到临时文件再读回)
function Invoke-Cli {
  param([string[]]$CliArgs)
  $tmp = Join-Path $td ('mgr_' + [guid]::NewGuid().ToString('N') + '.json')
  $psi = @{ FilePath = $cli; ArgumentList = $CliArgs; Wait = $true; NoNewWindow = $true
            RedirectStandardOutput = $tmp; RedirectStandardError = ($tmp + '.err') }
  Start-Process @psi | Out-Null
  return (Get-Content $tmp -Raw -ErrorAction SilentlyContinue)
}

Write-Host '[1] 列出设备 ...'
# dev list 一条命令给出干净的设备清单(纯数组),不用解析扫描事件流、也不用担心跨进程设备表
$devJson = Join-Path $td 'devices.json'
Invoke-Cli @('dev', 'list', '--out', $devJson) | Out-Null
$devs = @()
if (Test-Path $devJson) {
  foreach ($x in (Get-Content $devJson -Raw -Encoding UTF8 | ConvertFrom-Json)) { $devs += $x }
}
if ($devs.Count -eq 0) { Write-Host '没扫到设备。'; exit 0 }

$rows = @('序列号,硬件,来源,LUA已拉取,梯形图已拉取')
foreach ($d in $devs) {
  $id = $d.id
  $dir = Join-Path $out $id
  New-Item -ItemType Directory -Force -Path $dir | Out-Null

  # lua pull / ladder pull 一条命令即可:工具按设备的连接方式(UDP / 串口 / 云服务 …)
  # 自动走对应的专用读程序通道,不用您管通道、也不用开透传。
  $luaOut = Invoke-Cli @('lua', 'pull', '--device', $id, '--out', "$dir\main.lua")
  $luaOk = (Test-Path "$dir\main.lua") -and ((Get-Item "$dir\main.lua").Length -gt 0)
  $luaLink = ''
  foreach ($line in ($luaOut -split "`n")) {
    try { $o = ($line.Trim() | ConvertFrom-Json) } catch { continue }
    if ($o.type -eq 'cli_result' -and $o.cli -eq 'lua pull') { $luaLink = $o.link_type }
  }

  Invoke-Cli @('ladder', 'pull', '--device', $id, '--out', "$dir\ladder.il") | Out-Null
  $ladOk = (Test-Path "$dir\ladder.il") -and ((Get-Item "$dir\ladder.il").Length -gt 0)

  $rows += ("{0},{1},{2},{3},{4}" -f $id, $d.hardware, $luaLink, $luaOk, $ladOk)
  Write-Host ("设备 {0} [{1}]  Lua={2}  梯形图={3}" -f $id, $luaLink, $luaOk, $ladOk)
}
$rows | Set-Content (Join-Path $out 'manifest.csv') -Encoding UTF8
Write-Host ('完成,共 ' + $devs.Count + ' 台,归档于 ' + $out)

第 3 步:双击运行 ​

双击 程序归档.bat,脚本自动扫描、逐台读取、按序列号建文件夹。

跑完得到什么 ​

text
程序归档\
├─ 10000001\          ← 以序列号命名
│  ├─ main.lua        ← 该设备的 Lua 程序
│  └─ ladder.il       ← 该设备的梯形图(指令表文本)
├─ 12596159\
│  ├─ main.lua
│  └─ ladder.il
└─ manifest.csv       ← 汇总:每台设备拉没拉到

manifest.csv 用 Excel 打开即可看到每台设备的结果:

text
序列号,硬件,来源,LUA已拉取,梯形图已拉取
10000001,,local,True,True

在软 PLC 模拟器(序列号 10000001)上实测:main.lua 取回真实程序正文(如 -- x023 verify 5 / plc.d(503, 5)),ladder.il 取回指令表(空程序时为 END)。

读不到怎么办

  • 某台显示 False:先看它是否在线且能被搜到(lpplc-manager.exe dev scan)。跨网段、设备掉线都会读不到。
  • 真实 PLC 上梯形图读回时报「接收 FX 应答超时」:多为该设备当时正忙或未响应 FX 握手,稍后重试即可,不是脚本问题。
  • 梯形图是空程序时 ladder.il 内容就是 END,这是正常的(不是失败)。

关于读取 ​

  • 不管设备是网线、WiFi、串口还是 4G 云连接,用 lua pull / ladder pull 即可,工具会按连接方式自动走对应的专用读程序通道——您完全不用关心通道,也不用开透传。
  • 本例程只读取、不写入,不会改动设备,所以不需要 --yes。
  • 读不到会如实告诉您(结果里 False 并带原因),不会生成空文件冒充成功。

和界面操作的关系

界面里也能逐台上载梯形图、读取 Lua。本例程的价值在于"一次把全部设备的程序都拿回来",便于备份或交给 AI 做整体分析;二者底层是同一套读取协议。

LPPLC 工业物联网云平台 · 软硬件与云平台全栈自研