1#include "../include/sensor/sensor.h"
17#define SENSOR_PLUGIN_EXPORT __declspec(dllexport)
19#define SENSOR_PLUGIN_EXPORT
22static void fill_timestamp(
char *buf,
size_t len) {
23 time_t now = time(NULL);
24 const struct tm *ptm = localtime(&now);
26 snprintf(buf, len,
"1970-01-01 00:00:00");
29 if (strftime(buf, len,
"%Y-%m-%d %H:%M:%S", ptm) == 0) {
30 snprintf(buf, len,
"1970-01-01 00:00:00");
34static int pms5003_init(
void) {
36 printf(
"PMS5003 plugin initialized (real UART on Linux/macOS if available; fallback mock).\n");
38 printf(
"PMS5003 plugin initialized (mock on Windows).\n");
44static int open_serial_9600(
const char *device) {
45 int fd = open(device, O_RDWR | O_NOCTTY | O_SYNC);
49 memset(&tty, 0,
sizeof(tty));
50 if (tcgetattr(fd, &tty) != 0) {
54 cfsetospeed(&tty, B9600);
55 cfsetispeed(&tty, B9600);
56 tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8;
57 tty.c_iflag &= ~(IGNBRK | IXON | IXOFF | IXANY);
62 tty.c_cflag |= (CLOCAL | CREAD);
63 tty.c_cflag &= ~(PARENB | PARODD | CSTOPB | CRTSCTS);
64 if (tcsetattr(fd, TCSANOW, &tty) != 0) {
68 tcflush(fd, TCIOFLUSH);
76int pms5003_parse_frame(
const unsigned char frame[32],
int *pm25,
int *pm10) {
77 if (!frame || !pm25 || !pm10)
81 for (
int k = 0; k < 30; k++)
83 unsigned int chk = ((
unsigned int)frame[30] << 8) | frame[31];
84 if ((sum & 0xFFFF) != chk)
87 *pm25 = ((int)frame[12] << 8) | frame[13];
88 *pm10 = ((int)frame[14] << 8) | frame[15];
92static int read_frame(
int fd,
unsigned char *buf,
size_t want) {
95 ssize_t n = read(fd, buf + got, want - got);
103static int read_pms5003(
float *pm25,
float *pm10) {
104 const char *dev = getenv(
"PMS5003_DEVICE");
106 dev =
"/dev/ttyUSB0";
107 int fd = open_serial_9600(dev);
113 for (
int i = 0; i < 2048; i++) {
114 if (read(fd, &b, 1) != 1)
116 if (!found && b == 0x42) {
120 if (found && b == 0x4d) {
121 unsigned char frame[32];
124 if (read_frame(fd, frame + 2, 30) != 0) {
128 int val_pm25 = 0, val_pm10 = 0;
129 if (pms5003_parse_frame(frame, &val_pm25, &val_pm10) != 0) {
133 *pm25 = (float)val_pm25;
134 *pm10 = (float)val_pm10;
148 memset(out, 0,
sizeof(*out));
150 snprintf(out->
model,
sizeof(out->
model),
"PMS5003");
154 out->pm25 = (float)(rand() % 5000) / 100.0f;
155 out->pm10 = out->pm25 + (float)(rand() % 7000) / 100.0f;
157 float real_pm25 = 0.0f, real_pm10 = 0.0f;
158 if (read_pms5003(&real_pm25, &real_pm10) == 0) {
159 out->pm25 = real_pm25;
160 out->pm10 = real_pm10;
170static int pms5003_shutdown(
void) {
171 printf(
"PMS5003 plugin shutdown.\n");
178 .plugin_version =
"1.0.0",
179 .description =
"Simulated PMS5003 particulate readings.",
181 .init = pms5003_init,
182 .read_sample = pms5003_read_sample,
183 .shutdown = pms5003_shutdown,
One air quality reading: pollutant values plus sensor/timestamp metadata.
char timestamp[32]
Reading timestamp, formatted "%Y-%m-%d %H:%M:%S".
char model[64]
Sensor model name, e.g.
int sensor_id
Numeric sensor identifier, matches SensorPlugin::sensor_id.
Runtime contract every sensor plugin (.so/.dylib/.dll) must implement.
int api_version
Must equal SENSOR_PLUGIN_API_VERSION at build time.