Newer
Older
smart-home-server / devices / sensor / bh1750_sensor.cpp
@root root 18 hours ago 2 KB Device. Sensor
#include "bh1750_sensor.h"

Bh1750Sensor::Bh1750Sensor() {
}

bool Bh1750Sensor::begin(const Bh1750Config &config) {
	_config = config;

	Wire.begin(_config.sda_pin, _config.scl_pin);

	/*
		Пробуем перевести датчик в выбранный режим измерения.
	*/
	if (!send_command(_config.measurement_mode)) {
		_initialized = false;
		_online = false;
		return false;
	}

	_initialized = true;
	_online = true;
	return true;
}

void Bh1750Sensor::update() {
	if (!_initialized) {
		return;
	}

	uint32_t now_ms = millis();

	if (now_ms - _last_read_attempt_ms < _config.read_interval_ms) {
		return;
	}

	_last_read_attempt_ms = now_ms;

	uint16_t raw_value = 0;
	if (!read_measurement(raw_value)) {
		_online = false;
		return;
	}

	_online = true;
	_has_valid_data = true;
	_last_success_read_ms = now_ms;
	_last_raw_value = raw_value;

	/*
		Согласно даташиту:
		lux = raw / 1.2
	*/
	_raw_lux = static_cast<float>(raw_value) / 1.2f;

	update_filtered_lux(_raw_lux);
}

float Bh1750Sensor::get_raw_lux() const {
	return _raw_lux;
}

float Bh1750Sensor::get_filtered_lux() const {
	return _filtered_lux;
}

bool Bh1750Sensor::has_valid_data() const {
	return _has_valid_data;
}

bool Bh1750Sensor::is_stale() const {
	if (!_has_valid_data) {
		return true;
	}

	uint32_t now_ms = millis();
	return (now_ms - _last_success_read_ms) > _config.stale_after_ms;
}

bool Bh1750Sensor::is_online() const {
	return _online;
}

String Bh1750Sensor::get_state_json() const {
	String json = "{";
	json += "\"sensor\":\"bh1750\",";
	json += "\"online\":" + String(_online ? "true" : "false") + ",";
	json += "\"has_valid_data\":" + String(_has_valid_data ? "true" : "false") + ",";
	json += "\"stale\":" + String(is_stale() ? "true" : "false") + ",";
	json += "\"i2c_address\":\"0x" + String(_config.i2c_address, HEX) + "\",";

	json += "\"data\":{";
	json += "\"raw_value\":" + String(_last_raw_value) + ",";
	json += "\"raw_lux\":" + String(_raw_lux, 2) + ",";
	json += "\"filtered_lux\":" + String(_filtered_lux, 2);
	json += "}";

	json += "}";

	return json;
}

bool Bh1750Sensor::send_command(uint8_t command) {
	Wire.beginTransmission(_config.i2c_address);
	Wire.write(command);
	return (Wire.endTransmission() == 0);
}

bool Bh1750Sensor::read_measurement(uint16_t &raw_out) {
	Wire.requestFrom((int)_config.i2c_address, 2);

	if (Wire.available() != 2) {
		return false;
	}

	uint8_t msb = Wire.read();
	uint8_t lsb = Wire.read();

	raw_out = (static_cast<uint16_t>(msb) << 8) | lsb;
	return true;
}

void Bh1750Sensor::update_filtered_lux(float new_lux) {
	if (!_has_valid_data || _filtered_lux == 0.0f) {
		_filtered_lux = new_lux;
		return;
	}

	_filtered_lux =
		(_filtered_lux * (1.0f - _config.lux_ema_alpha)) +
		(new_lux * _config.lux_ema_alpha);
}