sensors stuff, mqtt message docs

This commit is contained in:
Miro Zmrzli 2024-06-13 13:13:46 -07:00
parent 5a82edc423
commit 2344f6efd0
6 changed files with 230 additions and 44 deletions

80
main/SENSORDATA.md Normal file
View File

@ -0,0 +1,80 @@
# MQTT message structure
## MSG Header
Every message. Total len 18 bytes.
```mermaid
block-beta
T["<b>TIME</b><br>4 bytes<br>seconds"]:2
Tm["<b>TIME</b><br>4 bytes<br>useconds"]:2
MAC["WIFI MAC<br>6 bytes"]:3
GRP["Group id<br>4 bytes"]:2
```
# Block messages
## Radar message
Arrives every 10 seconds. Total len 49 + 18 = 67 bytes
```mermaid
block-beta
MSG_HEADER
B["0x10"]
C["14 uint16<br>motion energy"]
D["10 uint16<br>stationary energy"]
```
<br>
## Sensors message
Arrives every 10 seconds, when gas sensor data has been collected. Total len: 18 + 16 + 5 * number_data_pairs
```mermaid
block-beta
MSG_HEADER:1
B["0x11"]:1
C["Pressure<br>float"]:1
D["Temperature<br>float"]:1
E["light<br>2 bytes"]:1
F["humidity<br>float"]:1
G["Number of data pairs<br>byte"]:1
block:aa:3
H["index 1<br>byte"]
I["gas resistance 1<br>float"]
J["..."]
end
```
<br>
# Notification messages
## Pressure
Total len: 18 + 5 = 23 bytes
```mermaid
block-beta
MSG_HEADER
B["0x01"]
C["value<br>float"]
```
## Temperature
Total len: 18 + 5 = 23 bytes
```mermaid
block-beta
MSG_HEADER
B["0x02"]
C["value<br>float"]
```
## Humidity
Total len: 18 + 5 = 23 bytes
```mermaid
block-beta
MSG_HEADER
B["0x03"]
C["value<br>float"]
```
## Light
Total len: 18 + 3 = 21 bytes
```mermaid
block-beta
MSG_HEADER
B["0x04"]
C["value<br>2 bytes"]
```

View File

@ -1,12 +1,12 @@
/// © MiroZ 2024
#ifndef __SENSOR_DATA_H__
#define __SENSOR_DATA_H__
#include <stdint.h>
#pragma pack(push, 1)
struct MESSAGE_HEADER
struct MESSAGE_HEADER // 19 bytes
{
uint8_t type;
uint32_t sec;
@ -22,12 +22,38 @@ struct MESSAGE_TYPE_VAL_REASON
uint8_t reason;
};
struct RADAR
struct RADAR // 49
{
uint8_t type;
uint16_t vals[24];
};
struct GAS_HEADER // 2 bytes
{
uint8_t type;
uint8_t num_measurements;
};
struct GAS_DATA //5 bytes
{
uint8_t index;
float gas_resistance;
};
struct OTHERS
{
float pressure;
float temp;
uint16_t light;
};
struct GAS // 6 + num_gas_data * 5
{
struct GAS_HEADER header;
float humidity;
struct GAS_DATA data[0];
};
#pragma pack(pop)
#define HEADER_MESSAGE(name_) \
@ -98,14 +124,25 @@ struct RADAR
#define RADAR_MESSAGE_P(addr_) \
(addr_)->type = MESSAGE_TYPE_RADAR;
#define GAS_MESSAGE(name_, num_vals_) \
struct GAS name_; \
name_.header.type = MESSAGE_TYPE_GAS; \
name_.header.num_measurements = num_vals_;
#define GAS_MESSAGE_P(addr_, num_vals_) \
(addr_)->header.type = MESSAGE_TYPE_GAS; \
(addr_)->header.num_measurements = num_vals_;
#define MESSAGE_TYPE_HEADER 0xa5
#define MESSAGE_TYPE_PRESSURE 0x04
#define MESSAGE_TYPE_RADAR 0x37
#define MESSAGE_TYPE_LIGHT 0x06
#define MESSAGE_TYPE_TEMP 0x07
#define MESSAGE_TYPE_HUMIDITY 0x08
#define MESSAGE_TYPE_GAS_IX 0x09
#define MESSAGE_TYPE_GAS_VAL 0x0a
#define MESSAGE_TYPE_GAS_IX 0x09 // deprecated
#define MESSAGE_TYPE_GAS_VAL 0x0a // deprecated
#define MESSAGE_TYPE_GAS 0x0b
#define MESSAGE_TYPE_SENSOR_BLOCK 0x0c
void createHeader(struct MESSAGE_HEADER * header);

View File

@ -35,12 +35,16 @@ bool Bme68x::init()
return m_operational;
}
void Bme68x::read(struct BME_DATA * data)
/// @brief
/// @param data
/// @return returns true when index 9 is read
bool Bme68x::read(struct BME_DATA * data)
{
MyLibs::bme68xData bdata;
uint8_t left;
bool ret_val = false;
if(m_sensor->fetchData() > 0)
{
do
@ -50,13 +54,19 @@ void Bme68x::read(struct BME_DATA * data)
if (bdata.status == NEW_GAS_MEAS)
{
int ix = _min(bdata.gas_index, 9);
ESP_LOGW(TAG, "index: %d", ix);
data->measurement_bitmask |= (1 << ix);
if(ix == 0)
data->humidity = bdata.humidity;
else if(ix == 9)
ret_val = true;
data->measurement[ix].resistance = bdata.gas_resistance;
data->measurement[ix].temp = bdata.temperature;
}
} while(left > 0);
}
return ret_val;
}

View File

@ -9,13 +9,13 @@
struct GAS_MEASUREMENT
{
float temp;
float resistance;
};
struct BME_DATA
{
float humidity;
uint16_t measurement_bitmask;
struct GAS_MEASUREMENT measurement[10];
};
@ -30,7 +30,7 @@ public:
Bme68x(TwoWire & bus);
bool init();
void read(struct BME_DATA * data);
bool read(struct BME_DATA * data);
};
#endif

View File

@ -51,51 +51,105 @@ void SensorService::start()
pinMode(LIGHT_SENSOR_PIN, INPUT);
}
void SensorService::postBme68xData(float pressure, float temp)
{
struct msg
{
struct MESSAGE_HEADER header;
struct OTHERS others;
struct GAS gas;
};
uint8_t msg_buffer[100];
struct msg *data_to_send = (struct msg *)msg_buffer;
HEADER_MESSAGE_P(&data_to_send->header);
GAS_MESSAGE_P(&data_to_send->gas, 0);
data_to_send->others.light = m_light_value;
data_to_send->others.pressure = pressure;
data_to_send->others.temp = temp;
int num_total = 0;
struct GAS_DATA * p = data_to_send->gas.data;
for(int n = 0; n < 10; n++)
{
if(m_bme_data.measurement_bitmask & (1 << n))
{
p[num_total].gas_resistance = m_bme_data.measurement[n].resistance;
p[num_total++].index = n;
}
}
data_to_send->gas.header.num_measurements = num_total;
data_to_send->gas.humidity = m_bme_data.humidity;
m_app_if.getBuffer()->putBlock((uint8_t*)&data_to_send, sizeof(*data_to_send) + num_total * sizeof(struct GAS_DATA));
// clear the blackboard
memset(&m_bme_data, 0, sizeof(m_bme_data));
}
/// @brief Actual light value is minimum in 2s window
/// @param light_value
void SensorService::processLight(int light_value)
{
static uint16_t min_light_val = 0xffff;
static int last_light_val = -1;
static uint64_t last_time = esp_timer_get_time();
uint64_t now;
// handle light sensor
if(light_value < min_light_val)
min_light_val = light_value;
now = esp_timer_get_time();
if(now - last_time >= 2000000) // >= 2s
{
ESP_LOGI(TAG, "light: %d", min_light_val);
if(last_light_val >= 0)
{
if(abs(min_light_val - last_light_val) > 4096*5/100)
{
ESP_LOGI(TAG, "light tripped");
struct msg
{
struct MESSAGE_HEADER header;
struct MESSAGE_TYPE_VAL_REASON light;
};
struct msg m;
HEADER_MESSAGE_P(&m.header);
LIGHT_MESSAGE_P(&m.light, min_light_val, 1);
m_app_if.getBuffer()->putBlock((uint8_t*)&m, sizeof(m));
}
}
last_light_val = min_light_val;
m_light_value = min_light_val;
min_light_val = 0xffff;
last_time = now;
}
}
// handles pressure and voc sensor
void SensorService::run_i2c_1()
{
uint16_t light_val = 0xffff;
int last_light_val = -1;
uint64_t last_time = esp_timer_get_time(), now;
while(true)
{
m_bmp280->read(m_bmp_data.temp, m_bmp_data.pressure);
m_bme68x->read(&m_bme_data);
bool bme_cycle_finished = m_bme68x->read(&m_bme_data);
uint16_t read_light_val = analogRead(LIGHT_SENSOR_PIN);
// handle light sensor
if(read_light_val < light_val)
light_val = read_light_val;
now = esp_timer_get_time();
if(now - last_time >= 2000000) // >= 2s
if(bme_cycle_finished)
{
ESP_LOGI(TAG, "light: %d", light_val);
if(last_light_val >= 0)
{
if(abs(light_val - last_light_val) > 4096*5/100)
{
ESP_LOGI(TAG, "light tripped");
struct msg
{
struct MESSAGE_HEADER header;
struct MESSAGE_TYPE_VAL_REASON light;
};
struct msg m;
HEADER_MESSAGE_P(&m.header);
LIGHT_MESSAGE_P(&m.light, light_val, 1);
m_app_if.getBuffer()->putBlock((uint8_t*)&m, sizeof(m));
}
}
last_light_val = light_val;
light_val = 0xffff;
last_time = now;
postBme68xData(m_bmp_data.pressure, m_bmp_data.temp);
}
processLight(read_light_val);
delay(10);
}
}

View File

@ -28,6 +28,11 @@ protected:
AppIF & m_app_if;
void postBme68xData(float pressure, float temp);
void processLight(int light_value);
void processHumidity(float humidity);
uint16_t m_light_value = 0;
public:
SensorService(AppIF & app_if);
void start();