An S1F4 Carries No SVIDs — Get the Names From S1F11 First
An S1F4 body carries no SVIDs at all. Real S1F11/S1F12 bytes showing where a host learns SVID numbers and names, and how S2F29 differs.
The host sent an S1F3 carrying two SVIDs. The S1F4 that came back holds four values, and no field anywhere in the reply says which of them is the 101 that was asked for. There are no SVIDs in an S1F4 body at all.
Which is why S1F3 is not the first message a host sends. The only route by which a host learns what SVID numbers and names a tool owns is S1F11/S1F12, the Status Variable Namelist Request. Pull the catalogue before you read the values, or the values come back uninterpretable. If you are writing this code with no equipment to test against, you need to see both bodies as bytes once.
Every frame below went over a socket to the SECS/GEM simulator's EQ1 passive listener (127.0.0.1:5501, SessionID 11, no fault modes set). The host side is a Python socket client that encodes and decodes the SECS-II items itself.
An empty list returns the whole catalogue
The S1F11 body is a list of SVIDs. With zero elements, SEMI E5's Stream 1 reads it as describe every status variable you have. A host meeting a tool for the first time knows no SVIDs anyway, so this is the form it starts from.
TX S1F11 W 00 00 00 0C 00 0B 81 0B 00 00 00 00 41 03 01 00
| Bytes | Field | Value |
|---|---|---|
00 00 00 0C | Length | 12 — a 10-byte header plus a 2-byte body |
00 0B | SessionID | 11 |
81 | Header byte 2 | W-bit set, Stream 1 |
0B | Header byte 3 | Function 11 |
00 00 | PType, SType | 0, 0 — a data message |
00 00 41 03 | SystemBytes | 0x00004103 |
01 00 | Body | L,0 — an empty list |
What came back:
RX S1F12 00 00 00 79 00 0B 01 0C 00 00 00 00 41 03
01 04
01 03 B1 04 00 00 00 64 41 12 53 56 31 30 30 5F 50 72 6F 63 65 73 73 53 74 61 74 65 41 00
01 03 B1 04 00 00 00 65 41 11 53 56 31 30 31 5F 54 65 6D 70 65 72 61 74 75 72 65 41 00
01 03 B1 04 00 00 00 66 41 0E 53 56 31 30 32 5F 50 72 65 73 73 75 72 65 41 00
01 03 B1 04 00 00 00 67 41 0C 53 56 31 30 33 5F 52 65 63 69 70 65 41 00
The length is 00 00 00 79, 121 — a 10-byte header and a 111-byte body. Header byte 2 is 01: W-bit clear, Stream 1. Byte 3 0C is Function 12, and the SystemBytes 41 03 are the request's own.
The body is an L,4, four entries. Each entry is an L,3 holding, in the order SEMI E5's Stream 1 specifies, SVID, SVNAME and UNITS. The first entry taken apart byte by byte:
01 03— in the item header byte01, the top six bits are format code 0 (List) and the bottom two say one length byte follows. The03after it is three elements. A list length counts elements, not bytes.B1 04 00 00 00 64— the top six bits ofB1are 44, U4. Four bytes, value 100. That is the SVID.41 12 53 56 31 30 30 …—41is ASCII and the length12is 18 bytes:SV100_ProcessState. That is SVNAME.41 00— a zero-length ASCII item. UNITS is the empty string.
The other three entries are SVID 101 SV101_Temperature, 102 SV102_Pressure and 103 SV103_Recipe. 00 00 00 65 is 101, 66 is 102, 67 is 103.
All four UNITS being empty is the simulator's model carrying no units. A real tool puts degC or Torr in that slot. What matters host-side is that treating 41 00 as "no item present" slips the parser one slot out of alignment right there. It is not a zero and it is not a null — a zero-length item occupies its position.
An SVID this tool does not have changes nothing in the answer
Ask again with SVID 101 plus 9999, a number this equipment does not own. 00 00 27 0F is 9999.
TX S1F11 W 00 00 00 18 00 0B 81 0B 00 00 00 00 41 04 01 02 B1 04 00 00 00 65 B1 04 00 00 27 0F
RX S1F12 00 00 00 79 00 0B 01 0C 00 00 00 00 41 04 01 04 … (byte for byte the earlier reply)
The length is 00 00 00 79 again, 121. Two asked for, four returned, and nothing in the reply rejects the number that does not exist. No S9 message either. This listener never reads the S1F11 body at all and returns every variable it holds — that is the simulator's implementation, not a statement about equipment in general. What a real tool does with an unknown SVID varies by vendor. E5's convention in reply lists like this one is to keep the entry and put zero-length items in the SVNAME and UNITS positions, and I have not verified how that comes out on a real tool.
So the host-side defence is not in the content but in the length comparison. If the reply list length does not equal the request list length, stop parsing and raise. Ask for two, get four, slice from the front anyway, and from that moment the process state is sitting in the temperature field.
Put S1F3 and S1F4 next to it and the reason for the catalogue shows
Send the same SVID list in an S1F3. The request body is byte for byte what went out in the S1F11; only header byte 3 changes, 0B to 03.
TX S1F3 W 00 00 00 18 00 0B 81 03 00 00 00 00 41 05 01 02 B1 04 00 00 00 65 B1 04 00 00 27 0F
RX S1F4 00 00 00 31 00 0B 01 04 00 00 00 00 41 05
01 04
41 04 49 64 6C 65
81 08 40 37 59 99 99 99 99 9A
81 08 3F F1 2B 02 0C 49 BA 5E
41 09 45 54 43 48 5F 42 41 53 45
The length 00 00 00 31 is 49, a 39-byte body. 01 04 is four elements. 41 04 49 64 6C 65 is ASCII Idle. The top six bits of 81 are 32, F8 — eight bytes of IEEE 754 double, so 40 37 59 99 99 99 99 9A is 23.35 and 3F F1 2B 02 0C 49 BA 5E is 1.073. The last item, 41 09 45 54 43 48 5F 42 41 53 45, is ETCH_BASE.
Not one SVID appears here. Without the S1F12 above in hand there is no way to tell from the message whether 23.35 is a temperature or a pressure. The second value reads as a temperature only because S1F12 attached SV101_Temperature to SVID 101, and that binding survives on ordering alone.
Asking with an empty list gives the same answer.
TX S1F3 W 00 00 00 0C 00 0B 81 03 00 00 00 00 41 06 01 00
RX S1F4 00 00 00 31 00 0B 01 04 00 00 00 00 41 06 01 04 … (byte for byte the `41 05` reply)
The float bytes match too because the temperature did not move in the 4 ms between the two requests. That this listener ignores the S1F3 body as well was already visible in the 41 05 exchange. It is not a cache.
S2F29 is the next street over
The name that gets mixed up with this one is the equipment constant namelist. Send an S2F29 down the same socket and the difference is visible in the bytes.
TX S2F29 W 00 00 00 0C 00 0B 82 1D 00 00 00 00 41 07 01 00
RX S2F30 00 00 00 8B 00 0B 02 1E 00 00 00 00 41 07
01 02
01 06 B1 04 00 00 01 2C
41 17 45 43 33 30 30 5F 54 61 72 67 65 74 54 65 6D 70 65 72 61 74 75 72 65
81 08 00 00 00 00 00 00 00 00
81 08 40 60 40 00 00 00 00 00
81 08 40 50 40 00 00 00 00 00
41 00
01 06 B1 04 00 00 01 2D 41 14 45 43 33 30 31 … 41 00
Header byte 2 of the request is 82, differing from S1F11's 81 in the low bits: Stream 2. And the entry is an 01 06, six items. ECID 300, ECNAME, then three F8s in the minimum, maximum and default slots, then UNITS. The S1F12 entry was an 01 03, three items.
That is a usable test for telling the two apart. A status variable is a read-only value the equipment holds right now, so a range or a default is not a thing it has; an equipment constant is a setting the host can change, so min, max and default ride along. Three items per entry means S1F12, six means S2F30. The S2F29/S2F13 side is worked through in reading equipment constants from the host.
What to actually put in the host code
- Send S1F11 as soon as S1F13/S1F14 is through. The reply to an S1F3 sent without the catalogue is a pile of numbers you cannot interpret.
- Compare the request list length against the reply list length. Different means raise. Implementations that ignore the request and return everything exist — one is above.
- Do not hardcode the SVID format code as U4. The capture above is
B1, U4, but E5 allows that slot to be several integer types and ASCII. Code that assumes U4 dies at connect time against a tool that numbers its variables as strings. - Cache SVNAME to SVID, but store the cache with the software revision S1F14 returns. When the
SECSGEM-1.4.1string changes, throw the cache away.
Item 4 is the one that bites the morning after a firmware update. If the SVID numbering has been rearranged the host sees no error at all and keeps writing wrong values down as good ones. I have met several hosts that read S1F12 once, wrote it into a config file and never read it again — and the route by which anyone discovered that the file disagreed with the tool was always scrap.
Every frame above really went over a socket, and the same bytes are in the equipment-side RX log. The raw export sits in content/demos/s1f11-s1f12-svid-namelist-host-side.json, and this article's run is SystemBytes 0x4101–0x4108 (the file holds other runs too). To push the same bytes yourself, point a socket at the SECS/GEM simulator.