Skip to content

Add a new scenario: meter-value-zero #108

Closed

Description

@sepehr-safari

Good First Issue

Add a new scenario meter-value-zero: a transaction where the meter register
reads zero throughout. This is a negative control. A flat register is not by
itself a detectable fault today, and the scenario pins that down so a future
change to METER_VALUE_ANOMALY cannot start reporting it by accident.

METER_VALUE_ANOMALY fires only on negative or decreasing cumulative readings.
An all-zero series is neither, so this trace must come back clean. Whether a
stuck register deserves its own rule is tracked separately in #144.

What to do

  1. Create packages/toolkit/src/scenarios/__scenarios__/meter-value-zero.ts
  2. Build a synthetic trace of a transaction whose meter never advances:
    • BootNotification at 2026-01-15T09:00:00.000Z, and its CallResult with
      interval: 300
    • Authorize with idTag: 'SYNTHETIC-TAG-021' at 09:00:30.000Z, accepted
    • StartTransaction on connector 1 at 09:01:00.000Z with meterStart: 0,
      answered with transactionId: 100021
    • MeterValues at 09:02:00.000Z, 09:03:00.000Z and 09:04:00.000Z, each
      carrying a single sampledValue of '0' with measurand
      Energy.Active.Import.Register and unit Wh
    • StopTransaction at 09:05:00.000Z with meterStop: 0 and
      reason: 'Local'
    • A CallResult for every Call
  3. Set expectedFailures: []
  4. Add { type: 'no_failures', params: {} } as the assertion
  5. Import and register in packages/toolkit/src/scenarios/index.ts
  6. Update the scenario count in every place that states it, see "Files to modify"
  7. Run ocpp-debugkit ci to verify all scenarios pass, then run the full local
    check from
    Verify Locally.
    ocpp-debugkit ci covers neither formatting nor lint nor types, and CI stops
    at the first failure.
  8. Add a changeset with pnpm changeset, and pick patch. Scenario additions
    are patch releases, see
    Adding a Scenario.

Why those timestamps

The transaction runs four minutes, comfortably past the sixty second floor that
SUSPICIOUS_SESSION_DURATION watches for. The whole trace also finishes inside
twice the three hundred second heartbeat interval, so TIMEOUT_NO_HEARTBEAT
stays silent without needing a heartbeat in the trace. This trace was run against
the detection engine and reports no failures.

Files to modify

  • packages/toolkit/src/scenarios/__scenarios__/meter-value-zero.ts (new)
  • packages/toolkit/src/scenarios/index.ts (register, and add to scenarioNames)
  • packages/toolkit/src/scenarios/index.test.ts (count, name order, getScenario)
  • tests/external-fixture/test.mjs (count)
  • README.md (count)
  • packages/toolkit/README.md (count)
  • .changeset/ (new changeset file)

The first two of the count files fail the test suite when they drift. The two
READMEs do not, so they are easy to miss.

Guidelines

  • All data must be synthetic. This scenario reserves station ID
    CS-SYNTHETIC-021, so please use that one.
  • Follow the pattern in an existing scenario file. meter-anomaly.ts is the
    closest match for shape, and normal-session is the closest for a scenario
    that expects no failures.
  • Verify with ocpp-debugkit scenario run meter-value-zero that no failures are
    reported. If a rule does fire, adjust the trace rather than adding the code to
    expectedFailures, since the whole point of this scenario is that it stays
    clean.
  • The scenario count depends on what has merged ahead of you. Run the suite and
    use the number it reports rather than assuming.

How to claim

Comment "I'd like to work on this" and it will be assigned to you.

Please hold one open claim at a time. Once the pull request for it is merged,
say which issue you want next and it will be assigned. That keeps issues from
sitting claimed while another is still in review, so other newcomers can see
what is genuinely free.

Activity

  1. YANGCHUNHONG3000 commented on Jul 26, 2026

    @YANGCHUNHONG3000
    Contributor

    I'd like to work on this meter-value-zero scenario.

  2. sepehr-safari commented on Jul 26, 2026

    @sepehr-safari
    MemberAuthor

    Thanks for the interest. I am assigning these one at a time, and #104 is with you
    now, so I am leaving this one open for the moment. Once #133 merges, say the word
    and it is yours.

  3. YANGCHUNHONG3000 commented on Aug 2, 2026

    @YANGCHUNHONG3000
    Contributor

    Hi sepehr-safari,

    Checking back in on this one — the firmware-update-success scenario (#133) has now merged (thanks for that!), and I'd like to pick this up next if it's still available.

    I have the plan clear from the issue body: build the meter-value-zero synthetic trace (flat register, zero throughout), assert expectedFailures: [] with a no_failures assertion, register it in scenarios/index.ts, and update the scenario count + changeset. I've got the workflow down from the scenario work I did in #133/#147.

    Happy to take it if you're good with that. Thanks!

  4. sepehr-safari commented on Aug 8, 2026

    @sepehr-safari
    MemberAuthor

    Yes, it is yours, and sorry for the slow reply.

    One thing to flag before you start, because the issue body changed after it was
    first written and your summary above matches the original rather than the current
    version. The scenario is now a negative control: expectedFailures: [] with a
    no_failures assertion, exactly as you describe, and the reason matters. A flat
    meter register is not a detectable fault today. METER_VALUE_ANOMALY only fires on
    readings that go negative or decrease, and an all-zero series does neither, so this
    trace has to come back completely clean. The scenario exists to pin that down, so a
    future change to the rule cannot start reporting it by accident. Whether a stuck
    register deserves a rule of its own is a separate question, tracked in #144.

    One correction to the issue body before you start, which is on me. It reserves
    CS-SYNTHETIC-017, and that ID is no longer free: refused-authorization.ts took
    it when it shipped in 0.4.5, after this issue was written. Please use
    CS-SYNTHETIC-021.
    I have updated the issue body to match, so it now says 021
    rather than 017. Everything else in the trace stands, and I checked that exact
    trace against the detection engine before writing it up, so it is known to produce
    no failures rather than assumed to.

    Two small things worth carrying over from #147: the changeset is patch, not
    minor, and please branch off current main rather than off a previous scenario
    branch, which is what tangled the last one.

  5. added 2 commits that reference this issue on Aug 10, 2026
    ca2bb0e
    6f7c081
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions