Skip to content

schema(#293): get_signal_contact sense_ps_state per-PSU dict {psid: bool} - #384

Merged
AdamRickards merged 1 commit into
mainfrom
schema/293-sense-ps-state-dict
Sep 24, 2026
Merged

AdamRickards merged 1 commit into
mainfrom
schema/293-sense-ps-state-dict

Conversation

@AdamRickards

Copy link
Copy Markdown
Owner

Rank1 soft — get_signal_contact.sense_ps_state as a per-PSU dict (read side)

Related: #293

Anchor: 1.17 clerk trail (issue comment 5823364677). sense_ps_state is a per-PSU dict {psu_id: bool} on ssh, mops and snmp. The MIB table is hm2SigConPSEntry INDEX {hm2SigConID, hm2PSID}. When there are no rows the result is {}, never a bool and never None. Before this PR crude returned a scalar: mops True (last row won), ssh False (default), snmp collapsed by key_field.

Changes (YAML only; existing driver primitives, same recipe as archive signal_contact.yaml ps_state):

protocol file change
snmp wire/diagnostic.yaml index_fields + key_field: hm2SigConID (collapsed to one value per contact) → index: [group, inner]. Suffix SigConID.PSID gives {cid: {psid: bool}}, with HmEnabledStatus 1/2 → True/False through the existing matrix.
mops wire/diagnostic.yaml index_field: hm2SigConID + inner_index_field: _enumerate. The rows have no hm2PSID column, so PSID comes from the per-contact row order, as in 1.17 mops_hios and the archive. The unused index_fields list was dropped.
ssh wire/ssh/diagnostic.yaml new hm2sigconsensepsstate read on the existing show signal-contact {entity} all (iterate_from: [1, 2], which shares the iterate cache, so no extra show): parser: table, section: 1, key_column: 0, column: 1, tag: value_map, map: sigcon_sense_ssh (existing tokens monitored → true, default false).
schema schemas/signal_contact.yaml default sense_ps_state: false → {}, so a contact with no PS rows is honestly {}.

Offline checks (drivers + shaping, mocked I/O):

  • snmp _gather_walks on {'1.1':1,'1.2':2,'2.1':1,'2.2':1} gives {'1': {'1': True, '2': False}, '2': {'1': True, '2': True}}. An empty walk gives {}.
  • mops gather on 4 rows (SigConID + state only) gives the same nested dict. 0 rows gives {}.
  • ssh _parse_response on a representative layout (title underline, then the Power Supply Status table, then the Intf Status table) gives {'1': 'monitored', '2': 'ignored'}, mapped to {'1': True, '2': False}. An empty or Error: response gives {}.
  • _shape_table_output gives rows {'1': {'1': True, '2': False}, …}. With no PS data, every row gets {}.

No aggregation into a bool, no new primitive, no engine/driver edit, no invented tokens. validate_schemas.py --errors gives 46 | 45 | 0 errors | 1 warning, same as baseline.

Watch in proof / leftovers:

  • The SSH layout is not device-captured. section: 1 comes from the archive and assumes a title underline before the PS table. If Test raw shows the PS table is separator 0, it's a one-token retune.
  • The MOPS PSID-by-row-order is the 1.17 assumption the anchor flags. Test should confirm the keys match snmp's real PSID suffix.
  • Write side is unchanged: set_signal_contact still has no per-PSU dict ingress, so that's out of scope for this read-side PR.
  • sense_fan/sense_humidity/sense_stp_port_block None vs False, and the empty cli list (get_interfaces.read: SSH parse remainder (cli listed; n=1 vs mops 36) #226 class), are not touched here.

Proof: python3 tests/release_matrix.py --inspect --method get_signal_contact --trace --device

…ool}

1.17 anchor: per-PSU dict on ssh/mops/snmp; {} when no rows.
- snmp: index [group, inner] (SigConID.PSID) replaces key_field collapse
- mops: inner_index_field _enumerate (no PSID column; 1.17 row order)
- ssh: Power Supply/Status table (table section 1, key_column 0, column 1,
  sigcon_sense_ssh) on the existing per-contact show; no extra fanout
- schema default false -> {}

Related: #293
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant