76 lines
1.7 KiB
C++
76 lines
1.7 KiB
C++
#include "vindriktning.h"
|
|
#include "esphome/core/log.h"
|
|
|
|
namespace esphome {
|
|
namespace vindriktning {
|
|
|
|
static const char *const TAG = "vindriktning";
|
|
|
|
void VindriktningComponent::dump_config() {
|
|
ESP_LOGCONFIG(TAG, "VINDRIKTNING:");
|
|
LOG_SENSOR(" ", "PM2.5", this);
|
|
}
|
|
|
|
void VindriktningComponent::loop() {
|
|
if (!available()) {
|
|
return;
|
|
}
|
|
|
|
while (available()) {
|
|
serialRxBuf[rxBufIdx++] = read();
|
|
|
|
//FIXME: "anything in loop() or setup() should not block" see https://esphome.io/guides/contributing.html#runtime
|
|
delay(15);
|
|
|
|
if (rxBufIdx >= 64) {
|
|
clearRxBuf();
|
|
}
|
|
}
|
|
|
|
if (isValidHeader() && isValidChecksum()) {
|
|
uint16_t state = parseState();
|
|
ESP_LOGD(TAG, "Received PM 2.5 reading: %d", state);
|
|
publish_state((uint32_t) state);
|
|
}
|
|
|
|
clearRxBuf();
|
|
}
|
|
|
|
void VindriktningComponent::clearRxBuf() {
|
|
memset(serialRxBuf, 0, sizeof(serialRxBuf));
|
|
rxBufIdx = 0;
|
|
}
|
|
|
|
uint16_t VindriktningComponent::parseState() {
|
|
/**
|
|
* MSB DF 3 DF 4 LSB
|
|
* uint16_t = xxxxxxxx xxxxxxxx
|
|
*/
|
|
const uint16_t pm25 = (serialRxBuf[5] << 8) | serialRxBuf[6];
|
|
return pm25;
|
|
}
|
|
|
|
bool VindriktningComponent::isValidHeader() {
|
|
bool headerValid = serialRxBuf[0] == 0x16 && serialRxBuf[1] == 0x11 && serialRxBuf[2] == 0x0B;
|
|
if (!headerValid) {
|
|
ESP_LOGD(TAG, "Received message with invalid header");
|
|
}
|
|
return headerValid;
|
|
}
|
|
|
|
bool VindriktningComponent::isValidChecksum() {
|
|
uint8_t checksum = 0;
|
|
|
|
for (uint8_t i = 0; i < 20; i++) {
|
|
checksum += serialRxBuf[i];
|
|
}
|
|
|
|
if (checksum != 0) {
|
|
ESP_LOGD(TAG, "Received message with invalid checksum. Expected: 0. Actual: %d", checksum);
|
|
}
|
|
|
|
return checksum == 0;
|
|
}
|
|
|
|
} // namespace vindriktning
|
|
} // namespace esphome
|