综合平台编程器项目的远程存储
No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.
 
 
 
 

15 KiB

工程 JSON 4.0 格式说明

格式策略

当前只有一个有效工程格式:4.0。代码直接读写本文描述的结构,不为 1.02.03.0 或早期开发草稿增加迁移分支、字段推断或双写逻辑;旧版本加载会明确失败。缺少必填字段、字段类型错误、引用不存在或领域校验失败时,加载必须失败且不得替换当前工程。

顶层结构

{
  "formatVersion": "4.0",
  "id": "project-1",
  "name": "包装线",
  "hmiPages": [],
  "initialHmiPageId": "",
  "alarmDefinitions": [],
  "registerComments": [],
  "controlLogics": []
}

所有顶层字段必填。空工程允许 hmiPagesalarmDefinitionsregisterCommentscontrolLogics 为空,此时 initialHmiPageId 必须为空。存在页面时,initialHmiPageId 必须引用 hmiPages 中的页面 ID。

hmiPagescontrolLogics 都是有序数组。页面顺序用于工程树显示;控制逻辑顺序是离线扫描顺序。对象 ID 稳定且唯一,名称可修改且在同类对象中唯一。

编辑器的当前页面 ID 和当前逻辑 ID 是主窗口会话状态,不进入工程 JSON。每次进入运行态时,HMI 从 initialHmiPageId 重新启动。

HMI 页面与控件

{
  "id": "page-1",
  "name": "主操作页面",
  "width": 800,
  "height": 400,
  "controls": []
}

每个控件都要求 idtypeboundstextbindingpropertiesbounds 包含整数 xywidthheight,矩形必须完整位于页面内。binding 为寄存器对象或 JSON null

页面尺寸是当前 PC HMI 编辑器的业务尺寸,宽度必须为 320~1600,高度必须为 200~800。默认页面尺寸为 800×400;超出范围的 JSON 页面直接加载失败。

properties 保存控件外观扩展属性。当前保留以下 HMI 外观属性名:

属性名 值格式 说明
textColor #RRGGBB 字符串 控件普通文字颜色,缺失时使用控件默认颜色
fontSize 6~72 的十进制数字字符串 控件文字字号
fontBold truefalse 字符串 是否使用粗体
fontItalic truefalse 字符串 是否使用斜体

字体和颜色属于静态显示属性,不参与 M/D 绑定、PLC 轮询和离线控制逻辑。未知扩展属性仍按字符串保留。

type 绑定 额外必填字段
button M 地址或 null 草稿 buttonOperationbuttonEnableCondition
indicator M 地址或 null 草稿
numericDisplay D 地址或 null 草稿 dataType
numericInput D 地址或 null 草稿 dataType
label 必须为 null
statusText M/D 地址或 null 草稿 statusText;D 模式还要求 dataType
pageJump 必须为 null targetPageId
alarmList 必须为 null

type 只接受表中列出的控件类型。其他类型按严格 4.0 规则直接拒绝加载,不做兼容迁移。

数值显示和数值输入控件必须额外保存 dataType,值只能是 int16int32float32float64

{
  "id": "temperature",
  "type": "numericDisplay",
  "bounds": {"x": 20, "y": 20, "width": 160, "height": 40},
  "text": "温度",
  "binding": {"area": "D", "index": 10},
  "properties": {},
  "dataType": "float32"
}

四种数值类型的 JSON 与地址规则如下:

dataType 含义 占用字数 有效起始地址
int16 有符号 16 位整数 1 D0~D4000
int32 有符号 32 位整数 2 D0~D3999
float32 IEEE-754 单精度浮点 2 D0~D3999
float64 IEEE-754 双精度浮点,界面显示为 Double (Float64) 4 偶数首地址 D0~D3996

多字值统一按信捷字序保存:低地址放低 16 位,地址递增时依次保存更高的 16 位。数值控件和 D 状态文本之间允许相同起始地址和相同类型重复绑定,部分重叠或同起始地址不同类型会被拒绝。要求 dataType 的控件缺少该字段或使用 int64 等未知枚举时加载失败。

按钮除了自身的 M 位操作外,还可以保存一个可选的启用条件。没有条件时,buttonEnableCondition 必须为 JSON null;有条件时只能保存一个 mBitdValue 条件:

{
  "id": "start-button",
  "type": "button",
  "bounds": {"x": 20, "y": 20, "width": 120, "height": 40},
  "text": "启动",
  "binding": {"area": "M", "index": 10},
  "properties": {},
  "buttonOperation": "momentaryOn",
  "buttonEnableCondition": {
    "type": "mBit",
    "address": {"area": "M", "index": 0},
    "expected": false
  }
}

mBit 使用 expected 判断 M 位 ON/OFF;dValue 还必须提供 dataTypeoperation 和有限数值 valueoperation 只能是 equalnotEquallessThanlessThanOrEqualgreaterThangreaterThanOrEqual。Int16/Int32 的比较值必须是对应范围内的整数,Float32/Float64 必须是可表示的有限值。条件地址及其连续 D 字会加入真机 PLC 轮询;条件读回失败时运行画面将按钮置灰并禁止操作。

状态文本是独立只读控件。M 模式保存 OFF/ON 文本:

{
  "id": "machine-state",
  "type": "statusText",
  "bounds": {"x": 20, "y": 80, "width": 140, "height": 40},
  "text": "状态文本",
  "binding": {"area": "M", "index": 0},
  "properties": {},
  "statusText": {
    "source": "m",
    "offText": "设备停止",
    "onText": "设备运行"
  }
}

D 模式保存数值类型和 1~16 个连续区间:

{
  "id": "temperature-state",
  "type": "statusText",
  "bounds": {"x": 180, "y": 80, "width": 140, "height": 40},
  "text": "状态文本",
  "binding": {"area": "D", "index": 100},
  "properties": {},
  "dataType": "float64",
  "statusText": {
    "source": "d",
    "ranges": [
      {"lower": null, "upper": 30, "text": "低温"},
      {"lower": 30, "upper": 80, "text": "温度正常"},
      {"lower": 80, "upper": null, "text": "高温"}
    ]
  }
}

D 区间统一按 [lower, upper) 匹配,即包含下限、不包含上限。第一条 lower 必须为 null,最后一条 upper 必须为 null,相邻区间的前一条 upper 必须等于后一条 lower,从而覆盖整个数值域且不留空档、不重叠。Int16/Int32 边界必须为整数,所有边界必须是有限数值。状态结果文本不能为空,只允许单行且最多 256 个 UTF-8 字节。编辑草稿允许 bindingnull,进入运行态前必须绑定;运行读取失败时画面显示 --

按钮操作字符串为 setOnsetOfftogglemomentaryOn。PageJump 使用目标页面稳定 ID,不使用名称或数组位置:

{
  "id": "page-jump-1",
  "type": "pageJump",
  "bounds": {"x": 20, "y": 20, "width": 120, "height": 40},
  "text": "参数设置",
  "binding": null,
  "properties": {},
  "targetPageId": "page-2"
}

编辑草稿允许 targetPageId 为空字符串,但进入运行态前必须配置为现存页面 ID。任何页面被 PageJump 引用时不得删除。

AlarmList 只负责显示项目级当前报警,不保存独立触发逻辑,也不直接绑定单个寄存器。编辑界面的标题输入上限为 12 个字符。多个页面放置 AlarmList 时共享同一组当前报警和确认状态。运行态始终按编辑时设置的位置和尺寸显示控件;有报警时逐行显示,没有报警时显示空状态。每页最多显示 5 条,超出时通过表头翻页按钮查看,记录不会被丢弃。标题和报警文本按单行绘制,空间不足时显示省略号。报警恢复后对应记录立即移除,不改变控件的可见性和尺寸。

报警定义

{
  "id": "alarm-1",
  "address": {"area": "M", "index": 0},
  "condition": "mOn",
  "threshold": 0,
  "message": "急停已按下"
}

alarmDefinitions 是项目级有序数组,报警 ID 必须唯一。触发条件只包含当前业务需要的四种:

condition 地址区域 触发规则
mOn M 位值为 ON
mOff M 位值为 OFF
dHigh D 字值大于等于 threshold
dLow D 字值小于等于 threshold

threshold 使用有符号 16 位范围;M 报警仍保留该必填字段但不参与判断。报警文本不能为空,编辑界面的输入上限为 20 个字符。运行界面按单行绘制,超出当前消息列宽度时显示省略号。发生时间、活动状态、确认状态和清除时间属于运行会话,不进入工程 JSON。

地址注释与网络注释

registerComments 是工程级 M/D 地址元数据数组。每个元素必须包含有效的 address 和非空 text,同一地址只能出现一次。软元件注释只能使用单行文本,不能包含回车或换行,且不能超过 64 个 UTF-8 字节:

{
  "address": {"area": "M", "index": 0},
  "text": "启动按钮"
}

注释不保存寄存器当前值,也不自动把地址加入 Modbus 轮询。网络注释使用网络首行的 LadderRung.comment 保存,与行 ID、名称、连续网格和输出并列;通过任意竖线连接到上一行的支路行必须保存空字符串。同一网络只有首行注释可以非空,违反该规则的 4.0 工程直接拒绝加载,不迁移或回退。网络注释允许为空;非空时只能使用单行文本,不能包含回车或换行,且不能超过 128 个 UTF-8 字节:

{
  "id": "rung-1",
  "name": "启动网络",
  "comment": "启动按钮接通后延时启动",
  "cells": [
    {"id":"cell-0","kind":"gap"}, {"id":"cell-1","kind":"gap"},
    {"id":"cell-2","kind":"gap"}, {"id":"cell-3","kind":"gap"},
    {"id":"cell-4","kind":"gap"}, {"id":"cell-5","kind":"gap"},
    {"id":"cell-6","kind":"gap"}, {"id":"cell-7","kind":"gap"},
    {"id":"cell-8","kind":"gap"}, {"id":"cell-9","kind":"gap"}
  ],
  "output": null
}

控制逻辑

{
  "id": "logic-1",
  "name": "主控制逻辑",
  "enabled": true,
  "rungs": []
}

enabled 决定离线执行器是否扫描该逻辑。所有启用逻辑按 controlLogics 数组顺序执行;禁用逻辑仍要求 ID、名称、行和连续网格结构合法,但允许保留未完成节点作为草稿。

控制逻辑初始可以没有行,rungs 为空不是错误。编辑器第一次添加条件、横线或输出时才创建行;删除最后一行后可以再次保存为空逻辑。没有输出的空行草稿允许保存 10 个 Gap 网格。输出行也允许暂存未完成的条件路径;运行时 Gap 会按断路处理,只有实际导通的输出槽才执行。

4.0 使用连续网格模型。每条 LadderRung 固定保存 10 个 cells,每格的 kindgapwirenode;条件节点直接嵌在 node 格中。行不再是互相隔离的网络容器,行间连接由控制逻辑的 verticalConnections 保存。长竖线由多个相邻连接对象组成,插入行会拆分原连接,删除行只在上下两段同列存在时合并。4.0 不把 ConditionExpression 写入工程 JSON,也不读取旧 condition 字段:

{"id":"vertical-1","upperRungId":"rung-1","lowerRungId":"rung-2","columnBoundary":2}

每行 cells 必须严格为 10 个。鼠标拖动会逐格设置横线或空白,删除横线只恢复目标格;竖线连接的行在执行器中共享列边界电源。

每个 cells 元素只描述一个固定列,例如 {"id":"cell-1","kind":"wire"}{"id":"cell-2","kind":"gap"},或者带 node 对象的 kind":"node"。横线和空白不使用 columnSpan;每个格子固定占用一列。Gap 表示明确断路,可以保存和重新加载;执行器遇到 Gap 时该行电源在此处断开,允许作为未完成草稿或并联网络中的断路支路。

单个行前 10 列是条件区,第 11 列固定放输出指令。空白格可作为编辑草稿,输出行中的断路会让该支路不导通。左右母线、格子端子和竖线均按网格模型绘制,画布像素坐标和运行轨迹不进入 JSON;横线和断路不绑定寄存器,也不产生 M/D 轮询地址。节点配置的类型和值域如下:

{"type": "contact", "address": {"area": "M", "index": 0}, "mode": "normallyOpen"}
{"type": "edgeContact", "address": {"area": "M", "index": 0}, "mode": "rising"}
{"type": "edgeContact", "address": {"area": "M", "index": 0}, "mode": "falling"}
{"type": "compare", "address": {"area": "D", "index": 0}, "comparison": "greaterThanOrEqual", "value": 10}
{"type": "coil", "address": {"area": "M", "index": 1}, "mode": "normal"}
{"type": "move", "source": {"kind": "register", "address": {"area": "D", "index": 1}}, "destination": {"area": "D", "index": 2}}
{"type": "arithmetic", "operation": "add", "left": {"kind": "register", "address": {"area": "D", "index": 2}}, "right": {"kind": "constant", "value": 1}, "destination": {"area": "D", "index": 2}}

当前 LogicNodeConfig 只接受 contactedgeContactcoilcomparemovearithmetictimerContactcounterContacttoncounter 等未支持类型会使工程加载失败,不会被忽略或自动迁移。触点模式为 normallyOpen / normallyClosed,边沿模式为 rising / falling,线圈模式为 normal / set / reset;比较运算支持 equal / notEqual / lessThan / lessThanOrEqual / greaterThan / greaterThanOrEqual,算术运算使用 add / subtract。上升沿和下降沿在离线执行器及真机本地推算中产生一次扫描脉冲。

MOVE、ADD 和 SUB 只能把结果写入 D 地址,源操作数和算术左右操作数可以是有符号 16 位常量或 D 地址。指令仅在所在网络条件成立时执行;ADD/SUB 使用更宽中间类型计算,结果超出 -32768~32767 时饱和到对应边界,并在本地运行轨迹中记录 overflow: true,不会中止扫描。真机本地推算时这些结果只写临时仓库,不写 PLC。

校验与读写

保存顺序为领域校验、JSON 序列化、QSaveFile 原子提交。加载顺序为 JSON 语法、formatVersion、必填字段和类型、领域关系校验,全部成功后才替换当前工程。

工程保存允许未绑定的寄存器控件和未完成梯形图草稿。进入离线运行还必须通过运行校验:所有 HMI 寄存器控件完成绑定、所有 PageJump 目标有效、所有报警定义合法、所有启用逻辑中的节点已配置;Gap 仍表示断路并会让该支路不导通,不会被当成隐含横线。禁用草稿逻辑不阻止运行。左侧电源线直接接通的输出必须保存为 10 个 Wire 网格加输出槽。

当前实现只读写本文定义的严格 4.01.02.0 或其他旧工程不会自动迁移,加载时直接返回不支持的格式版本。