feat(reporter): apply server-pushed CV tuning from heartbeat response
Heartbeat POST now captures the response body (up to 2048 bytes) and looks for a "config" object. If cfg_version advances past the stored value and all tunable fields pass range validation, the new tuning is applied to g_cv and persisted to NVS. - cv_tuning_validate: pure range checker (cv.cpp) - cv_apply_tuning / cv_get_tuning: mutex-guarded helpers in main.cpp exposed via cv_apply.h; 500 ms timeout, drop on contention - post_json now returns int (HTTP status) and optionally captures the response body; existing callers check == 200 - heartbeat: parse → cfg_version check → override present fields → validate → apply → save. Silent no-op when server returns no config. - 3 new native tests (15/15 pass). timercam flash 1,423,897 bytes (+9,828 vs baseline).
This commit is contained in:
@@ -183,6 +183,54 @@ void test_cv_process_respects_runtime_min_blob() {
|
||||
TEST_ASSERT_EQUAL_INT(0, r.exits_delta);
|
||||
}
|
||||
|
||||
// Helper: init tuning to defaults (via cv_init) with cfg_version = 1
|
||||
static CVTuning make_default_tuning() {
|
||||
CVState s;
|
||||
cv_init(s);
|
||||
s.tuning.cfg_version = 1;
|
||||
return s.tuning;
|
||||
}
|
||||
|
||||
void test_cv_tuning_validate_accepts_defaults() {
|
||||
CVTuning t = make_default_tuning();
|
||||
TEST_ASSERT_TRUE(cv_tuning_validate(t));
|
||||
}
|
||||
|
||||
void test_cv_tuning_validate_rejects_zero_version() {
|
||||
CVTuning t = make_default_tuning();
|
||||
t.cfg_version = 0;
|
||||
TEST_ASSERT_FALSE(cv_tuning_validate(t));
|
||||
}
|
||||
|
||||
void test_cv_tuning_validate_rejects_each_boundary() {
|
||||
// diff_thresh: 5–120
|
||||
{ CVTuning t = make_default_tuning(); t.diff_thresh = 4; TEST_ASSERT_FALSE(cv_tuning_validate(t)); }
|
||||
{ CVTuning t = make_default_tuning(); t.diff_thresh = 121; TEST_ASSERT_FALSE(cv_tuning_validate(t)); }
|
||||
// min_blob_px: 16–4096
|
||||
{ CVTuning t = make_default_tuning(); t.min_blob_px = 15; TEST_ASSERT_FALSE(cv_tuning_validate(t)); }
|
||||
{ CVTuning t = make_default_tuning(); t.min_blob_px = 4097; TEST_ASSERT_FALSE(cv_tuning_validate(t)); }
|
||||
// max_move: 2.0–50.0
|
||||
{ CVTuning t = make_default_tuning(); t.max_move = 1.9f; TEST_ASSERT_FALSE(cv_tuning_validate(t)); }
|
||||
{ CVTuning t = make_default_tuning(); t.max_move = 50.1f; TEST_ASSERT_FALSE(cv_tuning_validate(t)); }
|
||||
// max_missed: 1–60
|
||||
{ CVTuning t = make_default_tuning(); t.max_missed = 0; TEST_ASSERT_FALSE(cv_tuning_validate(t)); }
|
||||
{ CVTuning t = make_default_tuning(); t.max_missed = 61; TEST_ASSERT_FALSE(cv_tuning_validate(t)); }
|
||||
// line_offset: 0–100 (uint8 so only upper bound is meaningful)
|
||||
{ CVTuning t = make_default_tuning(); t.line_offset = 101; TEST_ASSERT_FALSE(cv_tuning_validate(t)); }
|
||||
|
||||
// Sanity: inclusive mins/maxes still pass
|
||||
{ CVTuning t = make_default_tuning(); t.diff_thresh = 5; TEST_ASSERT_TRUE(cv_tuning_validate(t)); }
|
||||
{ CVTuning t = make_default_tuning(); t.diff_thresh = 120; TEST_ASSERT_TRUE(cv_tuning_validate(t)); }
|
||||
{ CVTuning t = make_default_tuning(); t.min_blob_px = 16; TEST_ASSERT_TRUE(cv_tuning_validate(t)); }
|
||||
{ CVTuning t = make_default_tuning(); t.min_blob_px = 4096; TEST_ASSERT_TRUE(cv_tuning_validate(t)); }
|
||||
{ CVTuning t = make_default_tuning(); t.max_move = 2.0f; TEST_ASSERT_TRUE(cv_tuning_validate(t)); }
|
||||
{ CVTuning t = make_default_tuning(); t.max_move = 50.0f;TEST_ASSERT_TRUE(cv_tuning_validate(t)); }
|
||||
{ CVTuning t = make_default_tuning(); t.max_missed = 1; TEST_ASSERT_TRUE(cv_tuning_validate(t)); }
|
||||
{ CVTuning t = make_default_tuning(); t.max_missed = 60; TEST_ASSERT_TRUE(cv_tuning_validate(t)); }
|
||||
{ CVTuning t = make_default_tuning(); t.line_offset = 0; TEST_ASSERT_TRUE(cv_tuning_validate(t)); }
|
||||
{ CVTuning t = make_default_tuning(); t.line_offset = 100; TEST_ASSERT_TRUE(cv_tuning_validate(t)); }
|
||||
}
|
||||
|
||||
void test_no_crossing_same_side_no_count() {
|
||||
CVState state;
|
||||
cv_init(state);
|
||||
@@ -212,5 +260,8 @@ int main() {
|
||||
RUN_TEST(test_no_crossing_same_side_no_count);
|
||||
RUN_TEST(test_cv_init_populates_tuning_defaults);
|
||||
RUN_TEST(test_cv_process_respects_runtime_min_blob);
|
||||
RUN_TEST(test_cv_tuning_validate_accepts_defaults);
|
||||
RUN_TEST(test_cv_tuning_validate_rejects_zero_version);
|
||||
RUN_TEST(test_cv_tuning_validate_rejects_each_boundary);
|
||||
return UNITY_END();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user