mirror of
https://github.com/mikecarper/MeshCore.git
synced 2026-11-12 07:49:49 +00:00
Compare Sensor subscription deltas in exact LPP units
This commit is contained in:
1 parent
56a2918f9f
commit
277f6d174b
3 files changed
+183
-5
No files matched your search
@@ -323,6 +323,133 @@ static void snapshot_checks() {
|
||||
}
|
||||
std::cout << "Raw LPP snapshot samples checked: " << samples << '\n';
|
||||
}
|
||||
static void store_raw(uint8_t* data, uint8_t size, int64_t value) {
|
||||
uint64_t raw = uint64_t(value);
|
||||
for (unsigned i = size; i > 0; --i) {
|
||||
data[i - 1] = uint8_t(raw);
|
||||
raw >>= 8;
|
||||
}
|
||||
}
|
||||
static void expect_delta(uint8_t type, int64_t previous, int64_t current,
|
||||
int64_t threshold, bool expected) {
|
||||
SensorMesh target;
|
||||
ClientInfo client;
|
||||
const uint8_t size = LPPData::getDataSize(type);
|
||||
assert(subscribe(target, client, type, size) == 12);
|
||||
store_raw(client.extra.sensor.min_deltas + 2, size, threshold);
|
||||
target.telemetry.bytes.resize(2 + size);
|
||||
target.telemetry.bytes[0] = 1;
|
||||
target.telemetry.bytes[1] = type;
|
||||
store_raw(target.telemetry.getBuffer() + 2, size, previous);
|
||||
target.snapshotTelemetry(&client);
|
||||
const auto baseline = target.telemetry.bytes;
|
||||
store_raw(target.telemetry.getBuffer() + 2, size, current);
|
||||
for (unsigned repeat = 0; repeat < 2; ++repeat) {
|
||||
assert(target.telemHasChanged(&client) == expected
|
||||
&& "raw LPP delta must use the exact strict threshold");
|
||||
assert(!memcmp(client.extra.sensor.prev_telem, baseline.data(), baseline.size()));
|
||||
}
|
||||
}
|
||||
static void delta_checks() {
|
||||
for (unsigned type = 0; type < 256; ++type) {
|
||||
if (!LPPData::isScalarType(type)) continue;
|
||||
// Equal, smaller, and larger positive thresholds in both directions.
|
||||
for (int64_t step : {0, 1, 2, 3}) {
|
||||
expect_delta(type, 10, 10 + step, 2, step > 2);
|
||||
expect_delta(type, 10 + step, 10, 2, step > 2);
|
||||
expect_delta(type, 10, 10 + step, 0, step != 0);
|
||||
}
|
||||
const uint8_t size = LPPData::getDataSize(type);
|
||||
if (LPPData::isSigned(type)) {
|
||||
const int64_t minimum = -(int64_t(1) << (8 * size - 1));
|
||||
const int64_t maximum = -minimum - 1;
|
||||
expect_delta(type, minimum, maximum, maximum, true);
|
||||
expect_delta(type, maximum, minimum, maximum, true);
|
||||
expect_delta(type, minimum, minimum + 1, 1, false);
|
||||
expect_delta(type, -2, 1, 3, false);
|
||||
expect_delta(type, 1, -2, 2, true);
|
||||
// Negative signed thresholds retain their existing always-trigger behavior.
|
||||
expect_delta(type, -2, -2, -1, true);
|
||||
expect_delta(type, 0, 0, minimum, true);
|
||||
}
|
||||
SensorMesh target;
|
||||
ClientInfo client;
|
||||
assert(subscribe(target, client, type, size) == 12);
|
||||
target.telemetry.bytes.resize(2 + size);
|
||||
target.telemetry.bytes[0] = 1;
|
||||
target.telemetry.bytes[1] = type;
|
||||
store_raw(target.telemetry.getBuffer() + 2, size, 10);
|
||||
target.snapshotTelemetry(&client);
|
||||
store_raw(client.extra.sensor.min_deltas + 2, size, 10);
|
||||
const auto complete = target.telemetry.bytes;
|
||||
// Each truncated current record continues to use the zero default.
|
||||
for (unsigned length = 0; length < complete.size(); ++length) {
|
||||
target.telemetry.bytes.assign(complete.begin(), complete.begin() + length);
|
||||
assert(!target.telemHasChanged(&client));
|
||||
store_raw(client.extra.sensor.min_deltas + 2, size, 9);
|
||||
assert(target.telemHasChanged(&client));
|
||||
store_raw(client.extra.sensor.min_deltas + 2, size, 10);
|
||||
}
|
||||
target.telemetry.bytes = complete;
|
||||
store_raw(client.extra.sensor.min_deltas + 2, size, -1);
|
||||
client.extra.sensor.min_deltas_len = 1 + size;
|
||||
assert(!target.telemHasChanged(&client)); // Truncated thresholds stay rejected.
|
||||
}
|
||||
// Ordinary scaled readings emitted exactly by the production scalar writer.
|
||||
const struct { uint8_t type; int64_t previous, current; } ordinary[] = {
|
||||
{LPP_CURRENT, 1234, 1235}, {LPP_TEMPERATURE, 201, 202}
|
||||
};
|
||||
for (const auto& entry : ordinary) {
|
||||
const uint32_t multiplier = LPPData::getMultiplier(entry.type);
|
||||
for (int64_t raw : {entry.previous, entry.current}) {
|
||||
uint8_t bytes[4] = {};
|
||||
LPPWriter writer(bytes, sizeof(bytes));
|
||||
assert(writer.writeData(1, entry.type, float(raw) / multiplier));
|
||||
assert((uint32_t(bytes[2]) * 256 + bytes[3]) == raw);
|
||||
}
|
||||
expect_delta(entry.type, entry.previous, entry.current, 1, false);
|
||||
expect_delta(entry.type, entry.previous, entry.current + 1, 1, true);
|
||||
}
|
||||
}
|
||||
static void wide_delta_checks() {
|
||||
for (uint8_t type : {LPP_GENERIC_SENSOR, LPP_FREQUENCY, LPP_DISTANCE, LPP_ENERGY, LPP_UNIXTIME}) {
|
||||
assert(LPPData::getDataSize(type) == 4 && !LPPData::isSigned(type));
|
||||
for (uint32_t raw : {0x1000000U, 0x7fffffffU, 1700000000U, 0xfffffffeU}) {
|
||||
expect_delta(type, raw, uint64_t(raw) + 1, 0, true);
|
||||
expect_delta(type, uint64_t(raw) + 1, raw, 0, true);
|
||||
expect_delta(type, raw, uint64_t(raw) + 1, 1, false);
|
||||
}
|
||||
expect_delta(type, 16777219, 16777221, 1, true);
|
||||
expect_delta(type, 16777221, 16777219, 1, true);
|
||||
expect_delta(type, 0, UINT32_MAX, UINT32_MAX, false);
|
||||
expect_delta(type, UINT32_MAX, 0, UINT32_MAX - 1, true);
|
||||
expect_delta(type, UINT32_MAX, 1, UINT32_MAX - 1, false);
|
||||
}
|
||||
// Decoder sign extension covers every scalar width, including signed32.
|
||||
for (uint8_t size = 1; size <= 4; ++size) {
|
||||
const int64_t sign_bit = int64_t(1) << (8 * size - 1);
|
||||
for (int64_t value : {-sign_bit, -sign_bit + 1, int64_t(-1), int64_t(0), sign_bit - 1}) {
|
||||
uint8_t bytes[4] = {};
|
||||
store_raw(bytes, size, value);
|
||||
assert(readTelemRawValue(bytes, size, true) == value);
|
||||
}
|
||||
}
|
||||
assert(readTelemRawValue(nullptr, 4, false) == 0);
|
||||
uint8_t bytes[5] = {};
|
||||
assert(readTelemRawValue(bytes, 0, false) == 0);
|
||||
assert(readTelemRawValue(bytes, 5, false) == 0);
|
||||
}
|
||||
static void signed_wide_delta_checks() {
|
||||
// The runner supplies signed metadata for this normally unsigned scalar.
|
||||
const uint8_t type = LPP_GENERIC_SENSOR;
|
||||
assert(LPPData::getDataSize(type) == 4 && LPPData::isSigned(type));
|
||||
expect_delta(type, INT32_MIN, INT32_MAX, INT32_MAX, true);
|
||||
expect_delta(type, INT32_MAX, INT32_MIN, INT32_MAX, true);
|
||||
expect_delta(type, INT32_MIN, INT32_MIN + 1, 0, true);
|
||||
expect_delta(type, INT32_MAX - 1, INT32_MAX, 1, false);
|
||||
expect_delta(type, -16777217, -16777216, 0, true);
|
||||
expect_delta(type, 0, 0, INT32_MIN, true);
|
||||
}
|
||||
static void writer_checks() {
|
||||
uint8_t buffer[16];
|
||||
memset(buffer, 0xAA, sizeof(buffer));
|
||||
@@ -432,6 +559,9 @@ int main(int argc, char** argv) {
|
||||
else if (!strcmp(argv[1], "writer")) writer_checks();
|
||||
else if (!strcmp(argv[1], "tracker")) tracker_mode_checks();
|
||||
else if (!strcmp(argv[1], "snapshot")) snapshot_checks();
|
||||
else if (!strcmp(argv[1], "delta")) delta_checks();
|
||||
else if (!strcmp(argv[1], "wide-delta")) wide_delta_checks();
|
||||
else if (!strcmp(argv[1], "signed-wide-delta")) signed_wide_delta_checks();
|
||||
else assert(false);
|
||||
std::cout << "Sensor subscription checks passed\n";
|
||||
}
|
||||
Reference in new issue
Block a user