Why Your S6F11 Never Arrives: Getting S2F33, S2F35 and S2F37 in the Right Order
Your report is defined but S6F11 never arrives. Real S2F33, S2F35 and S2F37 captures from two equipments, and what a non-zero LRACK tells the host.
The MES side is written. You define a report, attach it to a CEID, send the enable. All three messages came back answered and all three answers ended in 00. And not one S6F11 has arrived. There is no equipment to plug into — only a simulator.
The mistake host developers make most often here is treating those three messages as independent. They are not. S2F35 refers to an RPTID that must already be defined, and S2F37 refers to a CEID that should already be linked. Reverse the order and you are sending a message whose referent does not exist — and what comes back then, which is the whole point, depends on the equipment implementation.
So I pushed the same frames in the same order at two equipments. One answers 00 to anything you send it. The other rejects with LRACK 5. Same host code, same bytes, different answers.
The three messages are chained by reference
What define, link and enable each do, and why the whole setup evaporates after a tool restart, is already covered in the article on event report links. That one shows the bytes the host sends and stops there without answers — the listener it ran against had no SECS-II responder. This article is the answer side: what actually rides in DRACK, LRACK and ERACK.
The reference chain, restated:
- S2F33 binds a VID list to one RPTID. The equipment has to own those VIDs.
- S2F35 binds an RPTID list to one CEID. Those RPTIDs must already exist from S2F33.
- S2F37 carries CEED (TRUE/FALSE) and a CEID list. No RPTID appears in it at all.
That third item is the trap. S2F37 knows nothing about reports. It switches CEIDs on and off. So there is no ground for the equipment to reject an enable on a CEID with no link, and it does not reject it. The host gets ERACK 0, believes the setup is complete, and the equipment has no report to attach and sends nothing. Half of "I got ERACK 0 and no S6F11" is exactly this.
The permissive equipment: wrong order, all zeros
First the SECS/GEM simulator's EQ1 passive listener (127.0.0.1:5501, SessionID 11, no fault modes). Select and S1F13 get the session to COMMUNICATING — SELECTED is not COMMUNICATING — and then I deliberately inverted the order: link RPTID 700, never defined, to CEID 1101.
TX S2F35 W 00 00 00 24 00 0B 82 23 00 00 00 00 04 03
01 02 B1 04 00 00 00 01
01 01 01 02 B1 04 00 00 04 4D 01 01 B1 04 00 00 02 BC
RX S2F36 00 00 00 0D 00 0B 02 24 00 00 00 00 04 03 21 01 00
The body is <L [2] <U4 1> <L [1] <L [2] <U4 1101> <L [1] <U4 700>>>>>. 00 00 04 4D is CEID 1101, 00 00 02 BC is RPTID 700. RPTID 700 was never defined in this session.
The answer is 21 01 00 — a one-byte binary item, value 0. LRACK 0, accepted. The enable goes through too.
TX S2F37 W 00 00 00 17 00 0B 82 25 00 00 00 00 04 04 01 02 25 01 01 01 01 B1 04 00 00 04 4D
RX S2F38 00 00 00 0D 00 0B 02 26 00 00 00 00 04 04 21 01 00
25 01 01 is CEED TRUE. ERACK 0. And sending the identical S2F33 twice in a row gets DRACK 0 both times.
TX S2F33 W 00 00 00 2A 00 0B 82 21 00 00 00 00 04 06
01 02 B1 04 00 00 00 01
01 01 01 02 B1 04 00 00 02 BC 01 02 B1 04 00 00 00 64 B1 04 00 00 00 65
RX S2F34 00 00 00 0D 00 0B 02 22 00 00 00 00 04 06 21 01 00
This listener returns 21 01 00 to S2F33, S2F35 and S2F37 unconditionally. It is not imitating an equipment, it is satisfying the ack shape — which makes it the worst possible partner for a host developer. Run your integration tests only here and the whole class of ordering bugs stays invisible until the first real tool.
The strict equipment: LRACK 5, DRACK 3, LRACK 4
The second partner is the secs-gem-equipment 0.1.0 package from the same repository, running as a listener on 127.0.0.1:5599 with SessionID 0. It owns two CEIDs, 10001 (START) and 10002 (STOP), and three VIDs: 1 (CONTROL_STATE), 2 (PROCESS_STATE), 3 (PROCESS_EVENT). Same inverted order first.
TX S2F35 W 00 00 00 24 00 00 82 23 00 00 00 00 04 03
01 02 B1 04 00 00 00 01
01 01 01 02 B1 04 00 00 27 11 01 01 B1 04 00 00 02 BC
RX S2F36 00 00 00 0D 00 00 02 24 00 00 00 00 04 03 21 01 05
00 00 27 11 is CEID 10001 and 00 00 02 BC is RPTID 700 again. The answer is 21 01 05 — LRACK 5, which in this implementation means at least one RPTID in the link is not defined. Same host frame as before, different answer.
Then the line that matters most here. Enable the CEID whose link just failed:
TX S2F37 W 00 00 00 17 00 00 82 25 00 00 00 00 04 04 01 02 25 01 01 01 01 B1 04 00 00 27 11
RX S2F38 00 00 00 0D 00 00 02 26 00 00 00 00 04 04 21 01 00
ERACK 0. Even the strict equipment does not object, because S2F37 carries no RPTID and has nothing to object with. The host log records "enable OK" and S6F11 never comes.
Now in order. Define RPTID 700 as VID 1 and VID 2.
TX S2F33 W 00 00 00 2A 00 00 82 21 00 00 00 00 04 05
01 02 B1 04 00 00 00 01
01 01 01 02 B1 04 00 00 02 BC 01 02 B1 04 00 00 00 01 B1 04 00 00 00 02
RX S2F34 00 00 00 0D 00 00 02 22 00 00 00 00 04 05 21 01 00
DRACK 0. Send the same message once more:
RX S2F34 00 00 00 0D 00 00 02 22 00 00 00 00 04 06 21 01 03
DRACK 3 — that RPTID is already defined. Define a different report with a VID the equipment does not have, 99, and a different value comes back.
TX S2F33 W 00 00 00 24 00 00 82 21 00 00 00 00 04 07
01 02 B1 04 00 00 00 01
01 01 01 02 B1 04 00 00 02 BD 01 01 B1 04 00 00 00 63
RX S2F34 00 00 00 0D 00 00 02 22 00 00 00 00 04 07 21 01 04
00 00 00 63 is VID 99. DRACK 4, and RPTID 701 (02 BD) is not created. Note what that implies: rejection is per message. Pack five reports into one S2F33, get one VID wrong, and none of the five exist afterwards.
With the definition in place the link goes through.
RX S2F36 00 00 00 0D 00 00 02 24 00 00 00 00 04 08 21 01 00
LRACK 0. Repeat the same link and you get 21 01 03 — LRACK 3, the CEID is already linked. Link CEID 9999 (00 00 27 0F), which does not exist, and you get 21 01 04 — LRACK 4.
One line per value. What follows is the meaning this equipment's code assigns; I have not checked these against the wording of the DRACK/LRACK/ERACK definitions in the SEMI E5 text.
| Value | S2F34 DRACK | S2F36 LRACK |
|---|---|---|
| 0 | accepted | accepted |
| 2 | item structure not as expected | item structure not as expected |
| 3 | RPTID already defined | CEID already linked |
| 4 | no such VID | no such CEID |
| 5 | — | RPTID not defined |
S2F38 ERACK has only two values in this implementation: 0 (accepted) and 1 (no such CEID, or CEED was not a BOOLEAN).
What S6F11 looks like once the order is right
After define → link → enable, S1F17 puts the equipment in ON-LINE REMOTE and S2F41 START goes out. HCACK 0 comes back — HCACK 2 and control states are a separate story — and the event follows immediately.
RX S6F11 W 00 00 00 2A 00 00 86 0B 00 00 00 00 00 01
01 03 B1 04 00 00 00 01
B1 04 00 00 27 11
01 01 01 02 B1 04 00 00 02 BC 01 02 A5 01 05 A5 01 03
TX S6F12 00 00 00 0D 00 00 06 0C 00 00 00 00 00 01 21 01 00
The body is <L [3] <U4 1> <U4 10001> <L [1] <L [2] <U4 700> <L [2] <U1 5> <U1 3>>>>>: DATAID 1, CEID 10001, and one report — RPTID 700 holding the values of VID 1 and VID 2 in the order the definition gave them. A5 is a U1 item; the values are 5 (CONTROL_STATE = ON-LINE REMOTE) and 3 (PROCESS_STATE = EXECUTING). The report body carries no VID numbers. Order is the contract.
One more thing in the header. 86 0B is W-bit plus Stream 6, Function 11, and the SystemBytes are 00 00 00 01 — not the 00 00 04 xx range the host was using. S6F11 is a primary message the equipment opens, so it uses the equipment's own SystemBytes, and S6F12 has to echo that value back. Look for it in the host's transaction table and it is not there.
One S2F33 can delete every link
On a fresh session I linked both CEID 10001 and 10002 to RPTID 700, enabled them, and received one S6F11 from START normally. Then, intending to add a report, I sent an S2F33 carrying only the new RPTID 701.
TX S2F33 W 00 00 00 24 00 00 82 21 00 00 00 00 05 08
01 02 B1 04 00 00 00 01
01 01 01 02 B1 04 00 00 02 BD 01 01 B1 04 00 00 00 03
RX S2F34 00 00 00 0D 00 00 02 22 00 00 00 00 05 08 21 01 00
DRACK 0. Success. Then STOP:
TX S2F41 W 00 00 00 14 00 00 82 29 00 00 00 00 05 09 01 02 41 04 53 54 4F 50 01 00
RX S2F42 00 00 00 11 00 00 02 2A 00 00 00 00 05 09 01 02 21 01 00 01 00
HCACK 0. And then three seconds of nothing. No S6F11 for CEID 10002.
This equipment treats one S2F33 as a replacement of the entire report definition set. RPTID 700 is not in the new set, so it disappears, and the two links referring to it are quietly deleted with it. The ack is 0 and there is no warning. That is the classic shape of a report that arrived yesterday and does not today.
Whether E5 specifies S2F33 as a replacement or as an accumulation is something I did not confirm in the standard text. What is certain is that this equipment behaved as a replacement in the capture above, and the host-side conclusion is the same either way. Do not send partial S2F33 messages when adding a report. Resend the complete definition set for that session every time.
The host-side list
- Order is S2F33 → S2F35 → S2F37. If a step answers non-zero, do not send the next one.
- Do not just test the last byte for zero — log the value itself. LRACK 5 and LRACK 4 have nothing in common, and collapsing both into "link setup failed" fixes neither.
- ERACK 0 is not evidence that a link exists. The only evidence is an S6F11 actually arriving. Force one event right after setup and check.
- Pull the VID list with S1F11 before defining, and keep VIDs the equipment does not have out of S2F33. DRACK 4 kills the whole message.
- The SystemBytes on S6F11 belong to the equipment. Echo them in S6F12 and never match them against the host's outstanding transactions.
- Report bodies contain no VID numbers. Store the order you sent in S2F33 on the host side, and refuse to interpret values without that mapping.
- When changing reports, resend everything. Whether an equipment supports incremental additions is answered by a capture, not by the vendor document.
Every frame above went over a socket. The same bytes are in the equipment-side RX log and the host-side TX log, and the raw export sits in content/demos/s2f35-lrack-report-link-order.json. To run it yourself, point a socket at the SECS/GEM simulator.
A last caveat. The ack values in this article belong to two implementations, not to the standard. A real tool may hold a third answer — silence, an SxF0, or a code that appears nowhere here — so host code should default to treating any value it does not recognise as a failure. The moment an unknown ack is handled like a zero, every failure in this article goes quiet.