Add sensors Sensor interface and a verified host test setup
Sensor/SensorValue in components/sensors/include/sensor.h is modeled on Zephyr's sensor API: a fetch()/get() split so multi-channel sensors (e.g. BME280) pay the hardware read cost once, fixed-point SensorValue (no float/double -- ESP32-C6 has no hardware FPU), a fine-grained SensorChannel enum, and an optional interrupt-driven set_trigger() for the battery-first sleep/wake design. Adds components/sensors/test_apps/host, a self-contained ESP-IDF project building against the `linux` target so this logic is host-testable per AGENTS.md's testing philosophy -- verified in a clean run against the pinned espressif/idf:v6.0.2 image (builds, 4/4 tests pass). Replaces the earlier generic top-level test/README.md placeholder now that a real per-component pattern exists. Also fixes .gitignore's build/managed_components patterns to match nested paths, not just the repo root. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
4
components/sensors/test_apps/host/main/CMakeLists.txt
Normal file
4
components/sensors/test_apps/host/main/CMakeLists.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
idf_component_register(
|
||||
SRCS "test_sensor.cpp"
|
||||
PRIV_REQUIRES sensors unity
|
||||
)
|
||||
85
components/sensors/test_apps/host/main/test_sensor.cpp
Normal file
85
components/sensors/test_apps/host/main/test_sensor.cpp
Normal file
@@ -0,0 +1,85 @@
|
||||
#include "sensor.h"
|
||||
#include "unity.h"
|
||||
|
||||
using namespace kvida;
|
||||
|
||||
namespace {
|
||||
|
||||
// Minimal fake sensor exercising the fetch()/get() cache contract and
|
||||
// SensorValue's fixed-point convention (val1 + val2 * 1e-6).
|
||||
class FakeSensor : public Sensor {
|
||||
public:
|
||||
const char *id() const override { return "fake0"; }
|
||||
void begin() override {}
|
||||
|
||||
bool supports(SensorChannel channel) const override
|
||||
{
|
||||
return channel == SensorChannel::AmbientTemperature;
|
||||
}
|
||||
|
||||
bool fetch() override
|
||||
{
|
||||
fetched_ = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool get(SensorChannel channel, SensorValue &out) override
|
||||
{
|
||||
if (!fetched_ || channel != SensorChannel::AmbientTemperature) {
|
||||
return false;
|
||||
}
|
||||
out = SensorValue{21, 500000, "C", 1234};
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
bool fetched_ = false;
|
||||
};
|
||||
|
||||
double to_double(const SensorValue &v)
|
||||
{
|
||||
return v.val1 + v.val2 * 1e-6;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST_CASE("get fails before fetch", "[sensor]")
|
||||
{
|
||||
FakeSensor sensor;
|
||||
SensorValue value{};
|
||||
TEST_ASSERT_FALSE(sensor.get(SensorChannel::AmbientTemperature, value));
|
||||
}
|
||||
|
||||
TEST_CASE("fetch then get returns the cached value", "[sensor]")
|
||||
{
|
||||
FakeSensor sensor;
|
||||
sensor.begin();
|
||||
TEST_ASSERT_TRUE(sensor.fetch());
|
||||
|
||||
SensorValue value{};
|
||||
TEST_ASSERT_TRUE(sensor.get(SensorChannel::AmbientTemperature, value));
|
||||
TEST_ASSERT_EQUAL_DOUBLE(21.5, to_double(value));
|
||||
}
|
||||
|
||||
TEST_CASE("get fails for an unsupported channel", "[sensor]")
|
||||
{
|
||||
FakeSensor sensor;
|
||||
sensor.begin();
|
||||
sensor.fetch();
|
||||
|
||||
SensorValue value{};
|
||||
TEST_ASSERT_FALSE(sensor.get(SensorChannel::Humidity, value));
|
||||
}
|
||||
|
||||
TEST_CASE("default set_trigger reports unsupported", "[sensor]")
|
||||
{
|
||||
FakeSensor sensor;
|
||||
TEST_ASSERT_FALSE(sensor.set_trigger(SensorTriggerType::DataReady, nullptr, nullptr));
|
||||
}
|
||||
|
||||
extern "C" void app_main(void)
|
||||
{
|
||||
UNITY_BEGIN();
|
||||
unity_run_all_tests();
|
||||
UNITY_END();
|
||||
}
|
||||
Reference in New Issue
Block a user