#pragma once #include namespace kvida { // Fine-grained channel identifiers, one per physical quantity a sensor can // expose -- mirrors Zephyr's SENSOR_CHAN_* granularity so a single sensor // (e.g. a BME280) can expose several channels from one fetch(). enum class SensorChannel { Contact, Motion, AmbientTemperature, Humidity, Pressure, AccelX, AccelY, AccelZ, Analog, PulseCount, Generic, }; // Fixed-point value: actual value = val1 + val2 * 1e-6 (same convention as // Zephyr's struct sensor_value). ESP32-C6 has no hardware FPU, so avoiding // float/double here avoids paying for software-emulated floating point on // every sample -- relevant given the battery-first design goal. struct SensorValue { int32_t val1; int32_t val2; const char* unit; uint64_t timestamp_ms; }; enum class SensorTriggerType { DataReady, Threshold, }; // Plain function pointer + user_data, not std::function, to avoid heap // allocation for callback storage on embedded targets. using SensorTriggerHandler = void (*)(void* user_data); class Sensor { public: virtual ~Sensor() = default; virtual const char* id() const = 0; virtual void begin() = 0; // True if this sensor exposes the given channel. Lets `profiles` // discover capabilities generically instead of hardcoding per // concrete sensor. virtual bool supports(SensorChannel channel) const = 0; // Triggers a hardware read and caches the result internally. A // single fetch() may populate several channels at once (e.g. one // I2C transaction on a BME280 yields temperature + humidity + // pressure), so multi-channel sensors only pay the hardware cost // once per fetch(), not once per channel. virtual bool fetch() = 0; // Reads a previously fetched channel from the internal cache. // Returns false if the sensor doesn't support the channel, or if // fetch() hasn't been called yet. virtual bool get(SensorChannel channel, SensorValue& out) = 0; // Registers an interrupt-driven callback (data-ready pin, threshold // crossing, edge on a reed switch, ...) for sensors that support it. // Default: not supported: polling-only sensors don't override this. virtual bool set_trigger(SensorTriggerType type, SensorTriggerHandler handler, void* user_data) { (void)type; (void)handler; (void)user_data; return false; } }; } // namespace kvida