aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/Makefile12
-rw-r--r--src/main.c256
-rw-r--r--src/pthread_dht11.c92
-rw-r--r--src/pthread_fan.c75
-rw-r--r--src/pthread_gprs.c90
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);
+}