ci-server-engineer/.claude/skills/equipment/tasks/modbus-station.md
cliu 516729ff24 R1.05 findings from a user project (tested only)
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>
2026-10-09 21:57:08 +11:00

7.1 KiB
Raw Blame History

task version source status
Modbus TCP station by quick load (line, station, scan type, points, items) R1.05 (first written for R1.03) 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 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).