Tested on the R1.05 test server 2026-10-09..12 with a user project (own objects only); not yet on CI-Eng-Sample (ISS-188). Only results that were tested are included; inferences, code-only and manual-only points and the untested sample layout change were left out. - layouts: 'logout' is a secondary logout, always disabled on the R1.05 web client; 'exit' closes the window and ends the session (ISS-182). - create-display: R1.05 web client table (String items in text vs textField, fixed text alignment, start-hidden limits ISS-183, two visibility conditions, On entry display actions, rectangle blinking, verified connections, first load). - java-class 4a: signal arrays at scale, write on change, attribute arrays, offline javac/javap check; change-reset-class: new signals need the object recreated, attributes lost (ISS-185); opcdbg reset in cmd, TRIGGER_1 via dssqld -m. - string-items (ISS-187), users-groups, modbus-station (400 registers, comm loss), export-dataset (NAME range filter), item-alarming. - new task system-management/package-project.md; tools/ModbusSim.java (tested on R1.05: FC03/04/06/16, exceptions, modes); AMSI (ISS-186). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
139 lines
7.1 KiB
Markdown
139 lines
7.1 KiB
Markdown
---
|
||
task: Modbus TCP station by quick load (line, station, scan type, points, items)
|
||
version: R1.05 (first written for R1.03)
|
||
source: IM 36K10L41-01EN §2, §3.1–3.2, §3.6–3.7; IM 36K10C10-01EN §4.1; practiced on CI-Eng-Sample 2026-09-30
|
||
status: verified on R1.03 (2026-09-30); on R1.05 the datasets, setup files and start scripts were checked identical (2026-10-08, read-only), re-tested on R1.05 2026-10-08 with the reduced sample load on the shared test server (setpoint 1234 read back, COMM_OK 1, eqpdbg slave GOOD; mirror started for the test only; everything removed afterwards)
|
||
---
|
||
|
||
# Modbus TCP station by quick load
|
||
|
||
Uses the CI-Eng-Sample loopback station `CIENG_PLC` as the worked example (files in
|
||
`examples/CI-Eng-Sample/`: `09_modbus_line_df.qli`, `10_modbus_station_df.qli`,
|
||
`11_item_eqp_df.qli`, removal `80_`–`82_`). For a real device, replace the address, unit id,
|
||
points and conversion settings. Works from a normal prompt while CI Server is running; use
|
||
short relative file names.
|
||
|
||
## 1. (Test only) CI Server as its own Modbus slave
|
||
|
||
CI Server ships a Modbus slave "mirror" that needs no hardware:
|
||
- `eqpmdcmem -n EQPMDCMEM`: slave memory (64K registers, 64K bits per unit id; input and
|
||
holding registers are the same memory, as are coils and input bits). The name must be
|
||
`EQPMDCMEM`: the TCP slave looks for it.
|
||
- `eqpmdcslvtcp -n EQPMDCSLVTCP -p 5020`: Modbus TCP listener (default port 502).
|
||
|
||
Started by hand from a normal prompt they run until logoff or CI Server restart. To start
|
||
them with CI Server, an administrator copies `examples/CI-Eng-Sample/equipment/
|
||
eqpciengslv_start.cmd` and `_stop.cmd` to `%TLS_ROOT_PATH%\tls\com`: `equipment_start.cmd`
|
||
runs every `eqp*start.cmd` there. On R1.05 (checked 2026-10-08) it also runs `eqt*start.cmd`
|
||
and, on the host node, every `?*_equipment_start.cmd` (with `?*_equipment_stop.cmd` called
|
||
from `equipment_stop.cmd`), which is a cleaner hook for such extensions.
|
||
|
||
## 2. Line (`MODBUS_LINE_DF`)
|
||
|
||
```
|
||
@FIELDS
|
||
NAME,DESCRIPTION,LINE_TYPE,EQUIPMENT_MAN,HEART_BEAT,TIMEOUT,DEAD_TIME,REPEAT_CONNECTION_DELAY
|
||
|
||
@MODBUS_LINE_DF
|
||
"CIENG_MB_LINE","CI-Eng-Sample Modbus loopback line","TCP/IP","EQPCIENG",100,3000,30,10
|
||
```
|
||
|
||
- `EQUIPMENT_MAN` = equipment manager process name, must start with `EQP`, ≤ 12 characters.
|
||
- Leave `EQUIPMENT_NODE` out: it defaults to the local node (keeps files portable).
|
||
- Loading it **creates** `tls\com\eqpcieng_start.cmd`, `eqpcieng_stop.cmd` and
|
||
`tls\sup\eqpcieng.sup` (written by the CI Service, no admin rights needed) and **starts**
|
||
`eqpmdc -n EQPCIENG` a few seconds later. Wait ~15 s before loading stations.
|
||
|
||
## 3. Station, scan type, points (`MODBUS_STATION_DF`, `MODBUS_SCAN_TYPE_DF`, `MODBUS_POINT_DF`)
|
||
|
||
```
|
||
@FIELDS
|
||
NAME,DESCRIPTION,LINE,PROTOCOL,LINE_1_DEVICE,SUB_STATION_ID,OUTPUT_METHOD,STATUS_ITEM,ON_SCAN
|
||
|
||
@MODBUS_STATION_DF
|
||
"CIENG_PLC","Loopback to CI Server Modbus slave (port 5020)","CIENG_MB_LINE","Open Modbus/TCP","localhost:5020",1,"On change and connect","CI-Eng-Sample.PLC1.COMM_OK",1
|
||
|
||
@FIELDS
|
||
NAME,DESCRIPTION,SCAN_INTERVAL
|
||
|
||
@MODBUS_SCAN_TYPE_DF
|
||
"CIENG_SCAN1S","CI-Eng-Sample 1 s scan",1000
|
||
|
||
@FIELDS
|
||
NAME,STATION,POINT,DESCRIPTION,IO_ADDRESS,EXTERNAL_RELATION,SCAN_TYPE,CONV_TYPE,BITS
|
||
|
||
@MODBUS_POINT_DF
|
||
"CIENG_PLC:SP","CIENG_PLC","SP","Setpoint, holding register 1","RO:1","Output","CIENG_SCAN1S","Binary",16
|
||
"CIENG_PLC:PV","CIENG_PLC","PV","Read-back, input register 1","RI:1","Input","CIENG_SCAN1S","Binary",16
|
||
```
|
||
|
||
- `PROTOCOL`: `Open Modbus/TCP`, `RTU` or `Ascii`. The CI Server TCP slave only answered
|
||
**Open Modbus/TCP** (with `RTU` every request timed out, `EQP-E-TCPRCVTMO`; ISS-024).
|
||
- `LINE_1_DEVICE` `<host>[:<port>]`, default port 502. `SUB_STATION_ID` = Modbus unit id.
|
||
- `STATUS_ITEM`: an existing Boolean item; 1 = communication good, 0 = bad, status 22
|
||
OFFSCAN when off-scan. Load it before the station.
|
||
- Points need `NAME` = `<station>:<point>` as well as `STATION` and `POINT`
|
||
(without it: `DSS-E-PIDX_FST`).
|
||
- Addresses: `DO:n` coil, `DI:n` input bit, `RO:n[,bit]` holding register, `RI:n[,bit]` input
|
||
register (numbers from 1, not 40001/30001). `EXTERNAL_RELATION`: `Input`, `Output`,
|
||
`Input + Output`. `CONV_TYPE`: `Binary`, `Linear` (with `ELEC_LOW/HIGH`, `PHYS_LOW/HIGH`),
|
||
`Float` (`FLOAT_TYPE` Intel, swap words), `Digital`, … (L41 summary §3.3).
|
||
|
||
## 4. Connect items (`ITEM_DF.STATION`, `POINT`)
|
||
|
||
```
|
||
@FIELDS
|
||
NAME,DESCRIPTION,ITEM_REP,VALUE_FORMAT,STATION,POINT
|
||
|
||
@ITEM_DF
|
||
"CI-Eng-Sample.PLC1.SETPOINT","Setpoint written to holding register 1","Integer","99999","CIENG_PLC","SP"
|
||
"CI-Eng-Sample.PLC1.READBACK","Read back from input register 1","Integer","99999","CIENG_PLC","PV"
|
||
```
|
||
|
||
## 5. Test
|
||
|
||
```
|
||
itmval -p -n CI-Eng-Sample.PLC1.SETPOINT -v 1234
|
||
itmval -g -n CI-Eng-Sample.PLC1.READBACK
|
||
itmval -g -n CI-Eng-Sample.PLC1.COMM_OK
|
||
printf '3\n1\n-1\n' | eqpdbg 0 EQPCIENG # slave 1: scan status, line status, request statistics
|
||
```
|
||
|
||
Before the first good scan input items show `off` (offline) and status 13 NOT INIT.
|
||
|
||
**Off-scan / on-scan** (`dssqld -m` with `NAME,ON_SCAN` = 0 or 1): off-scan sets the status
|
||
item to 0 / status 22 OFFSCAN and freezes input items at their last value with the `off`
|
||
flag; a value written to an output while off-scan reached the device after going back
|
||
on-scan (output method *On change and connect*).
|
||
|
||
## 6. Remove (reverse order)
|
||
|
||
1. Items connected to points (`ITEM_DF` names).
|
||
2. Points, then station, then scan type (one file, in that order).
|
||
3. Line: this **stops** the equipment manager and deletes its start/stop scripts, setup file
|
||
and `tls\sav` files.
|
||
4. The status item and section with the other items.
|
||
|
||
## Test system (R1.03, 2026-09-30)
|
||
|
||
Full cycle on CI-Eng-Sample: loaded, `SETPOINT` 1234/4321/2468 and `CMD` 1/0 read back
|
||
through Modbus on `READBACK`/`FEEDBACK`, off-scan/on-scan checked, removed (manager stopped,
|
||
files deleted), reloaded from the sample files and re-tested: all 0 errors. With
|
||
`eqpciengslv_start.cmd`/`_stop.cmd` copied to `tls\com` and CI Server restarted, the mirror and
|
||
`EQPCIENG` started under the CI Service, `COMM_OK` = 1, and the saved setpoint (2468) was
|
||
re-sent to the freshly zeroed slave memory on connect (output method *On change and connect*).
|
||
|
||
## R1.05: a 400-register device (2026-10-12, user project on the R1.05 test server, 2026-10-09 to 10-12)
|
||
|
||
- Own line and equipment manager (`EQUIPMENT_MAN` e.g. `EQP<NAME>`) next to another project's
|
||
line: loaded, removed and loaded again with 0 errors; removing the line stopped only its manager.
|
||
- 400 holding registers as points `RO:1`–`RO:400`, `CONV_TYPE` `Linear` with `HAS_SIGN` 1,
|
||
`ELEC_LOW,ELEC_HIGH` = `-32768,32767` and `PHYS_LOW,PHYS_HIGH` = `-327.68,327.67` (raw ÷ 100):
|
||
all 400 items read the expected signed values (test pattern from a simulator, quality 0,
|
||
status 9).
|
||
- Communication loss: status item 0 (status 4), inputs keep their last value with the `off` option;
|
||
values and status item recover on the next scan after the device answers again.
|
||
- Test without the device: `tools/ModbusSim.java` (Java, runs with CI Server's own JDK; holding
|
||
registers with read and write, scenarios through a mode file). A PowerShell script that opens a
|
||
TCP listener was blocked by Windows antivirus (AMSI) as malicious content on the engineering PC
|
||
(Windows 10).
|