ci-server-engineer/.claude/skills/pytools/tasks/read-items-history.md
cliu bf7d88a027 R1.05 re-check batch 3: alarms, audit, authorization, classes, HAC, reporting, pyTOOLS
Full manual diffs (L15, C20, E30, L25, J40, C10 §2, L10, P10, P11, J20,
C30, P20, R40, E10) and read-only checks on the shared R1.05 test server.
Skills and summaries moved to R1.05; new skill pytools (IM 36K10P40) from
docs (no Python on the test server). Issues ISS-132..181; corrections to
version-differences (E10, E30, P11, dss_ath_grp_u0104); C10 summary lists
the 3 new authorization actions; r105-verification V10-V17.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 10:21:36 +11:00

103 lines
5 KiB
Markdown

---
task: Read item values and definitions, and item history / aggregates, from a Python script
version: R1.05
source: IM 36K10P40-01EN §3.3, §3.5, §3.12, §3.13, §4 (2nd ed., Feb. 2026); field names from the R1.05 data dictionary (copied from the R1.05 test server 2026-10-08); `aggr_period` and its values checked in the installed R1.05 `dss.pyd` (2026-10-09)
status: from docs, not tested (no Python on the R1.05 test server)
---
# Read items and item history
Start from `setup-first-script.md` (setup, logon). Only read mode (`'r'`) is used here.
## 1. Read all items of a section (ITEM_VAL)
`ITEM_VAL` = current values (`NAME`, `ITEM_VALUE`, `ITEM_VALUE_STR`, `STATUS`, `QUALITY`,
`UPDATE_TIME`, limits, `IN_ALARM`, `ENG_UNIT`, `SCALE_HIGH_LIMIT`, `SCALE_LOW_LIMIT` …);
`ITEM_DF` = definitions (description, type, limits, history and alarm settings). See all
fields with `dss.getFieldNames(conn, 'ITEM_VAL')` and their type/length with
`dss.getFieldProperties(conn, 'ITEM_VAL', 'NAME')`.
```python
import os, sys, getpass
sys.path.insert(0, os.path.join(os.environ['TLS_ROOT_PATH'], 'tls', 'exe'))
import dss
conn = dss.connect(os.environ.get('CI_USER') or input('User: '),
os.environ.get('CI_PASSWORD') if 'CI_PASSWORD' in os.environ
else getpass.getpass('Password: '))
try:
ds = dss.openDataset(conn, 'ITEM_VAL',
['NAME', 'ITEM_VALUE', 'ITEM_VALUE_STR', 'STATUS', 'ENG_UNIT'], 'r')
try:
dss.createFilter(conn, ds, '"CI-Eng-Sample.*"') # or '"<Section>.*"'
dss.activateFilter(conn, ds)
while True:
try:
r = dss.readNext(conn, ds)
except dss.error as e:
if e.args[0] == 'DSS-E-EOS': # end of the dataset
break
raise
print('%-40s %12s %-8s %s' % (r['NAME'], r['ITEM_VALUE_STR'] or r['ITEM_VALUE'],
r['ENG_UNIT'], r['STATUS']))
dss.deactivateFilter(conn, ds)
dss.deleteFilter(conn, ds)
finally:
dss.closeDataset(conn, ds)
finally:
dss.close(conn)
```
- One item: `dss.readEqual(conn, ds, 'CI-Eng-Sample.TANK1.LEVEL')` (no filter needed).
- Small result sets: `dss.readRecords(conn, ds)` returns a list at once (the filter applies).
- Time fields are floats (seconds since 1970, local time unless the dataset was opened with
`'rt'` = UTC); format with `dss.dateString(conn, t, 'GENERAL')`.
## 2. Item history (fast path)
`getItemHistory` asks ITEM Service directly (faster than `ITEM_HISTORY` through DSS). The item
must be in the storage group you name (CI-Eng-Sample: `CIENG_EVENT` and `CIENG_SCAN10S` hold
`TANK1.LEVEL` and `TANK1.INFLOW`; `CIENG_AGG` holds hourly and 30-minute max/min/average of
`TANK1.LEVEL`; skill `history-management`).
```python
# inside the try: after dss.connect(...)
print(dss.getHisGroupItems(conn, 'CIENG_EVENT')) # items in the group
start = dss.dateRelDSS(conn, '-02:00') # 2 hours ago
end = dss.dateRelDSS(conn, '-00:00') # now
item, group = 'CI-Eng-Sample.TANK1.LEVEL', 'CIENG_EVENT'
while True:
samples = dss.getItemHistory(conn, item, group, start, end, 500)
done = samples and samples[-1] is None
rows = [s for s in samples if s is not None]
for (t, value, status, option_bits, quality) in rows:
print(dss.dateString(conn, t, 'GENERAL'), value, status, quality)
if done or not rows:
break
start = rows[-1][0] # next block starts at the last time read (may repeat it once)
```
Optional named arguments:
- `interval=60000` — interpolated values every 60 s (milliseconds) instead of the stored samples.
- `attribute='HIGH_LIMIT'` (also `DEADBAND`, `LOW_LIMIT`, `LOW_LOW_LIMIT`, `HIGH_HIGH_LIMIT`,
`SCALE_LOW`, `SCALE_HIGH`) where the group type stores them.
- Aggregation group: `attribute='AGGR_MAX'` (`AGGR_MIN`, `AGGR_AVERAGE`, `AGGR_INTG`,
`AGGR_COUNT`, `AGGR_STDV`, `AGGR_DFMS`) with `aggr_period='HOUR'` (`30_MINUTES`, `SHIFT`,
`DAY`, `WEEK`, `MONTH`, `YEAR`; only periods configured for the group, and only aggregates
stored for the item), e.g.
`dss.getItemHistory(conn, item, 'CIENG_AGG', start, end, 100, attribute='AGGR_MAX', aggr_period='HOUR')`.
- `node=<number>` — group on another node of a distributed system.
The status and quality numbers are the same codes as in `ITEM_HISTORY` / `STATUS_DF` (read
`STATUS_DF` to translate status numbers, task `filter-index.md`).
Expected: a list of tuples per block; the last block ends with `None`. An item that is not in
the group, or a group that does not exist, raises `dss.error` (code from ITEM Service).
## 3. Not tested / to verify
On a test Core with Python (user): run §1 against the sample section and compare with
`itmval -g` (skill `system-management`, `read-write-item.md`); run §2 for `CIENG_EVENT` and
compare with an `ITEM_HISTORY` report or `rptgen` query for the same period (skill
`reporting`). Check whether the repeated boundary sample appears when a block is continued.