8static const char *
const TAG =
"senseair";
9static const uint8_t SENSEAIR_REQUEST_LENGTH = 8;
10static const uint8_t SENSEAIR_PPM_STATUS_RESPONSE_LENGTH = 13;
11static const uint8_t SENSEAIR_ABC_PERIOD_RESPONSE_LENGTH = 7;
12static const uint8_t SENSEAIR_CAL_RESULT_RESPONSE_LENGTH = 7;
13static const uint8_t SENSEAIR_COMMAND_GET_PPM_STATUS[] = {0xFE, 0x04, 0x00, 0x00, 0x00, 0x04, 0xE5, 0xC6};
14static const uint8_t SENSEAIR_COMMAND_CLEAR_ACK_REGISTER[] = {0xFE, 0x06, 0x00, 0x00, 0x00, 0x00, 0x9D, 0xC5};
15static const uint8_t SENSEAIR_COMMAND_BACKGROUND_CAL[] = {0xFE, 0x06, 0x00, 0x01, 0x7C, 0x06, 0x6C, 0xC7};
16static const uint8_t SENSEAIR_COMMAND_BACKGROUND_CAL_RESULT[] = {0xFE, 0x03, 0x00, 0x00, 0x00, 0x01, 0x90, 0x05};
17static const uint8_t SENSEAIR_COMMAND_ABC_ENABLE[] = {0xFE, 0x06, 0x00, 0x1F, 0x00, 0xB4, 0xAC, 0x74};
18static const uint8_t SENSEAIR_COMMAND_ABC_DISABLE[] = {0xFE, 0x06, 0x00, 0x1F, 0x00, 0x00, 0xAC, 0x03};
19static const uint8_t SENSEAIR_COMMAND_ABC_GET_PERIOD[] = {0xFE, 0x03, 0x00, 0x1F, 0x00, 0x01, 0xA1, 0xC3};
22 uint8_t response[SENSEAIR_PPM_STATUS_RESPONSE_LENGTH];
23 if (!this->
senseair_write_command_(SENSEAIR_COMMAND_GET_PPM_STATUS, response, SENSEAIR_PPM_STATUS_RESPONSE_LENGTH)) {
24 ESP_LOGW(TAG,
"Reading data from SenseAir failed!");
29 if (response[0] != 0xFE || response[1] != 0x04) {
30 ESP_LOGW(TAG,
"Invalid preamble from SenseAir! %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x",
31 response[0], response[1], response[2], response[3], response[4], response[5], response[6], response[7],
32 response[8], response[9], response[10], response[11], response[12]);
38 ESP_LOGV(TAG,
" ... %02x", b);
40 ESP_LOGV(TAG,
" ... nothing read");
46 uint16_t calc_checksum =
crc16(response, 11);
47 uint16_t resp_checksum = (uint16_t(response[12]) << 8) | response[11];
48 if (resp_checksum != calc_checksum) {
49 ESP_LOGW(TAG,
"SenseAir checksum doesn't match: 0x%02X!=0x%02X", resp_checksum, calc_checksum);
55 const uint8_t
length = response[2];
59 ESP_LOGD(TAG,
"SenseAir Received CO₂=%uppm Status=0x%02X", ppm,
status);
61 ESP_LOGD(TAG,
"Discarding 0 ppm reading with out-of-range status.");
70 ESP_LOGD(TAG,
"SenseAir Starting background calibration");
71 uint8_t command_length =
sizeof(SENSEAIR_COMMAND_CLEAR_ACK_REGISTER) /
sizeof(SENSEAIR_COMMAND_CLEAR_ACK_REGISTER[0]);
72 uint8_t response[command_length];
78 ESP_LOGD(TAG,
"SenseAir Requesting background calibration result");
79 uint8_t response[SENSEAIR_CAL_RESULT_RESPONSE_LENGTH];
81 SENSEAIR_CAL_RESULT_RESPONSE_LENGTH)) {
82 ESP_LOGE(TAG,
"Requesting background calibration result from SenseAir failed!");
86 if (response[0] != 0xFE || response[1] != 0x03) {
87 ESP_LOGE(TAG,
"Invalid reply from SenseAir! %02x%02x%02x %02x%02x %02x%02x", response[0], response[1], response[2],
88 response[3], response[4], response[5], response[6]);
93 ESP_LOGI(TAG,
"SenseAir Result=%s (%02x%02x%02x %02x%02x %02x%02x)", (response[4] & 0b100000) != 0 ?
"OK" :
"NOT_OK",
94 response[0], response[1], response[2], response[3], response[4], response[5], response[6]);
99 ESP_LOGD(TAG,
"SenseAir Enabling automatic baseline calibration");
100 uint8_t command_length =
sizeof(SENSEAIR_COMMAND_ABC_ENABLE) /
sizeof(SENSEAIR_COMMAND_ABC_ENABLE[0]);
101 uint8_t response[command_length];
107 ESP_LOGD(TAG,
"SenseAir Disabling automatic baseline calibration");
108 uint8_t command_length =
sizeof(SENSEAIR_COMMAND_ABC_DISABLE) /
sizeof(SENSEAIR_COMMAND_ABC_DISABLE[0]);
109 uint8_t response[command_length];
114 ESP_LOGD(TAG,
"SenseAir Requesting ABC period");
115 uint8_t response[SENSEAIR_ABC_PERIOD_RESPONSE_LENGTH];
116 if (!this->
senseair_write_command_(SENSEAIR_COMMAND_ABC_GET_PERIOD, response, SENSEAIR_ABC_PERIOD_RESPONSE_LENGTH)) {
117 ESP_LOGE(TAG,
"Requesting ABC period from SenseAir failed!");
121 if (response[0] != 0xFE || response[1] != 0x03) {
122 ESP_LOGE(TAG,
"Invalid reply from SenseAir! %02x%02x%02x %02x%02x %02x%02x", response[0], response[1], response[2],
123 response[3], response[4], response[5], response[6]);
127 const uint16_t hours = (uint16_t(response[3]) << 8) | response[4];
128 ESP_LOGD(TAG,
"SenseAir Read ABC Period: %u hours", hours);
133 if (response ==
nullptr) {
140 this->
write_array(command, SENSEAIR_REQUEST_LENGTH);
142 bool ret = this->
read_array(response, response_length);
148 ESP_LOGCONFIG(TAG,
"SenseAir:");
void check_uart_settings(uint32_t baud_rate, uint8_t stop_bits=1, UARTParityOptions parity=UART_CONFIG_PARITY_NONE, uint8_t data_bits=8)
Check that the configuration of the UART bus matches the provided values and otherwise print a warnin...
uint16_t crc16(const uint8_t *data, uint16_t len, uint16_t crc, uint16_t reverse_poly, bool refin, bool refout)
Calculate a CRC-16 checksum of data with size len.