N: E39 generic ObjectService — S14F1/F2 GetAttr + S14F3/F4 SetAttr

The catalog had S14F9/F10 / F11/F12 specialized for E94 ControlJob;
this commit adds the generic E14 attribute access pair, the most-
queried half of the E39 surface area, backed by the CemObjectStore.

  S14F1 / F2  GetAttr  — OBJSPEC + OBJTYPE + ATTRID list ->
                         (ATTRID, VALUE) pairs + OBJACK
  S14F3 / F4  SetAttr  — same addressing, applies ATTRID/VALUE pairs,
                         reply echoes stored values + OBJACK

Server dispatches both into the CemObjectStore added in tranche G.
OBJTYPE validation is case-sensitive against the CemObjectType name
(Equipment / Subsystem / IODevice / Module / MaterialLocation).
Unknown objects return Denied_UnknownObject; type mismatches return
Denied_InvalidAttribute.

The shared AttrValue struct is declared external_struct: true on
F3/F4 so both directions share the same C++ type.

Two round-trip tests cover both pairs.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-06-08 09:09:51 +02:00
parent 3b45bade8f
commit af2c60663e
3 changed files with 169 additions and 0 deletions
+87
View File
@@ -1407,6 +1407,93 @@ messages:
# generic ATTRIBUTES list specialized.
# =====================================================================
# S14F1 / F2 — GetAttr (generic). E39/E14 ObjectService form: host
# requests one or more attribute values from a named object. OBJSPEC
# is the dotted path through the CEM tree, OBJTYPE is the expected
# type (validated by the equipment), ATTRID is a list of names.
# Reply carries the values in the same order, plus an OBJACK code.
- id: S14F1
stream: 14
function: 1
w: true
builder: s14f1_get_attr
parser: parse_s14f1
body:
kind: list
struct_name: GetAttrRequest
fields:
- {name: objspec, shape: {kind: scalar, item_type: ASCII}}
- {name: objtype, shape: {kind: scalar, item_type: ASCII}}
- name: attrids
shape: {kind: list_of, element: {kind: scalar, item_type: ASCII}}
- id: S14F2
stream: 14
function: 2
builder: s14f2_get_attr_data
parser: parse_s14f2
body:
kind: list
struct_name: GetAttrReply
fields:
- name: attrs
shape:
kind: list_of
element:
kind: list
struct_name: AttrValue
fields:
- {name: attrid, shape: {kind: scalar, item_type: ASCII}}
- {name: value, shape: {kind: scalar, item_type: ITEM}}
- {name: ack, shape: {kind: scalar, item_type: BINARY_BYTE, enum: ObjectAck}}
# S14F3 / F4 — SetAttr (generic). Same OBJSPEC/OBJTYPE addressing as
# GetAttr; body carries (ATTRID, VALUE) pairs the equipment applies
# in order. Reply echoes whatever the equipment now has.
- id: S14F3
stream: 14
function: 3
w: true
builder: s14f3_set_attr
parser: parse_s14f3
body:
kind: list
struct_name: SetAttrRequest
fields:
- {name: objspec, shape: {kind: scalar, item_type: ASCII}}
- {name: objtype, shape: {kind: scalar, item_type: ASCII}}
- name: attrs
shape:
kind: list_of
element:
kind: list
struct_name: AttrValue
external_struct: true
fields:
- {name: attrid, shape: {kind: scalar, item_type: ASCII}}
- {name: value, shape: {kind: scalar, item_type: ITEM}}
- id: S14F4
stream: 14
function: 4
builder: s14f4_set_attr_ack
parser: parse_s14f4
body:
kind: list
struct_name: SetAttrReply
fields:
- name: attrs
shape:
kind: list_of
element:
kind: list
struct_name: AttrValue
external_struct: true
fields:
- {name: attrid, shape: {kind: scalar, item_type: ASCII}}
- {name: value, shape: {kind: scalar, item_type: ITEM}}
- {name: ack, shape: {kind: scalar, item_type: BINARY_BYTE, enum: ObjectAck}}
# S14F9 / F10 — CreateObject (CJ). Host asks the equipment to bring
# a new ControlJob into existence and registers the list of PJs it
# contains; the CJ starts in CJ-QUEUED.