#ifndef __THER_INFRARED_HPP__ #define __THER_INFRARED_HPP__ #include #include #include #include #include #include #include #include namespace ther { class Infrared { public: static auto Init() -> zpp::error { static sensor_trigger tri{.type = SENSOR_TRIG_DATA_READY, .chan = SENSOR_CHAN_AMBIENT_TEMP}; for (auto dev : s_dev) { if (auto r = sensor_trigger_set( dev, &tri, [](const device *dev, const sensor_trigger *trig) { const size_t id = etl::distance( s_dev.begin(), etl::find(s_dev.begin(), s_dev.end(), dev)); s_dev_ready[id] = 1; }); r != 0) { return -ENODEV; } } return zpp::ok(); } /* One-shot fetch of ALL sensors, return the hottest one. */ static auto GetMaxSensorValue() -> zpp::result> { bool found = false; int max_id = 0; sensor_value max_val{}; for (size_t id = 0; id < s_dev.size(); ++id) { /* -ENODATA just means no new sample for this channel; keep going. */ if (0 != sensor_sample_fetch(s_dev[id])) { continue; } sensor_value val; if (0 != sensor_channel_get(s_dev[id], SENSOR_CHAN_AMBIENT_TEMP, &val)) { s_dev_ready[id] = 0; /* sample consumed, drop the ready flag */ continue; } s_dev_ready[id] = 0; if (!found || val.val1 > max_val.val1 || (val.val1 == max_val.val1 && val.val2 > max_val.val2)) { found = true; max_id = static_cast(id); max_val = val; } } if (!found) { return zpp::error_code::k_nodata; } return std::make_pair(max_id, max_val); } private: #define INFRARED_DEV(node) DEVICE_DT_GET(node), inline static etl::array s_dev{ DT_FOREACH_STATUS_OKAY(godtek_temp_uart, INFRARED_DEV)}; inline static etl::bitset s_dev_ready; }; } // namespace ther #endif