Toner: count cartridge changes that happened, and rate a burst as one burst
Two things reported from the floor, one cause each. "5 CHANGES IN 90 DAYS, THAT'S HARD TO BELIEVE." It was. A replacement was any +10 rise between readings, with no check on where it landed, so two shapes that are not swaps scored as swaps: a supply reading 0 or near-0 while it was out of the machine and then reading normally again, and a coarse gauge ticking back up after a reseat or a power cycle. A swap must now also LAND near full, because that is what a new cartridge reads, and a single dip that RECOVERS to roughly where it came from is dropped before anything looks at it. The dip filter keys on shape rather than cause, which is why it holds for all of them - a supply pulled out to be shaken, a door open mid-poll, or a site whose preprocessing maps the Printer MIB's unknown sentinels onto 0. It is NOT a Zabbix timeout: an item that does not answer records nothing rather than writing a zero. A genuine near-empty reading before a real swap does not recover, it jumps to full, so it survives and its swap still counts. find_replacements and current_run now read one predicate. When they disagreed, a phantom rise reset the run and threw away the history the estimate needed - so the bad count was quietly damaging the rate as well, which is why both were wrong at once. Expect replacement counts to FALL and per-cartridge history to lengthen. A BURST BIASED THE RATE FOR THE LIFE OF THE CARTRIDGE. The rate was the slope between the first and last reading of the run, and two endpoints cannot tell "steady" from "burst then stopped". A cartridge that lost 20 percent in two days and then barely moved for a month read as 0.83 percent/day forever after, so the report kept promising it would run out long after printing slowed. It is now the median of the per-interval rates: the burst is one interval among many rather than one of two points. Rising intervals are dropped as noise; flat ones stay in at zero, because a cartridge that did not move is real information. If every interval is flat or rising yet the run dropped overall, it falls back to the whole-run slope rather than reporting nothing. Where the intervals disagree by 5x or more the rate carries a marker and an explanation on hover. The number is still the best estimate available; the flag stops it reading as a measurement. The "Changed" column is "Replacements", and its cell says "2 in 90d" rather than "2 / 90d", which was read as a date, a ratio and a version number.
This commit is contained in:
@@ -90,7 +90,7 @@
|
||||
<th class="collevel">Level</th>
|
||||
<th>Runs out</th>
|
||||
<th>Rate</th>
|
||||
<th>Changed</th>
|
||||
<th title="Cartridge changes detected, over the days of history behind this row">Replacements</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -123,11 +123,20 @@
|
||||
<span class="days" :class="c.band">{{ daysText(c) }}</span>
|
||||
</td>
|
||||
<td class="muted small">
|
||||
{{ c.burnrateperday != null ? c.burnrateperday + '%/day' : '-' }}
|
||||
<template v-if="c.burnrateperday != null">
|
||||
{{ c.burnrateperday }}%/day<!--
|
||||
--><span v-if="c.rateunstable" class="unstable"
|
||||
title="This cartridge's usage has varied a lot between readings - a burst then a lull, or the reverse. The estimate is the best available, not a measurement.">~</span>
|
||||
</template>
|
||||
<template v-else>-</template>
|
||||
</td>
|
||||
<td class="muted small">
|
||||
{{ c.replacements || 0 }}
|
||||
<span v-if="c.basisdays">/ {{ c.basisdays }}d</span>
|
||||
<!-- "2 / 90d" read as a date, a ratio, or a version to
|
||||
everyone who saw it. Say the unit. -->
|
||||
<template v-if="c.basisdays">
|
||||
{{ c.replacements || 0 }} in {{ c.basisdays }}d
|
||||
</template>
|
||||
<template v-else>{{ c.replacements || 0 }}</template>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
@@ -424,6 +433,10 @@ onMounted(load)
|
||||
.days.empty { color: var(--danger); }
|
||||
.days.soon { color: var(--warning); }
|
||||
.small { font-size: 0.8rem; }
|
||||
|
||||
/* Marks a rate the intervals do not agree on. Deliberately quiet - it qualifies
|
||||
the number beside it rather than competing with the urgency bands. */
|
||||
.unstable { margin-left: 2px; font-weight: 600; cursor: help; }
|
||||
.empty-state { padding: 2rem; text-align: center; }
|
||||
.footnote { margin-top: 1rem; font-size: 0.85rem; }
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user