Files
deckenlampe/main/feature_tsl.cpp
T
2021-08-06 15:50:44 +02:00

134 lines
4.7 KiB
C++

#include "feature_tsl.h"
// esp-idf includes
#include <esp_log.h>
// 3rdparty lib includes
#include <fmt/core.h>
#include <Adafruit_TSL2561_U.h>
// local includes
#include "myconfig.h"
#include "mymqtt.h"
#include "delayedconstruction.h"
using namespace std::chrono_literals;
namespace deckenlampe {
std::optional<TslValue> lastTslValue;
espchrono::millis_clock::time_point last_tsl2561_lux_pub;
bool tslInitialized{};
namespace {
constexpr const char * const TAG = "TSL";
cpputils::DelayedConstruction<Adafruit_TSL2561_Unified> tsl;
espchrono::millis_clock::time_point last_tsl2561_readout;
} // namespace
void init_tsl()
{
if (!config::enable_i2c.value() || !config::enable_tsl.value())
return;
tsl.construct(TSL2561_ADDR_FLOAT, 12345);
ESP_LOGI(TAG, "calling tsl.begin()...");
tslInitialized = tsl->begin(true);
ESP_LOGI(TAG, "finished with %s", tslInitialized ? "true" : "false");
if (tslInitialized)
{
sensor_t sensor = tsl->getSensor();
ESP_LOGI(TAG, "------------------------------------");
ESP_LOGI(TAG, "Sensor: %s", sensor.name);
ESP_LOGI(TAG, "Driver Ver: %i", sensor.version);
ESP_LOGI(TAG, "Unique ID: %i", sensor.sensor_id);
ESP_LOGI(TAG, "Max Value: %.1f lux", sensor.max_value);
ESP_LOGI(TAG, "Min Value: %.1f lux", sensor.min_value);
ESP_LOGI(TAG, "Resolution: %.1f lux", sensor.resolution);
ESP_LOGI(TAG, "------------------------------------");
ESP_LOGI(TAG, "");
/* You can also manually set the gain or enable auto-gain support */
// tsl->setGain(TSL2561_GAIN_1X); /* No gain ... use in bright light to avoid sensor saturation */
// tsl->setGain(TSL2561_GAIN_16X); /* 16x gain ... use in low light to boost sensitivity */
tsl->enableAutoRange(true); /* Auto-gain ... switches automatically between 1x and 16x */
/* Changing the integration time gives you better sensor resolution (402ms = 16-bit data) */
tsl->setIntegrationTime(TSL2561_INTEGRATIONTIME_13MS); /* fast but low resolution */
// tsl->setIntegrationTime(TSL2561_INTEGRATIONTIME_101MS); /* medium resolution and speed */
// tsl->setIntegrationTime(TSL2561_INTEGRATIONTIME_402MS); /* 16-bit data but slowest conversions */
/* Update these values depending on what you've set above! */
ESP_LOGI(TAG, "------------------------------------");
ESP_LOGI(TAG, "Gain: Auto");
ESP_LOGI(TAG, "Timing: 13 ms");
ESP_LOGI(TAG, "------------------------------------");
}
}
void update_tsl()
{
if (!config::enable_i2c.value() || !config::enable_tsl.value())
return;
if (tslInitialized)
{
if (espchrono::ago(last_tsl2561_readout) < 5s)
return;
last_tsl2561_readout = espchrono::millis_clock::now();
if (std::optional<sensors_event_t> event = tsl->getEvent())
{
/* Display the results (light is measured in lux) */
if (event->light)
{
TslValue tslValue {
.timestamp = espchrono::millis_clock::now(),
.lux = event->light
};
ESP_LOGI(TAG, "read tsl: %.1f lux", tslValue.lux);
if (mqttConnected)
{
if (!lastTslValue)
mqttVerbosePub(config::topic_tsl2561_availability.value(), "online", 0, 1);
if (!lastTslValue || espchrono::ago(last_tsl2561_lux_pub) >= config::valueUpdateInterval.value())
{
if (mqttVerbosePub(config::topic_tsl2561_lux.value(), fmt::format("{:.1f}", tslValue.lux), 0, 1) >= 0)
last_tsl2561_lux_pub = espchrono::millis_clock::now();
}
}
lastTslValue = tslValue;
}
else
{
/* If event.light = 0 lux the sensor is probably saturated
* and no reliable data could be generated! */
ESP_LOGW(TAG, "tsl sensor overload %f", event->light);
goto tslOffline;
}
}
else
{
ESP_LOGW(TAG, "tsl failed");
goto tslOffline;
}
}
else
{
tslOffline:
if (lastTslValue && espchrono::ago(lastTslValue->timestamp) >= config::availableTimeoutTime.value())
{
ESP_LOGW(TAG, "tsl timeouted");
if (mqttConnected)
mqttVerbosePub(config::topic_tsl2561_availability.value(), "offline", 0, 1);
lastTslValue = std::nullopt;
}
}
}
} // namespace deckenlampe