◇ OpenCyber Academy
Bachelor's · Chapter 3 · English

Chapter 3 — Programming I

Open, free learning for anyone who wants to protect people and technology. No account is required to read this text or its worked answers.

Chapter 3 — Programming I

Lesson map

Lesson 03 published. Map, example, EX007.

flowchart TD
  N0["Learning outcomes"]
  N1["3.1 Tags as records"]
  N2["3.2 Range validation"]
  N3["3.3 Readable output"]
  N4["Synthesis"]
  N0 --> N1 --> N2 --> N3 --> N4
  N4 --> EX["Worked example"]
  EX --> Q["Exercise EX007"]

Logical drawing

flowchart LR
  N0["Learning outcomes"]
  N1["3.1 Tags as records"]
  N2["3.2 Range validation"]
  N3["3.3 Readable output"]
  N4["Synthesis"]
  N0 --> N1 --> N2 --> N3 --> N4 --> Q["EX007"]
[Learning outcomes]
    |
    v
[3.1 Tags as records]
    |
    v
[3.2 Range validation]
    |
    v
[3.3 Readable output]
    |
    v
[Synthesis]
    |
    v
[Worked example] --> [Exercise EX007]

Learning outcomes

You will (1) read structured data with Python's standard library; (2) validate values against engineering ranges; (3) write output that a reviewer can check line by line; and (4) explain why validation code is a safety-relevant artefact.

3.1 Tags as records

An OT tag list is a table: tag name, engineering unit, low and high limits, current value. Python's csv module reads such tables without third-party packages, which matters on locked-down engineering laptops where installing software needs approval. Treat each row as a dictionary and keep raw text separate from parsed numbers so a parsing failure is visible rather than silently becoming zero.

In the tag lab, keeping the raw text is what lets Maya's note say "FT-301 read −3.0 m³/h" rather than reporting a blank or a zero; the instrument technician can then look at the exact value the meter sent and decide whether scaling or wiring is at fault.

3.2 Range validation

A temperature of 141 °C on a probe calibrated for 20–130 °C is either a real excursion, a failed sensor or a manipulated value. Code cannot tell which; it can flag the row and stop it reaching a report labelled "normal". The same applies to a negative flow, which is physically impossible for a one-way meter and therefore always a data-quality or integrity question.

The tag lab flags exactly these two rows: TT-102 at 141.0 °C against a 130 °C limit, and FT-301 at −3.0 m³/h. Maya sends the first to the operator at once and the second to instrumentation as a suspected wiring or scaling fault.

3.3 Readable output

Print one decision per line with the input that caused it. Reviewers in plant change boards are rarely programmers; they will trust output they can trace to a row.

"""Lab 03: validate a synthetic LDHP tag list (no plant access)."""
import csv, io
RAW = """tag,unit,lo,hi,value
TT-101,degC,20,130,96.5
TT-102,degC,20,130,141.0
PT-201,bar,0,16,9.8
FT-301,m3/h,0,250,-3.0
LT-401,pct,0,100,57
"""
bad = []
for row in csv.DictReader(io.StringIO(RAW)):
    v, lo, hi = float(row["value"]), float(row["lo"]), float(row["hi"])
    ok = lo <= v <= hi
    print(f"{row['tag']:7} {v:7.1f} {row['unit']:5} {'ok' if ok else 'OUT-OF-RANGE'}")
    if not ok: bad.append(row["tag"])
print("flagged:", ", ".join(bad))

Run with python3 lab_tags.py. Verified output:

TT-101     96.5 degC  ok
TT-102    141.0 degC  OUT-OF-RANGE
PT-201      9.8 bar   ok
FT-301     -3.0 m3/h  OUT-OF-RANGE
LT-401     57.0 pct   ok
flagged: TT-102, FT-301

At LDHP, the two flagged rows print as TT-102 141.0 degC OUT-OF-RANGE and FT-301 -3.0 m3/h OUT-OF-RANGE, with the input value on the same line as the decision; routing each flag to the operator or to instrumentation is Maya's judgement in her note, not something the script decides. A change-board reviewer who is a control engineer, not a programmer, can check each line against the instrument index in a minute and does not need to read the script. If a line cannot be traced to a row, the reviewer has no reason to trust it, so the output should never print a summary count without the rows behind it.

Worked example (synthetic LDHP)

The lab flags TT-102 (141.0 °C, above 130) and FT-301 (−3.0 m³/h, below 0). Maya's note separates them: TT-102 could be a genuine high reading and goes to the operator immediately; FT-301 is physically impossible and goes to instrumentation as a suspected wiring or scaling fault, with integrity review if the fault cannot be explained.

Synthetic case — Lakeside District Heating Plant. The tag list in the lab is invented; real LDHP limits would come from the instrument index maintained by the control engineers.

Errors and limits

Range checks catch gross errors, not subtle manipulation inside the band. Floating-point comparison at the boundary needs a stated rule (inclusive here). The script reads a string, not a live system.

Exercises

Synthesis

Small, readable stdlib programs that flag rather than fix are the first tool an OT security student should trust and be able to defend.

Continue studying — chapter 03 of 40

← Chapter 02 (draft) · Course chapter index · Chapter 04 (draft) →