Skip to content

[hardware test]: S7-1500 CPU 1511F-1 PN V2.9.7, classic S7 — pass (13/13) #909

Closed

Description

@russwing

Source revision

140ccf0 (master, 2026-09-30): the revision #907 ran, so the two CPUs compare directly. #908's runner fixes are not in it.

Overall result

pass

PLC family, model, and order code

S7-1500, CPU 1511F-1 PN (a fail-safe CPU); order code not recorded (order_code_status: unavailable:AttributeError, the runner bug fixed in #908)

Firmware and security mode

V2.9.7, PUT/GET enabled for this run only, non-optimized fixture DBs (DB1 read-only, DB2 scratch). The safety program was not touched.

Host environment

Python 3.11.2 (CPython), Linux x86_64; pytest-bdd 8.1.0, python-snap7 3.2.0; dependencies from uv sync --extra test

Run time (UTC)

2026-10-01T09:40:44Z (the scratch-write run; a read-only smoke run at the same minute also passed 5/5)

Sanitized report artifacts

JSON report
{
  "ended_at": "2026-10-01T09:40:45.176386+00:00",
  "environment": {
    "architecture": "x86_64",
    "implementation": "CPython",
    "os": "Linux",
    "os_release": "6.1.0-53-amd64",
    "pytest_bdd": "8.1.0",
    "python": "3.11.2",
    "python_snap7": "3.2.0"
  },
  "overall_result": "pass",
  "plc": {
    "cpu_state": "S7CpuStatusRun",
    "family": "S7-1500",
    "firmware": "V2.9.7",
    "model": "CPU 1511F-1 PN",
    "order_code": "",
    "order_code_status": "unavailable:AttributeError",
    "protocol_path": "classic_s7",
    "rack": 0,
    "security_mode": "PUT/GET, non-optimized fixture DBs",
    "slot": 1,
    "tia_configuration": ""
  },
  "scenarios": [
    {
      "diagnostic": null,
      "duration_seconds": 0.015812239958904684,
      "scenario_id": "tests/real_plc/test_acceptance.py::test_establish_and_close_a_session",
      "status": "passed",
      "tags": [
        "classic_s7",
        "real_plc",
        "smoke"
      ]
    },
    {
      "diagnostic": null,
      "duration_seconds": 0.022633926011621952,
      "scenario_id": "tests/real_plc/test_acceptance.py::test_read_the_canonical_fixture",
      "status": "passed",
      "tags": [
        "classic_s7",
        "real_plc",
        "smoke"
      ]
    },
    {
      "diagnostic": null,
      "duration_seconds": 0.018758510006591678,
      "scenario_id": "tests/real_plc/test_acceptance.py::test_read_multiple_values_in_one_request",
      "status": "passed",
      "tags": [
        "classic_s7",
        "real_plc",
        "smoke"
      ]
    },
    {
      "diagnostic": null,
      "duration_seconds": 0.018106958945281804,
      "scenario_id": "tests/real_plc/test_acceptance.py::test_reconnect_after_a_clean_disconnect",
      "status": "passed",
      "tags": [
        "classic_s7",
        "real_plc",
        "smoke"
      ]
    },
    {
      "diagnostic": null,
      "duration_seconds": 0.02350460598245263,
      "scenario_id": "tests/real_plc/test_acceptance.py::test_repeated_operations_do_not_corrupt_the_session",
      "status": "passed",
      "tags": [
        "classic_s7",
        "real_plc",
        "smoke"
      ]
    },
    {
      "diagnostic": null,
      "duration_seconds": 0.01520702603738755,
      "scenario_id": "tests/real_plc/test_acceptance.py::test_roundtrip_a_value_and_restore_the_plc[INT]",
      "status": "passed",
      "tags": [
        "classic_s7",
        "real_plc",
        "write"
      ]
    },
    {
      "diagnostic": null,
      "duration_seconds": 0.014817069983109832,
      "scenario_id": "tests/real_plc/test_acceptance.py::test_roundtrip_a_value_and_restore_the_plc[REAL]",
      "status": "passed",
      "tags": [
        "classic_s7",
        "real_plc",
        "write"
      ]
    },
    {
      "diagnostic": null,
      "duration_seconds": 0.016789042041637003,
      "scenario_id": "tests/real_plc/test_acceptance.py::test_roundtrip_a_value_and_restore_the_plc[BYTE]",
      "status": "passed",
      "tags": [
        "classic_s7",
        "real_plc",
        "write"
      ]
    },
    {
      "diagnostic": null,
      "duration_seconds": 0.016873087035492063,
      "scenario_id": "tests/real_plc/test_acceptance.py::test_roundtrip_a_value_and_restore_the_plc[WORD]",
      "status": "passed",
      "tags": [
        "classic_s7",
        "real_plc",
        "write"
      ]
    },
    {
      "diagnostic": null,
      "duration_seconds": 0.013880087994039059,
      "scenario_id": "tests/real_plc/test_acceptance.py::test_roundtrip_a_value_and_restore_the_plc[DWORD]",
      "status": "passed",
      "tags": [
        "classic_s7",
        "real_plc",
        "write"
      ]
    },
    {
      "diagnostic": null,
      "duration_seconds": 0.015659189084544778,
      "scenario_id": "tests/real_plc/test_acceptance.py::test_roundtrip_a_value_and_restore_the_plc[DINT]",
      "status": "passed",
      "tags": [
        "classic_s7",
        "real_plc",
        "write"
      ]
    },
    {
      "diagnostic": null,
      "duration_seconds": 0.014981463085860014,
      "scenario_id": "tests/real_plc/test_acceptance.py::test_roundtrip_a_value_and_restore_the_plc[CHAR]",
      "status": "passed",
      "tags": [
        "classic_s7",
        "real_plc",
        "write"
      ]
    },
    {
      "diagnostic": null,
      "duration_seconds": 0.015706156962551177,
      "scenario_id": "tests/real_plc/test_acceptance.py::test_roundtrip_a_value_and_restore_the_plc[BOOL]",
      "status": "passed",
      "tags": [
        "classic_s7",
        "real_plc",
        "write"
      ]
    }
  ],
  "schema_version": "1.0",
  "source": {
    "commit": "140ccf08f7bb602b63d2fa074bdedaa5399d8431",
    "dirty": false,
    "kind": "git"
  },
  "started_at": "2026-10-01T09:40:44.797590+00:00",
  "tester": "@russwing"
}
JUnit XML (the hostname attribute redacted)
<?xml version="1.0" encoding="utf-8"?><testsuites name="pytest tests"><testsuite name="pytest" errors="0" failures="0" skipped="0" tests="13" time="0.375" timestamp="2026-10-01T09:40:44.800927+00:00" hostname="redacted"><testcase classname="tests.real_plc.test_acceptance" name="test_establish_and_close_a_session" time="0.016" /><testcase classname="tests.real_plc.test_acceptance" name="test_read_the_canonical_fixture" time="0.023" /><testcase classname="tests.real_plc.test_acceptance" name="test_read_multiple_values_in_one_request" time="0.019" /><testcase classname="tests.real_plc.test_acceptance" name="test_reconnect_after_a_clean_disconnect" time="0.018" /><testcase classname="tests.real_plc.test_acceptance" name="test_repeated_operations_do_not_corrupt_the_session" time="0.024" /><testcase classname="tests.real_plc.test_acceptance" name="test_roundtrip_a_value_and_restore_the_plc[INT]" time="0.016" /><testcase classname="tests.real_plc.test_acceptance" name="test_roundtrip_a_value_and_restore_the_plc[REAL]" time="0.015" /><testcase classname="tests.real_plc.test_acceptance" name="test_roundtrip_a_value_and_restore_the_plc[BYTE]" time="0.017" /><testcase classname="tests.real_plc.test_acceptance" name="test_roundtrip_a_value_and_restore_the_plc[WORD]" time="0.017" /><testcase classname="tests.real_plc.test_acceptance" name="test_roundtrip_a_value_and_restore_the_plc[DWORD]" time="0.014" /><testcase classname="tests.real_plc.test_acceptance" name="test_roundtrip_a_value_and_restore_the_plc[DINT]" time="0.016" /><testcase classname="tests.real_plc.test_acceptance" name="test_roundtrip_a_value_and_restore_the_plc[CHAR]" time="0.015" /><testcase classname="tests.real_plc.test_acceptance" name="test_roundtrip_a_value_and_restore_the_plc[BOOL]" time="0.016" /></testsuite></testsuites>

Skips, failures, and notes

  • Smoke (read-only): 5/5. Scratch writes (--allow-write, DB2 only): 8/8 types (INT, REAL, BYTE, WORD, DWORD, DINT, CHAR, BOOL), each restored and read back. --allow-admin off.
  • DB2 was byte-identical afterwards (all 38 bytes compared, before and after).
  • Block upload/download was not run on this CPU. The run kept to DB reads and scratch writes.
  • With PUT/GET off, the same CPU refuses every classic S7 read with class=0x81, code=0x04 (30 Sep).
  • Runner notes: as in [hardware test]: S7-1200 CPU 1212C V4.7.3, classic S7 — pass (13/13) #907, the JUnit XML's hostname attribute is redacted by hand, and the order-code read fails with AttributeError.

Safety confirmation

  • I reviewed the attachments and they contain no PLC address, credentials, private keys, plant/site identifiers, or proprietary PLC program.

Activity

  1. added
    hardware-testStructured result from a real PLC acceptance run
    test-result: passAll selected applicable real-PLC scenarios passed
    on Oct 2, 2026
  2. gijzelaerr commented on Oct 2, 2026

    @gijzelaerr
    Owner

    Thanks for the run, and for checking DB2 byte for byte afterwards! Having a fail-safe 1500 next to the 1212C is useful coverage.

    The two runner problems you noted are both fixed in #908: the order code was read from the wrong S7OrderCode field, and the JUnit XML now drops hostname and redacts addresses on its own. Once that's merged, a rerun on either CPU would give us a report with the order code filled in, if you have time. No rush; please open it as a new issue and link this one, per the result policy.

  3. gijzelaerr commented on Oct 3, 2026

    @gijzelaerr
    Owner

    #908 is merged, so a rerun on current master will record the order code and produce a clean JUnit XML without manual redaction. The PUT/GET-disabled 0x81/0x04 behaviour you saw is now in the error reference (#911).

  4. gijzelaerr commented on Oct 13, 2026

    @gijzelaerr
    Owner

    Recorded in the new Tested and Verified Hardware section of the PLC support matrix (#947). Thanks for the runs!

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    hardware-testStructured result from a real PLC acceptance runtest-result: passAll selected applicable real-PLC scenarios passed

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions