diff options
-rw-r--r-- | src/Makefile | 12 | ||||
-rw-r--r-- | src/main.c | 256 | ||||
-rw-r--r-- | src/pthread_dht11.c | 92 | ||||
-rw-r--r-- | src/pthread_fan.c | 75 | ||||
-rw-r--r-- | src/pthread_gprs.c | 90 |
5 files changed, 525 insertions, 0 deletions
diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..7526926 --- /dev/null +++ b/src/Makefile @@ -0,0 +1,12 @@ +CFLAGS += -Wall -pthread -I../include/ -DDEBUG_LOG -g + +LDFLAGS = -lcomfig -L../lib/ + +SRCS= main.c \ + pthread_dht11.c \ + pthread_fan.c \ + pthread_gprs.c + +demo_start: $(SRCS) + $(CC) $(CFLAGS) $(SRCS) -o $@ $(LDFLAGS) + mv ./demo_start ../build diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..82c5d0d --- /dev/null +++ b/src/main.c @@ -0,0 +1,256 @@ +/* + * File Name: main.c + * Workflow: prepare serial port, create MQ, SHM, child threads, + * register SIGINT to shutdown demo, recycle IPC waste. + * Return Value: 0, normal exit. -1, erroneous exit. + */ + +/* Header files */ +#include <errno.h> +#include <pthread.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/ipc.h> +#include <sys/msg.h> +#include <sys/shm.h> +#include <sys/stat.h> +#include <sys/types.h> + +#include "debug.h" +#include "proto.h" +#include "uart_api.h" + +/* external threads */ +extern void *pthread_gprs(void *args); +extern void *pthread_fan(void *args); +extern void *pthread_dht11(void *args); + +/* global variables*/ +pthread_t id_dht11, id_fan, id_gprs; + +pthread_mutex_t mutex_zigbee_coordinator, mutex_gprs; + +volatile sig_atomic_t should_exit = 0; + +/* functions */ +static void cleanThreadsHandler(int signum); + +/* main */ +int main(void) { + int *p_coordinator_fd = malloc(sizeof(int)); + int retVal; + int *p_gprs_fd = malloc(sizeof(int)); + key_t *p_shm_key = malloc(sizeof(key_t)); + key_t *p_msg_key = malloc(sizeof(key_t)); + int *p_shm_id = malloc(sizeof(int)); + int *p_msg_id = malloc(sizeof(int)); + ARG_STRUCT *p_dht11_resource_struct = malloc(sizeof(ARG_STRUCT)); + ARG_STRUCT *p_fan_resource_struct = malloc(sizeof(ARG_STRUCT)); + ARG_STRUCT *p_gprs_resource_struct = malloc(sizeof(ARG_STRUCT)); + + // prepare serial communication + if ((*p_coordinator_fd = open_port("/dev/ttyUSB0")) == -1) { + fprintf(stderr, "[%s:%d] open_port: %s.\n", __FUNCTION__, __LINE__, + strerror(errno)); + exit(-1); + } + DebugLog("[DEBUG-INFO %s:%d]: Get zigbee coordinator fd: %d.\n", __FUNCTION__, + __LINE__, *p_coordinator_fd); + + if ((retVal = set_comfig(*p_coordinator_fd, 115200)) != 0) { + fprintf(stderr, "[%s:%d] set_comfig: %s.\n", __FUNCTION__, __LINE__, + strerror(errno)); + exit(-1); + } + DebugLog("[DEBUG-INFO %s:%d]: Set Zigbee coordinator serial config with " + "return value: %d.\n", + __FUNCTION__, __LINE__, retVal); + + if ((*p_gprs_fd = open_port("/dev/ttyUSB1")) == -1) { + fprintf(stderr, "[%s:%d] open_port: %s.\n", __FUNCTION__, __LINE__, + strerror(errno)); + exit(-1); + } + DebugLog("[DEBUG-INFO %s:%d]: Get GPRS fd : %d.\n", __FUNCTION__, __LINE__, + *p_gprs_fd); + + if ((retVal = set_comfig(*p_gprs_fd, 9600)) != 0) { + fprintf(stderr, "[%s:%d] set_comfig: %s.\n", __FUNCTION__, __LINE__, + strerror(errno)); + exit(-1); + } + DebugLog( + "[DEBUG-INFO %s:%d]: Set GPRS serial config with return value: %d.\n", + __FUNCTION__, __LINE__, retVal); + + // prepare IPC + if ((*p_shm_key = ftok("/usr/bin/boa", 'm')) == -1) { + fprintf(stderr, "[%s:%d] ftok: %s.\n", __FUNCTION__, __LINE__, + strerror(errno)); + exit(-1); + } + DebugLog("[DEBUG-INFO %s:%d]: Generate shared memory key : %d.\n", + __FUNCTION__, __LINE__, *p_shm_key); + + if ((*p_msg_key = ftok("/usr/bin/boa", 'q')) == -1) { + fprintf(stderr, "[%s:%d] ftok: %s.\n", __FUNCTION__, __LINE__, + strerror(errno)); + exit(-1); + } + DebugLog("[DEBUG-INFO %s:%d]: Generate message queue key: %d.\n", + __FUNCTION__, __LINE__, *p_msg_key); + + if ((*p_shm_id = shmget(*p_shm_key, sizeof(SHM_STRUCT), + IPC_CREAT | IPC_EXCL | 0600)) == -1) { + fprintf(stderr, "[%s:%d] shmget: %s.\n", __FUNCTION__, __LINE__, + strerror(errno)); + exit(-1); + } + DebugLog("[DEBUG-INFO %s:%d]: Generate shared memory id: %d.\n", __FUNCTION__, + __LINE__, *p_shm_id); + + if ((*p_msg_id = msgget(*p_msg_key, IPC_CREAT | IPC_EXCL | 0600)) == -1) { + fprintf(stderr, "[%s:%d] msgget: %s", __FUNCTION__, __LINE__, + strerror(errno)); + exit(-1); + } + DebugLog("[DEBUG-INFO %s:%d]: Generate message queue id: %d.\n", __FUNCTION__, + __LINE__, *p_msg_id); + + // register SIGINT to cleanThreadsHandler function + struct sigaction sa_struct; + sa_struct.sa_handler = cleanThreadsHandler; + sa_struct.sa_flags = 0; + + // except SIGINT all signals are blocked + sigfillset(&sa_struct.sa_mask); + sigdelset(&sa_struct.sa_mask, SIGINT); + + if ((retVal = sigaction(SIGINT, &sa_struct, NULL)) == -1) { + fprintf(stderr, "[%s:%d] sigaction: %s.\n", __FUNCTION__, __LINE__, + strerror(errno)); + exit(-1); + } + DebugLog("[DEBUG-INFO %s:%d]: sigaction with return value: %d.\n", + __FUNCTION__, __LINE__, retVal); + + // prepare mutex + if ((retVal = pthread_mutex_init(&mutex_zigbee_coordinator, NULL)) != 0) { + fprintf(stderr, "[%s:%d] pthread_mutex_init: %s.\n", __FUNCTION__, __LINE__, + strerror(errno)); + exit(-1); + } + + if ((retVal = pthread_mutex_init(&mutex_gprs, NULL)) != 0) { + fprintf(stderr, "[%s:%d] pthread_mutex_init: %s.\n", __FUNCTION__, __LINE__, + strerror(errno)); + exit(-1); + } + + // create child threads + memset(p_dht11_resource_struct, '\0', sizeof(ARG_STRUCT)); + + p_dht11_resource_struct->rw_fd = *p_coordinator_fd; + DebugLog( + "[DEBUG-INFO %s:%d]: Pass to child thread dht11 read/write fd: %d.\n", + __FUNCTION__, __LINE__, p_dht11_resource_struct->rw_fd); + + p_dht11_resource_struct->shm_id = *p_shm_id; + DebugLog( + "[DEBUG-INFO %s:%d]: Pass to child thread dht11 shared memory id: %d.\n", + __FUNCTION__, __LINE__, p_dht11_resource_struct->shm_id); + + if ((retVal = pthread_create(&id_dht11, NULL, pthread_dht11, + p_dht11_resource_struct)) != 0) { + fprintf(stderr, "[%s:%d] pthread_create: %s", __FUNCTION__, __LINE__, + strerror(errno)); + exit(-1); + } + DebugLog("[DEBUG-INFO %s:%d]: Create child thread pthread_dht11 with return " + "value: %d.\n", + __FUNCTION__, __LINE__, retVal); + + memset(p_fan_resource_struct, '\0', sizeof(ARG_STRUCT)); + + p_fan_resource_struct->rw_fd = *p_coordinator_fd; + DebugLog( + "[DEBUG-INFO %s:%d]: Pass to child thread pthread_fan read/write fd: " + "%d.\n", + __FUNCTION__, __LINE__, p_fan_resource_struct->rw_fd); + + p_fan_resource_struct->mq_id = *p_msg_id; + DebugLog( + "[DEBUG-INFO %s:%d]: Pass to child thread pthread_fan message queue id: " + "%d.\n", + __FUNCTION__, __LINE__, p_fan_resource_struct->mq_id); + + if ((retVal = pthread_create(&id_fan, NULL, pthread_fan, + p_fan_resource_struct)) != 0) { + fprintf(stderr, "[%s:%d] pthread_create: %s", __FUNCTION__, __LINE__, + strerror(errno)); + exit(-1); + } + DebugLog( + "[DEBUG-INFO %s:%d]: Create child thread pthread_fan with return value: " + "%d\n", + __FUNCTION__, __LINE__, retVal); + + memset(p_gprs_resource_struct, '\0', sizeof(ARG_STRUCT)); + + p_gprs_resource_struct->rw_fd = *p_gprs_fd; + DebugLog("[DEBUG-INFO %s:%d]: Pass to child thread gprs read/write fd: %d.\n", + __FUNCTION__, __LINE__, p_gprs_resource_struct->rw_fd); + + p_gprs_resource_struct->mq_id = *p_msg_id; + DebugLog( + "[DEBUG-INFO %s:%d]: Pass to child thread gprs message queue id: %d.\n", + __FUNCTION__, __LINE__, p_gprs_resource_struct->mq_id); + + if ((retVal = pthread_create(&id_gprs, NULL, pthread_gprs, + p_gprs_resource_struct)) != 0) { + fprintf(stderr, "[%s:%d] pthread_create: %s", __FUNCTION__, __LINE__, + strerror(errno)); + exit(-1); + } + DebugLog( + "[DEBUG-INFO %s:%d]: Create child thread pthread_gprs with return value: " + "%d.\n", + __FUNCTION__, __LINE__, retVal); + + // wait for child thread return + pthread_join(id_dht11, NULL); + pthread_join(id_fan, NULL); + pthread_join(id_gprs, NULL); + + // destory mutex + pthread_mutex_destroy(&mutex_zigbee_coordinator); + pthread_mutex_destroy(&mutex_gprs); + + // remove IPC + shmctl(*p_shm_id, IPC_RMID, NULL); + msgctl(*p_msg_id, IPC_RMID, NULL); + + // close file describer + close(*p_coordinator_fd); + close(*p_gprs_fd); + + // free memory + free(p_coordinator_fd); + free(p_gprs_fd); + free(p_shm_key); + free(p_msg_key); + free(p_shm_id); + free(p_msg_id); + free(p_dht11_resource_struct); + free(p_fan_resource_struct); + free(p_gprs_resource_struct); + + return 0; +} + +static void cleanThreadsHandler(int signum) { + if (signum == SIGINT) { + should_exit = 1; + } +} diff --git a/src/pthread_dht11.c b/src/pthread_dht11.c new file mode 100644 index 0000000..d1eb518 --- /dev/null +++ b/src/pthread_dht11.c @@ -0,0 +1,92 @@ +/* + * File Name: pthread_dht11.c + * Workflow: periodically rw from coordinator, get TH data, push + * it to shared memory + * Return Value: NULL always + */ + +/* Header files */ +#include <errno.h> +#include <pthread.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <sys/ipc.h> +#include <sys/shm.h> +#include <sys/types.h> + +#include "debug.h" +#include "proto.h" + +/* external variables */ +extern pthread_mutex_t mutex_zigbee_coordinator; +extern volatile sig_atomic_t should_exit; + +/* thread start routine function*/ +void *pthread_dht11(void *args) { + ARG_STRUCT *p_resource_struct = malloc(sizeof(ARG_STRUCT)); + SHM_STRUCT *p_shm_struct = malloc(sizeof(SHM_STRUCT)); + char tmp[7]; + ssize_t rwRetCount; + + // get resources from main + p_resource_struct = args; + DebugLog("[DEBUG-INFO %s:%d]: Get read/write fd: %d.\n", __FUNCTION__, + __LINE__, p_resource_struct->rw_fd); + DebugLog("[DEBUG-INFO %s:%d]: Get shared memory ID: %d.\n", __FUNCTION__, + __LINE__, p_resource_struct->shm_id); + + // attach shared memory to local + p_shm_struct = shmat(p_resource_struct->shm_id, NULL, 0); + + // prepare buffer to get TH data + memset(tmp, '\0', 7); + + // modify shared memory + while (!should_exit) { + pthread_mutex_lock(&mutex_zigbee_coordinator); + rwRetCount = write(p_resource_struct->rw_fd, "TH", sizeof("TH")); + // write failure retry + if (rwRetCount == -1) { + pthread_mutex_unlock(&mutex_zigbee_coordinator); + continue; + } + DebugLog("[DEBUG-INFO %s:%d]: write(\"TH\") to coordinator, %zd Byte(s) " + "written.\n", + __FUNCTION__, __LINE__, rwRetCount); + + // zigbee end-device reaction time wait + sleep(3); + + rwRetCount = read(p_resource_struct->rw_fd, tmp, 7); + DebugLog("[DEBUG-INFO %s:%d]: read() from coordinator, %zd Byte(s) read.\n", + __FUNCTION__, __LINE__, rwRetCount); + + if (rwRetCount == -1) { + p_shm_struct->tempNow = 0; + DebugLog("[DEBUG-INFO %s:%d]: Nothing read, set temperature to 0.\n", + __FUNCTION__, __LINE__); + + p_shm_struct->humiNow = 0; + DebugLog("[DEBUG-INFO %s:%d]: Nothing read, set humidity to 0.\n", + __FUNCTION__, __LINE__); + } else { + p_shm_struct->tempNow = + ((int)(tmp[0] - '0')) * 10 + ((int)(tmp[1] - '0')) * 1; + DebugLog("[DEBUG-INFO %s:%d]: Current temperature: %d.\n", __FUNCTION__, + __LINE__, p_shm_struct->tempNow); + + p_shm_struct->humiNow = + ((int)(tmp[4] - '0')) * 10 + ((int)(tmp[5] - '0')) * 1; + DebugLog("[DEBUG-INFO %s:%d]: Current humidity: %d.\n", __FUNCTION__, + __LINE__, p_shm_struct->humiNow); + } + + pthread_mutex_unlock(&mutex_zigbee_coordinator); + } + + pthread_exit(NULL); +} diff --git a/src/pthread_fan.c b/src/pthread_fan.c new file mode 100644 index 0000000..55fcfb6 --- /dev/null +++ b/src/pthread_fan.c @@ -0,0 +1,75 @@ +/* + * File Name: pthread_fan.c + * Workflow: continually listen to MQ, write ON/OFF + * Return Value: NULL always + */ + +/* Header files */ +#include <errno.h> +#include <pthread.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <sys/ipc.h> +#include <sys/msg.h> +#include <sys/types.h> + +#include "debug.h" +#include "proto.h" + +/* external variables */ +extern pthread_mutex_t mutex_zigbee_coordinator; +extern volatile sig_atomic_t should_exit; + +void *pthread_fan(void *args) { + ARG_STRUCT *p_resource_struct = malloc(sizeof(ARG_STRUCT)); + MQ_STRUCT *p_mq_struct = malloc(sizeof(MQ_STRUCT)); + ssize_t rwRetCount; + + p_resource_struct = args; + + memset(p_mq_struct, '\0', sizeof(MQ_STRUCT)); + + DebugLog("[DEBUG-INFO %s:%d]: Get read/write file describer: %d.\n", + __FUNCTION__, __LINE__, p_resource_struct->rw_fd); + DebugLog("[DEBUG-INFO %s:%d]: Get message queue ID: %d.\n", __FUNCTION__, + __LINE__, p_resource_struct->mq_id); + + while (!should_exit) { + /* read from message queue */ + msgrcv(p_resource_struct->mq_id, p_mq_struct, + sizeof(MQ_STRUCT) - sizeof(long), 20L, 0); + + pthread_mutex_lock(&mutex_zigbee_coordinator); + if (p_mq_struct->tswitch == 0) { + rwRetCount = write(p_resource_struct->rw_fd, "OFF", sizeof("OFF")); + if (rwRetCount < 3) { + fprintf(stderr, "[%s:%d] Not enough bytes written.\n", __FUNCTION__, + __LINE__); + continue; + } + DebugLog( + "[DEBUG-INFO %s:%d]: Write Zigbee command, %zd Byte(s) written.\n", + __FUNCTION__, __LINE__, rwRetCount); + } else if (p_mq_struct->tswitch == 1) { + rwRetCount = write(p_resource_struct->rw_fd, "ON", sizeof("ON")); + if (rwRetCount < 2) { + fprintf(stderr, "[%s:%d] Not enough bytes written.\n", __FUNCTION__, + __LINE__); + continue; + } + DebugLog( + "[DEBUG-INFO %s:%d]: Write Zigbee command, %zd Byte(s) written.\n", + __FUNCTION__, __LINE__, rwRetCount); + } + pthread_mutex_unlock(&mutex_zigbee_coordinator); + } + + free(p_resource_struct); + free(p_mq_struct); + + pthread_exit(NULL); +} diff --git a/src/pthread_gprs.c b/src/pthread_gprs.c new file mode 100644 index 0000000..5d1994e --- /dev/null +++ b/src/pthread_gprs.c @@ -0,0 +1,90 @@ +/* + * File Name: pthread_gprs.c + * Workflow: continually listen to MQ, write AT commands + * Note: AT commands must endline with '\n' + * Return Value: NULL always + */ + +/* Header files */ +#include <errno.h> +#include <pthread.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <sys/ipc.h> +#include <sys/msg.h> +#include <sys/types.h> + +#include "debug.h" +#include "proto.h" + +/* external variables */ +extern pthread_mutex_t mutex_gprs; +extern volatile sig_atomic_t should_exit; + +void *pthread_gprs(void *args) { + ARG_STRUCT *p_resource_struct; + MQ_STRUCT *p_mq_struct = NULL; + ssize_t rwRetCount; + char staging_telnum[12] = "18851792375"; + char rw_tempbuf[32] = {'\0'}; + + p_resource_struct = args; + memset(p_mq_struct, '\0', sizeof(MQ_STRUCT)); + + DebugLog("[DEBUG-INFO %s:%d]: Get read/write file describer: %d.\n", + __FUNCTION__, __LINE__, p_resource_struct->rw_fd); + DebugLog("[DEBUG-INFO %s:%d]: Get message queue ID: %d.\n", __FUNCTION__, + __LINE__, p_resource_struct->mq_id); + + // read from message queue + while (!should_exit) { + msgrcv(p_resource_struct->mq_id, p_mq_struct, + sizeof(MQ_STRUCT) - sizeof(long), 21L, 0); + memset(rw_tempbuf, '\0', sizeof(rw_tempbuf)); + pthread_mutex_lock(&mutex_gprs); + if (p_mq_struct->tswitch == 1) { + // init module + strcpy(rw_tempbuf, "AT;\n"); + rwRetCount = + write(p_resource_struct->rw_fd, rw_tempbuf, strlen(rw_tempbuf)); + if (rwRetCount < 4) { + fprintf(stderr, "[%s:%d] Not enough bytes written.\n", __FUNCTION__, + __LINE__); + continue; + } + DebugLog("[DEBUG-INFO %s:%d]: Write AT command, %zd Byte(s) written.\n", + __FUNCTION__, __LINE__, rwRetCount); + + // alarm call + memset(rw_tempbuf, '\0', sizeof(rw_tempbuf)); + sprintf(rw_tempbuf, "ATD%s;", staging_telnum); + strcat(rw_tempbuf, "\n"); + rwRetCount = + write(p_resource_struct->rw_fd, rw_tempbuf, strlen(rw_tempbuf)); + if (rwRetCount < 16) { + fprintf(stderr, "[%s:%d] Not enough bytes written.\n", __FUNCTION__, + __LINE__); + continue; + } + DebugLog("[DEBUG-INFO %s:%d]: Write AT command, %zd Byte(s) written.\n", + __FUNCTION__, __LINE__, rwRetCount); + } else if (p_mq_struct->tswitch == 0) { + strcpy(rw_tempbuf, "ATH;\n"); + rwRetCount = + write(p_resource_struct->rw_fd, rw_tempbuf, strlen(rw_tempbuf)); + if (rwRetCount < 5) { + fprintf(stderr, "[%s:%d] Not enough bytes written.\n", __FUNCTION__, + __LINE__); + continue; + } + DebugLog("[DEBUG-INFO %s:%d]: Write AT command, %zd Byte(s) written.\n", + __FUNCTION__, __LINE__, rwRetCount); + } + pthread_mutex_unlock(&mutex_gprs); + } + pthread_exit(NULL); +} |