From 5c96cfc1f36005e38f76dd5cf8376a4debc183c1 Mon Sep 17 00:00:00 2001 From: Vitali Date: Fri, 17 Jul 2026 20:02:40 +0700 Subject: [PATCH] feat: in-RAM pressure history ring buffer with 3h trend Co-Authored-By: Claude Opus 4.8 --- WeatherPredictor/WeatherPredictor.ino | 13 +++++++++ WeatherPredictor/history.cpp | 38 +++++++++++++++++++++++++++ WeatherPredictor/history.h | 15 +++++++++++ 3 files changed, 66 insertions(+) create mode 100644 WeatherPredictor/history.cpp create mode 100644 WeatherPredictor/history.h diff --git a/WeatherPredictor/WeatherPredictor.ino b/WeatherPredictor/WeatherPredictor.ino index ceafb31..0a6d4af 100644 --- a/WeatherPredictor/WeatherPredictor.ino +++ b/WeatherPredictor/WeatherPredictor.ino @@ -5,6 +5,7 @@ #include "sensors.h" #include "rtc_time.h" #include "forecast.h" +#include "history.h" static void i2cScan() { Serial.println(F("I2C scan:")); @@ -46,6 +47,18 @@ void setup() { Serial.printf("p=%.0f trend=%d -> %c [%s] (%s)\n", c.p, c.tr, f.letter, f.text, categoryShort(f.category)); } + + // --- history self-test (remove after Task 8) --- + historyBegin(); + uint32_t base = 1000000000UL; + for (int i = 0; i < 40; i++) // 40 samples @ 5 min = 3h20m, pressure falling + historyAdd(base + (uint32_t)i * 300, 1015.0f - i * 0.2f, 20.0f); + float d; + if (historyTrendDelta(d)) + Serial.printf("history count=%d 3h delta=%.2f hPa trend=%d\n", + historyCount(), d, classifyTrend(d)); + else + Serial.println(F("history: not enough data for trend")); } void loop() { diff --git a/WeatherPredictor/history.cpp b/WeatherPredictor/history.cpp new file mode 100644 index 0000000..440c28e --- /dev/null +++ b/WeatherPredictor/history.cpp @@ -0,0 +1,38 @@ +#include "config.h" +#include "history.h" + +static Sample s_buf[HISTORY_SIZE]; +static int s_head = 0; // next write position +static int s_count = 0; + +void historyBegin() { s_head = 0; s_count = 0; } + +void historyAdd(uint32_t epoch, float mslHpa, float tempC) { + s_buf[s_head] = Sample{ epoch, mslHpa, tempC }; + s_head = (s_head + 1) % HISTORY_SIZE; + if (s_count < HISTORY_SIZE) s_count++; +} + +int historyCount() { return s_count; } + +Sample historyGet(int i) { + int start = (s_head - s_count + HISTORY_SIZE) % HISTORY_SIZE; + return s_buf[(start + i) % HISTORY_SIZE]; +} + +Sample historyLatest() { return historyGet(s_count - 1); } + +bool historyTrendDelta(float& outDelta) { + if (s_count < 2) return false; + Sample latest = historyLatest(); + uint32_t target = latest.epoch - 10800UL; // 3 h earlier + int idx = -1; + for (int i = 0; i < s_count; i++) { + if (historyGet(i).epoch <= target) idx = i; else break; + } + if (idx < 0) return false; + Sample past = historyGet(idx); + if (latest.epoch - past.epoch < 9000UL) return false; // need >= 2.5 h span + outDelta = latest.mslHpa - past.mslHpa; + return true; +} diff --git a/WeatherPredictor/history.h b/WeatherPredictor/history.h new file mode 100644 index 0000000..f63b36b --- /dev/null +++ b/WeatherPredictor/history.h @@ -0,0 +1,15 @@ +#pragma once +#include + +struct Sample { + uint32_t epoch; + float mslHpa; + float tempC; +}; + +void historyBegin(); +void historyAdd(uint32_t epoch, float mslHpa, float tempC); +int historyCount(); +Sample historyGet(int i); // 0 = oldest +Sample historyLatest(); +bool historyTrendDelta(float& outDeltaHpa);