#include "hc-12.h" #include "mysql.h" pthread_mutex_t mutex; void *pull_data_mysql(void *p) { char sql_insert[1024] = { 0 }; time_t current_time; struct tm *time_info; char timeString[20]; static int r = 0; Thread *args = (Thread *) p; if (args->data->co >= 0 && args->data->co2 >= 0 && args->data->ch4_ >= 0) { time(¤t_time); // 获取当前时间 time_info = localtime(¤t_time); // 将时间转换为本地时间 strftime(timeString, sizeof(timeString), "%Y-%m-%d %H:%M:%S", time_info); // 格式化时间字符串 sprintf(sql_insert, "INSERT INTO %s (TIME, CO, CO2, CH4, TEMPERATURE, RP2040_TEMPERATURE) VALUES ('%s', '%.0fppm', '%.0fppm', '%.0fppm', '%.3f°C', '%.02f°C');", args->conf->MYSQL_TABLES, timeString, args->data->co, args->data->co2, args->data->ch4_, args->data->ds18b20, args->data->rp2040); printf("%s\n", sql_insert); r = _mysql(sql_insert, args->conf->MYSQL_HOST, args->conf->MYSQL_PORT_, args->conf->MYSQL_USRT, args->conf->MYSQL_PASSWORD, args->conf->MYSQL_DB, args->conf->MYSQL_TABLES); if (r == -1) { perror("_mysql"); } } return NULL; } int send_mail(char *mail, const char *string, CONF *conf, DATA *data) { static char *buff; const char *subject = "厨房危险(火灾)报警!!!"; buff = (char *)alloca(BUFFER * 10); if (buff == NULL) perror("out of memory."); sprintf(buff, MAIL, mail, subject, string); printf("%s\n", buff); system(buff); return 0; } void *createSharedMemory(int key, size_t size) { static int shm_id; static void *shared_memory; shm_id = shmget(key, size, IPC_CREAT | 0666); if (shm_id == -1) { perror("shmget"); exit(1); } shared_memory = shmat(shm_id, NULL, 0); if (shared_memory == (void *)-1) { perror("shmat"); exit(1); } return shared_memory; } void detachAndDeleteSharedMemory(int key, void *shared_memory) { static int shm_id; if (shmdt(shared_memory) == -1) { perror("shmdt"); exit(1); } shm_id = shmget(key, 0, 0); if (shmctl(shm_id, IPC_RMID, NULL) == -1) { perror("shmctl"); exit(1); } } int loop(int fd, CONF *conf, DATA *DATA) { static char receivedString[BUFFER]; static int index = 0; static int timing = 0; DATA->ds18b20_shm = (int *)createSharedMemory(1, sizeof(int)); DATA->co_shm = (int *)createSharedMemory(2, sizeof(int)); DATA->co2_shm = (int *)createSharedMemory(3, sizeof(int)); *DATA->ds18b20_shm = 0; *DATA->co_shm = 0; *DATA->co2_shm = 0; pid_t pid = fork(); if (pid < 0) { perror("fork"); exit(1); } if (pid == 0) // 子进程 { int conut = 0; while (1) { pthread_mutex_lock(&mutex); // 加锁 if (conut >= DATA->_time) { *DATA->ds18b20_shm = 1; *DATA->co_shm = 1; *DATA->co2_shm = 1; conut = 0; } pthread_mutex_unlock(&mutex); // 解锁 conut++; sleep(1); } } else // 父进程 { while (1) { if (serialDataAvail(fd)) { // 串口有数据可读 char data = serialGetchar(fd); if (data != '\n') { // 如果接收到的不是回车符,则添加到接收字符串中 receivedString[index] = data; index++; // 检查是否超出数组长度,如果超出则重置索引 if (index >= BUFFER) { index = 0; } } else { // 如果接收到回车符,则打印接收到的字符串,并清空接收字符串和索引 receivedString[index] = '\0'; // 添加字符串结束符 if (index > 0) { // RP2040 if (strstr(receivedString, "Onboard")) { if (2 == (sscanf(receivedString, "Onboard temperature %f°C %f°F\n", &(DATA->rp2040), &(DATA->rp2040_f)))) { DATA->rp2040_num++; printf("Onboard temperature %.02f°C %.02f°F\n", DATA->rp2040, DATA->rp2040_f); } } // DS18B20 if (strstr(receivedString, "Temperature")) { if (1 == (sscanf(receivedString, "Temperature: %f°C\n", &DATA->ds18b20))) { printf("Temperature: %.3f°C\n", DATA->ds18b20); if (DATA->ds18b20 >= atoi(conf->temperature)) { DATA->ds18b20_num++; printf("请注意室内温度%.3f°C超过%d次!\n", DATA->ds18b20, DATA->ds18b20_num); if (DATA->ds18b20_num >= 3) { // 第一次发送 if (DATA->ds18b20_1st == 1) { DATA->ds18b20_1st = 0; send_mail(conf->mail, receivedString, conf, DATA); } // 如果浓度持续一段时间, (降低发送频率, 若干秒后再次发送) pthread_mutex_lock(&mutex); // 加锁 if (*DATA->ds18b20_shm == 1) { send_mail(conf->mail, receivedString, conf, DATA); *DATA->ds18b20_shm = 0; } pthread_mutex_unlock(&mutex); // 解锁 DATA->ds18b20_num = 0; } } } } // CH4 if (strstr(receivedString, "CH4 Concentration")) { if (1 == (sscanf(receivedString, "CH4 Concentration: %f\n", &DATA->ch4_))) { printf("CH4 Concentration: %.0F ppm\n", DATA->ch4_); } } // CO if (strstr(receivedString, "CO")) { if (1 == (sscanf(receivedString, "CO Concentration: %f ppm", &DATA->co))) { printf("CO Concentration: %.2f ppm\n", DATA->co); if (DATA->co >= atoi(conf->co)) { DATA->co_num++; printf("请注意室内CO浓度%.3f°C超过%d次!\n", DATA->co, DATA->co_num); if (DATA->co_num >= 3) { if (DATA->co_1st == 1) { DATA->co_1st = 0; send_mail(conf->mail, receivedString, conf, DATA); } pthread_mutex_lock(&mutex); if (*DATA->co_shm == 1) { send_mail(conf->mail, receivedString, conf, DATA); *DATA->co_shm = 0; } pthread_mutex_unlock(&mutex); DATA->co_num = 0; } } } } // CO2 if (strstr(receivedString, "CO2")) { if (1 == (sscanf(receivedString, "CO2 Concentration: %f ppm", &DATA->co2))) { printf("CO2 Concentration: %.2f ppm\n", DATA->co2); if (DATA->co2 >= atoi(conf->co2)) { DATA->co2_num++; printf("请注意室内CO2浓度%.3f°C超过%d次!\n", DATA->co2, DATA->co2_num); if (DATA->co2_num >= 3) { if (DATA->co2_1st == 1) { DATA->co2_1st = 0; send_mail(conf->mail, receivedString, conf, DATA); } pthread_mutex_lock(&mutex); if (*DATA->co2_shm == 1) { send_mail(conf->mail, receivedString, conf, DATA); *DATA->co2_shm = 0; } pthread_mutex_unlock(&mutex); DATA->co2_num = 0; } } } printf("\n"); } } receivedString[0] = '\0'; index = 0; } } // 上传传感器数据到Mysql数据库 timing++; if (0 == strcasecmp(conf->MYSQL_ON, "on")) { if (timing >= (atoi(conf->PUSH_MYSQL_DATA_TIME) * 100)) { Thread args = { conf, DATA }; pthread_t tid; // 创建线程,并传递包含两个结构体的参数 if (pthread_create(&tid, NULL, pull_data_mysql, &args) != 0) { perror("pthread_create"); return 1; } // 等待线程结束 pthread_join(tid, NULL); timing = 0; } } delay(10); } } waitpid(pid, NULL, 0); // 断开共享内存连接 detachAndDeleteSharedMemory(1, DATA->ds18b20_shm); detachAndDeleteSharedMemory(2, DATA->co_shm); detachAndDeleteSharedMemory(3, DATA->co2_shm); return 0; } int redirect_stdout_to_file(int fd, const char *filename) { fd = open(filename, O_WRONLY | O_CREAT | O_APPEND, 0644); if (fd == -1) { perror("open"); return 1; } if (dup2(fd, STDOUT_FILENO) == -1) { perror("dup2"); return 1; } return 0; } int main() { int logfd = -1; int fd = -1; if (nice(-20) == -1) { perror("nice"); return 1; } if (0 != daemon(1, 1)) { perror("daemon"); } if ((fd = serialOpen("/dev/serial0", 9600)) < 0) { printf("Unable to open device\n"); return 1; } else { printf("Serial port opened\n"); } CONF *conf = (struct CONF *)malloc(sizeof(struct CONF)); memset(conf, 0, sizeof(struct CONF)); conf->mail = strdup(read_conf("hc-12.conf", "global", "MAIL")); conf->temperature = strdup(read_conf("hc-12.conf", "global", "TEMPERATURE")); conf->co = strdup(read_conf("hc-12.conf", "global", "CO")); conf->co2 = strdup(read_conf("hc-12.conf", "global", "CO2")); conf->MYSQL_ON = strdup(read_conf("hc-12.conf", "global", "MYSQL")); if (0 == strcasecmp(conf->MYSQL_ON, "on")) { conf->PUSH_MYSQL_DATA_TIME = strdup(read_conf("hc-12.conf", "global", "PUSH_MYSQL_DATA_TIME")); conf->MYSQL_HOST = strdup(read_conf("hc-12.conf", "global", "MYSQL_HOST")); conf->MYSQL_PORT_ = strdup(read_conf("hc-12.conf", "global", "MYSQL_PORT")); conf->MYSQL_USRT = strdup(read_conf("hc-12.conf", "global", "MYSQL_USRT")); conf->MYSQL_PASSWORD = strdup(read_conf("hc-12.conf", "global", "MYSQL_PASSWORD")); conf->MYSQL_DB = strdup(read_conf("hc-12.conf", "global", "MYSQL_DB")); conf->MYSQL_TABLES = strdup(read_conf("hc-12.conf", "global", "MYSQL_TABLES")); } DATA *data = (struct DATA *)malloc(sizeof(struct DATA)); memset(data, 0, sizeof(struct DATA)); data->ds18b20 = 0; data->ch4 = 0; data->rp2040 = 0; data->rp2040_f = 0; data->co = 0; data->co2 = 0; data->rp2040_num = 0; data->ch4_num = 0; data->ds18b20_num = 0; data->co_num = 0; data->co2_num = 0; data->ds18b20_1st = 1; data->ch4_1st = 1; data->co_1st = 1; data->co2_1st = 1; data->_time = 180; redirect_stdout_to_file(logfd, "hc-12.log"); pthread_mutex_init(&mutex, NULL); // 初始化互斥锁 loop(fd, conf, data); pthread_mutex_destroy(&mutex); // 销毁互斥锁 free(conf->mail); free(conf->temperature); free(conf->co); free(conf->co2); free(conf->PUSH_MYSQL_DATA_TIME); free(conf->MYSQL_HOST); free(conf->MYSQL_PORT_); free(conf->MYSQL_USRT); free(conf->MYSQL_PASSWORD); free(conf->MYSQL_DB); free(conf->MYSQL_TABLES); free(conf); free(data); close(fd); close(logfd); return 0; }