For new projects, start with SuperJupiter Sensor Toolkit. This standalone package and its published releases remain available. Existing installations need no change.
If migrating with PlatformIO, replace the standalone dependency with:
lib_deps = superjupiter/SuperJupiterSensorToolkit@0.1.0Replace this standalone include:
#include <SuperJupiterSensorQuality.h>with this consolidated include:
#include <SuperJupiter/SensorToolkit/SensorQuality.h>The component namespace and behaviour are preserved from standalone 0.2.1. If using an earlier version, review its API migration requirements first. Use one implementation of this component per application; do not mix standalone and consolidated copies.
See the consolidated migration guide and consolidated README for Arduino/CMake installation. Hardware validation pending.
Flag suspicious sensor readings without changing the raw data.
A small, allocation-free C++11 library for Arduino, ESP32 and host applications. Use one monitor per sensor channel to report invalid numbers, out-of-range values, rapid changes, late samples, stale data and possibly stuck signals.
Status: early release. Software tests and board compilation are automated; physical hardware validation is pending. A passing quality check is not proof that a sensor is accurate. This library does not provide safety certification.
Your sensor driver -> raw value + sample timestamp -> SensorQuality -> quality flags
| |
+---------- raw data ----------+-> your logger / application
- Keep the original measurement, including invalid values, available for investigation.
- Catch stale data when a driver stops producing new measurements.
- Make quality problems explicit instead of quietly replacing or smoothing values.
- Use your existing sensor driver, storage and transport. No account, network or cloud required.
- No heap allocation, external dependencies, background task or hidden clock reads.
- In Library Manager search for SuperJupiterSensorQuality by SuperJupiter.
- Install 0.2.1 once it appears in your refreshed index.
- Open File > Examples > SuperJupiterSensorQuality > SyntheticTemperature.
- Select your board, upload and open Serial Monitor at 115200 baud.
Library Manager registration is live. New tags require index processing; check that your selected version is 0.2.1 rather than assuming a cached index is current. For an exact CLI installation:
arduino-cli lib update-index
arduino-cli lib install "SuperJupiterSensorQuality@0.2.1"Alternatively, download the source ZIP from Releases and choose Sketch > Include Library > Add .ZIP Library.
Use the official registry package with an exact version pin:
lib_deps = superjupiter/SuperJupiterSensorQuality@0.2.1@^0.2.1 is a compatible version range, not an exact pin. A Git tag is an
alternative: https://github.com/Super-Jupiter/superjupiter-sensor-quality.git#v0.2.1.
Package name, repository and include header are unchanged. The C++ namespace
changed in 0.2.0; see migration.
#include <SuperJupiterSensorQuality.h>
superjupiter::sensor_quality::Config makeConfig() {
superjupiter::sensor_quality::Config c;
c.rangeEnabled = true;
c.minimum = -40.0f; // Example Celsius limits, not universal limits.
c.maximum = 125.0f;
c.expectedIntervalMs = 100; // Expected observation interval, approximately 10 Hz.
c.gapToleranceMs = 30;
c.staleAfterMs = 750;
c.maxRatePerSecond = 10.0f; // Example limit in degrees C / second.
c.stuckAfterMs = 5000;
c.stuckTolerance = 0.02f;
return c;
}
superjupiter::sensor_quality::SensorQuality temperature(makeConfig());
void onFreshReading(float rawCelsius, uint32_t sampledAtMs) {
const superjupiter::sensor_quality::Result result = temperature.observe(rawCelsius, sampledAtMs);
// Store result.value and result.flags together. The value is not corrected.
if (result.has(superjupiter::sensor_quality::OutOfRange)) {
// Your application decides whether to log, alert or ignore this reading.
}
}
void checkWhileWaiting(uint32_t nowMs) {
const superjupiter::sensor_quality::Result current = temperature.inspect(nowMs);
if (current.has(superjupiter::sensor_quality::Stale)) {
// No sufficiently recent finite, in-range observation is available.
}
}Call observe() only for a fresh measurement. Resubmitting a cached value with
a new timestamp hides staleness. Reading a thermocouple interface at 10 Hz does
not prove that its converter supplies 10 fresh conversions per second.
| Flag | Meaning |
|---|---|
NoData |
No observation has been accepted since construction or reset. |
InvalidNumber |
The raw reading is NaN or positive/negative infinity. |
OutOfRange |
The reading is outside your inclusive minimum/maximum bounds. |
RateExceeded |
The absolute change per second exceeds your configured limit. |
Stuck |
Consecutive readings stayed within tolerance of a fixed anchor long enough to be suspicious. |
SampleGap |
The interval exceeds expected interval plus tolerance. It does not prove how many samples were lost. |
Stale |
No finite, in-range observation exists, or its age meets/exceeds the configured limit. |
InvalidTimestamp |
A timestamp is duplicate, backward or outside the supported comparison span. |
InvalidConfiguration |
Settings are inconsistent or contain unsupported values. |
Flags can occur together. A constant temperature can be entirely legitimate;
Stuck is a prompt to investigate, not a diagnosis. All configurable checks are
disabled by default. Invalid numbers and timestamp ordering are always checked.
See API and exact semantics before using flags to drive decisions.
On a machine with a C++11 compiler:
g++ -std=c++11 -Wall -Wextra -Werror -Isrc tools/replay.cpp -o replay
./replayThe synthetic example shows an excursion, NaN, out-of-range data, a possibly stuck signal and stale data. There is no sensor, network or hidden telemetry.
sampled_at_ms,raw_value,flags
0,20,healthy
100,20.1,healthy
200,80,rate_exceeded
300,20.1,rate_exceeded
400,nan,invalid_number
500,200,out_of_range
...
900,22,possibly_stuck
900,22,possibly_stuck|stale
The repeated 900 timestamp is intentional: inspect() does not invent a fresh sample.
The core uses standard C++11 with <stdint.h> and <float.h>. Arduino metadata
uses architectures=* to describe this portable source; that is not a claim that
every board has been physically tested.
CI runs host tests with GCC and Clang, including address/undefined-behaviour sanitisers, and compiles both examples for ESP32, ESP32-S3, ESP32-C3 and Arduino Uno. See the actual CI results and validation record for evidence and limitations.
cmake -S . -B build -DSUPERJUPITER_SENSOR_QUALITY_BUILD_TESTS=ON
cmake --build build
ctest --test-dir build --output-on-failureNo persistence, smoothing, calibration, sensor-fault register decoding, automatic retries or transport is included. Monitor calls must be serialised by the caller.
- Validate the synthetic example on real ESP32 hardware.
- Add an accurately documented integration with an established sensor driver.
- Publish measured memory and timing results for exact board/compiler versions.
- Keep Arduino/PlatformIO package consumer checks and release records current.
Bug reports and small, well-tested contributions are welcome. Include settings, timestamps, expected behaviour and a minimal reproduction. Read CONTRIBUTING.md and SECURITY.md.
SuperJupiter builds custom software, connected devices and operational platforms. This library is a standalone, free component for the wider developer community, under the MIT licence.
No SuperJupiter service is required to use it. Contact: info@superjupiter.net.
add_subdirectory(path/to/superjupiter-sensor-quality)
target_link_libraries(your_application PRIVATE SuperJupiter::SensorQuality)Tests, examples and install rules default to OFF when included as a subproject.
For an installed package, use find_package(SuperJupiterSensorQuality 0.2 CONFIG REQUIRED)
and the same target. See build and release conventions.
Do not compile this library with fast-math or finite-math-only assumptions: invalid-number detection requires non-finite values to retain their meaning.
This patch includes independent regression tests and a reviewed interoperability contract. Hardware validation pending.
- Explicit numeric-error flag and zero unavailable rate for reduced-precision rate overflow; raw readings retained.