From 542454b6e29fd5359fca69b71e1666ad71a7b7d7 Mon Sep 17 00:00:00 2001
From: guowenxue <guowenxue@gmail.com>
Date: Wed, 30 Jan 2019 00:57:22 +0800
Subject: [PATCH] Add monitred and mqttd source code

---
 monitord/cp_logger.h  |  111 +
 monitord/cp_comport.c |  600 ++++++++++
 monitord/cp_logger.c  |  433 +++++++
 mqttd/sht20.h         |   74 +
 monitord/cp_comport.h |   67 +
 monitord/cp_proc.c    |  342 +++++
 mqttd/led.c           |   60 +
 monitord/beep.h       |   38 
 monitord/cp_proc.h    |   42 
 monitord/makefile     |   68 +
 monitord/beep.c       |  216 +++
 mqttd/makefile        |   68 +
 mqttd/sht20.c         |  439 +++++++
 mqttd/led.h           |   48 
 monitord/cp_socket.c  |  357 ++++++
 mqttd/ds18b20.c       |  105 +
 mqttd/ds18b20.h       |   19 
 monitord/monitord.c   |  186 +++
 monitord/monitord.h   |   18 
 monitord/cp_socket.h  |   65 +
 mqttd/main.c          |   92 +
 21 files changed, 3,448 insertions(+), 0 deletions(-)

diff --git a/monitord/beep.c b/monitord/beep.c
new file mode 100644
index 0000000..b02aa61
--- /dev/null
+++ b/monitord/beep.c
@@ -0,0 +1,216 @@
+/*********************************************************************************
+ *      Copyright:  (C) 2018 LingYun IoT System Studio
+ *                  All rights reserved.
+ *
+ *       Filename:  led.c
+ *    Description:  This file is used to control Passive buzzer or Active buzzer
+ *
+ *     pi@raspberrypi:~ $ gpio readall show BCM and wPi pinmap  
+ *
+ *                  VCC ---- 5V/3.3V
+ *                  GND ---- GND
+ *                  I/O ---- GPIO.18  ---- GPIO.1    
+ *                           BCM           wPi 
+ *                 
+ *        Version:  1.0.0(2018/10/14)
+ *         Author:  Guo Wenxue <guowenxue@gmail.com>
+ *      ChangeLog:  1, Release initial version on "2018/10/14 12:13:26"
+ *                 
+ ********************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <string.h>
+#include <time.h>
+#include <errno.h>
+
+#include <wiringPi.h>
+#include "beep.h"
+
+//#define CONFIG_ACTV_BEEP
+
+/* Only passive buzzer can play tone */
+#ifndef CONFIG_ACTV_BEEP 
+#define CONFIG_PLAY_LITTLE_STAR 
+//#define CONFIG_PLAY_TONE_TEST
+#endif
+
+void play_tone_freq(void);
+void play_little_star(void);
+
+
+/*+-----------------------------+
+ *|  Turn buzzer on or off API  |
+ *+-----------------------------+*/
+int turn_passive_beep(int cmd, int freq)
+{
+       	int range;
+
+	if(OFF == cmd)
+	{
+	       	pwmWrite(PWM_PIN, 0);
+	       	pinMode(PWM_PIN, INPUT) ;
+	}
+	else
+	{
+
+		if(freq<2000 || freq>5000)
+	       	{
+		       	printf("Beep set invalid PWM frequency[%d]!\n", freq);
+		       	return -1;
+	       	}
+
+		/* Set GPIO as PWM output mode */
+	       	pinMode(PWM_PIN, PWM_OUTPUT) ;
+
+		/* Set PWM mode as ms mode */
+	       	pwmSetMode(PWM_MODE_MS);
+
+		/* Set PWM clock: 19.2MHz/32=600KHz */
+	       	pwmSetClock(32);
+
+		/* Set PWM frequency */
+		range=600000/freq;
+		pwmSetRange(range);
+
+		/* Set PWM duty 50% */
+		pwmWrite(PWM_PIN, range/2);
+	}
+}
+
+
+/* Turn ON/OFF buzzer, Active Buzzer can not set frequency */
+int turn_active_beep(int cmd)
+{
+
+        /* Active buzzer VCC connect to:
+           5V: Both high and low level will be on
+         3.3V: Low level be on and High level be off
+
+	   So we use INPUT or OUTPUT to control the Beeper
+	*/
+	if(OFF == cmd)
+	{
+	       	pinMode(PWM_PIN, INPUT);
+	}
+	else
+	{
+	       	pinMode(PWM_PIN, OUTPUT);
+		digitalWrite(PWM_PIN, LOW);
+	}
+
+	return 0;
+}
+
+
+/*+---------------------------------+
+ *|  Play Tone OD,RE,MI....XI,DO1   |
+ *+---------------------------------+*/
+
+enum
+{
+	UNUSED=0,
+	DO,
+	RE,
+	MI,
+	FA,
+	SO,
+	LA,
+	XI,
+	DO1,
+	RI1,
+	TONE_MAX,
+};
+
+#define msleep(x) usleep( 1000*(x) )
+
+static int tone_freq[TONE_MAX]={0, 2093, 2349, 2637, 2794, 3136, 3520, 3952, 4186, 4698 };
+//static int tone_freq[TONE_MAX]={0, 2000, 2130, 2250, 2360, 2450, 2530, 2620, 2700, 2780};
+
+static inline void play_tone(int tone, int delay)
+{
+	if(tone<DO || tone>RI1)
+		return ;
+
+       	turn_passive_beep(ON, tone_freq[tone]);
+	msleep(delay);
+       	turn_passive_beep(OFF, 0);
+}
+
+void play_tone_freq(void)
+{
+	int            i;
+
+	for(i=DO; i<TONE_MAX; i++)
+	{
+		play_tone( i, 500 );
+		msleep(500);
+	}
+}
+
+
+/*+------------------------------+
+ *|  Play song "Little Start"    |
+ *+------------------------------+*/
+
+typedef struct tone_s
+{
+	int     tone;
+	int     delay_ms;   
+
+} tone_t;
+
+#define DEF_DELAY      350 
+static tone_t little_start_notation[]=
+{
+	{DO, DEF_DELAY},
+	{DO, DEF_DELAY},
+	{SO, DEF_DELAY},
+	{SO, DEF_DELAY},
+	{LA, DEF_DELAY},
+	{LA, DEF_DELAY},
+	{SO, DEF_DELAY*2},
+
+	{FA, DEF_DELAY},
+	{FA, DEF_DELAY},
+	{MI, DEF_DELAY},
+	{MI, DEF_DELAY},
+	{RE, DEF_DELAY},
+	{RE, DEF_DELAY},
+	{DO, DEF_DELAY*2},
+
+
+	{SO, DEF_DELAY},
+	{SO, DEF_DELAY},
+	{FA, DEF_DELAY},
+	{FA, DEF_DELAY},
+	{MI, DEF_DELAY},
+	{MI, DEF_DELAY},
+	{RE, DEF_DELAY*2},
+
+
+	{SO, DEF_DELAY},
+	{SO, DEF_DELAY},
+	{FA, DEF_DELAY},
+	{FA, DEF_DELAY},
+	{MI, DEF_DELAY},
+	{MI, DEF_DELAY},
+	{RE, DEF_DELAY*2},
+};
+
+#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
+void play_little_star(void)
+{
+	int        i;
+
+	for(i=0; i<ARRAY_SIZE(little_start_notation); i++)
+	{
+		play_tone(little_start_notation[i].tone, little_start_notation[i].delay_ms);
+		msleep(30);
+	}
+}
+
+
diff --git a/monitord/beep.h b/monitord/beep.h
new file mode 100644
index 0000000..68c4751
--- /dev/null
+++ b/monitord/beep.h
@@ -0,0 +1,38 @@
+/*********************************************************************************
+ *      Copyright:  (C) 2018 LingYun IoT System Studio
+ *                  All rights reserved.
+ *
+ *       Filename:  beep.h
+ *    Description:  This file is used to control Passive buzzer or Active buzzer
+ *
+ *     pi@raspberrypi:~ $ gpio readall show BCM and wPi pinmap  
+ *
+ *                VCC ---- 5V/3.3V
+ *                GND ---- GND
+ *                I/O ---- GPIO.18  ---- GPIO.1 
+ *                         BCM           wPi
+ *                 
+ *        Version:  1.0.0(2018/10/14)
+ *         Author:  Guo Wenxue <guowenxue@gmail.com>
+ *      ChangeLog:  1, Release initial version on "2018/10/14 12:13:26"
+ *                 
+ ********************************************************************************/
+
+#ifndef __BEEP_H
+#define __BEEP_H
+
+#define OFF           0
+#define ON            1
+
+#define BEEP_FREQ     2400
+
+/* Use Pin12 == GPIO18(BCM) == GPIO.1(wPi) */
+#define PWM_PIN       1
+
+
+int turn_passive_beep(int cmd, int freq);
+
+int turn_active_beep(int cmd);
+
+#endif
+
diff --git a/monitord/cp_comport.c b/monitord/cp_comport.c
new file mode 100644
index 0000000..8363cb2
--- /dev/null
+++ b/monitord/cp_comport.c
@@ -0,0 +1,600 @@
+/*  ********************************************************************************
+ *      Copyright:  (C) 2012 Guo Wenxue <guowenxue@gmail.com>
+ *                  All rights reserved.
+ *
+ *       Filename:  cp_comport.c
+ *    Description:  It's the comport operate library.
+ *                  
+ *        Version:  1.0.0(10/17/2011~)
+ *         Author:  Guo Wenxue <guowenxue@gmail.com>
+ *      ChangeLog:  1, Release initial version on "10/17/2011 03:33:25 PM"
+ *                  
+ ********************************************************************************/
+
+#include    "cp_comport.h"
+
+/**************************************************************************************
+ *  Description: Set the comport structure
+ *   Input Args: dev_name:  The comport device name path, such as '/dev/ttyS3'
+ *               baudrate:  The baudrate, such as 115200
+ *               settings:  The databit,parity,stopbit,flowctrl settings, such as '8N1N'
+ *  Output Args: NONE
+ * Return Value: The cp_comport_t structure pointer.
+ *************************************************************************************/
+cp_comport_t *comport_init(const char *dev_name, int baudrate, const char *settings)
+{
+    cp_comport_t *comport = NULL;
+    if (NULL == (comport = (cp_comport_t *) malloc(sizeof(cp_comport_t))))
+    {
+        return NULL;
+    }
+    memset(comport, 0, sizeof(cp_comport_t));
+    comport->connected = 0;
+    comport->frag_size = 128;
+
+    strncpy(comport->dev_name, dev_name, DEVNAME_LEN);
+    comport->baudrate = baudrate;
+
+    set_settings(comport, settings);
+#ifdef  COM_DEBUG
+    disp_settings(comport);
+#endif
+
+    return comport;
+}
+
+#ifdef  COM_DEBUG
+void disp_settings(cp_comport_t * comport)
+{
+    COM_PRINT("Device:\t\t\t\"%s\"\n", comport->dev_name);
+    COM_PRINT("Baudrate:\t\t%ld\n", comport->baudrate);
+    COM_PRINT("DataBit:\t\t\'%d\'\n", comport->databit);
+    switch (comport->parity)
+    {
+      case 0:
+          COM_PRINT("Parity:\t\t\t\'N\'\n");
+          break;
+      case 1:
+          COM_PRINT("Parity:\t\t\t\'O\'\n");
+          break;
+      case 2:
+          COM_PRINT("Parity:\t\t\t\'E\'\n");
+          break;
+      case 3:
+          COM_PRINT("Parity:\t\t\t\'S\'\n");
+          break;
+    }
+    COM_PRINT("StopBit:\t\t\'%ld\'\n", (long int)comport->stopbit);
+    switch (comport->flowctrl)
+    {
+      case 0:
+          COM_PRINT("FlowCtrl:\t\t\'N\'\n");
+          break;
+      case 1:
+          COM_PRINT("FlowCtrl:\t\t\'S\'\n");
+          break;
+      case 2:
+          COM_PRINT("FlowCtrl:\t\t\'H\'\n");
+          break;
+      case 3:
+          COM_PRINT("FlowCtrl:\t\t\'B\'\n");
+          break;
+    }
+    COM_PRINT("\n");
+    return;
+}
+#endif
+
+/**************************************************************************************
+ *  Description: Set the comport databit,parity,stopbit,flowctrl
+ *   Input Args: comport: the cp_comport_t pointer
+ *               settings: The databit/parity/stopbit/flowctrl settings as like "8N1N" 
+ *  Output Args: NONE
+ * Return Value: NONE
+ *************************************************************************************/
+void set_settings(cp_comport_t * comport, const char *settings)
+{
+    if(NULL==settings || NULL==comport)
+        return ;
+
+    switch (settings[0])        /* data bit */
+    {
+      case '7':
+          comport->databit = 7;
+          break;
+      case '8':
+      default:
+          comport->databit = 8;
+          break;
+    }
+
+    switch (settings[1])        /* parity */
+    {
+      case 'O':
+      case 'o':
+          comport->parity = 1;
+          break;
+      case 'E':
+      case 'e':
+          comport->parity = 2;
+          break;
+      case 'S':
+      case 's':
+          comport->parity = 3;
+          break;
+      case 'N':
+      case 'n':
+      default:
+          comport->parity = 0;
+          break;
+    }
+
+    switch (settings[2])        /* stop bit */
+    {
+      case '0':
+          comport->stopbit = 0;
+          break;
+      case '1':
+      default:
+          comport->stopbit = 1;
+          break;
+    }
+
+    switch (settings[3])        /* flow control */
+    {
+      case 'S':
+      case 's':
+          comport->flowctrl = 1;
+          break;
+      case 'H':
+      case 'h':
+          comport->flowctrl = 2;
+          break;
+      case 'B':
+      case 'b':
+          comport->flowctrl = 3;
+          break;
+      case 'N':
+      case 'n':
+      default:
+          comport->flowctrl = 0;
+          break;
+    }
+}
+
+void comport_close(cp_comport_t * comport)
+{
+    if (0 != comport->fd)
+    {
+        COM_PRINT("Close device \"%s\"\n", comport->dev_name);
+        close(comport->fd);
+    }
+    comport->connected = 0x00;
+    comport->fd = -1;
+}
+
+void cp_comport_term(cp_comport_t * comport)
+{
+    if(NULL == comport)
+        return;
+
+    if (0 != comport->fd)
+    {
+        comport_close(comport);
+    }
+    memset(comport, 0x00, sizeof(cp_comport_t)); 
+    free(comport);
+    comport = NULL;
+
+    return;
+}
+
+int comport_open(cp_comport_t * comport)
+{
+    int retval = -1;
+    struct termios old_cfg, new_cfg;
+    int old_flags;
+    long tmp;
+
+    if(NULL==comport)
+        return -1;
+
+    comport_close(comport);
+
+
+    /* Not a TTY device */
+    if( !strstr(comport->dev_name, "tty"))
+    {
+        COM_PRINT("Open Not tty device \"%s\"\n", comport->dev_name);
+        comport->fd = open(comport->dev_name, O_RDWR);
+        retval = comport->fd<0 ? -2 : comport->fd;
+        goto CleanUp;
+    }
+
+    comport->fd = open(comport->dev_name, O_RDWR | O_NOCTTY | O_NONBLOCK);
+    if (comport->fd < 0)
+    {
+        retval = -3;
+        goto CleanUp;
+    }
+    COM_PRINT("Open device \"%s\"\n", comport->dev_name);
+
+    if ((-1 != (old_flags = fcntl(comport->fd, F_GETFL, 0)))
+        && (-1 != fcntl(comport->fd, F_SETFL, old_flags & ~O_NONBLOCK)))
+    {
+        // Flush input and output
+        if (-1 == tcflush(comport->fd, TCIOFLUSH))
+        {
+            retval = -4;
+            goto CleanUp;
+        }
+    }
+    else                        // Failure
+    {
+        retval = -5;
+        goto CleanUp;
+    }
+
+    if (0 != tcgetattr(comport->fd, &old_cfg))
+    {
+        retval = -6;          // Failed to get Com settings  
+        goto CleanUp;
+    }
+
+    memset(&new_cfg, 0, sizeof(new_cfg));
+
+    /*=====================================*/
+    /*       Configure comport         */
+    /*=====================================*/
+
+    new_cfg.c_cflag &= ~CSIZE;
+    new_cfg.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
+    new_cfg.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
+    new_cfg.c_oflag &= ~(OPOST);
+
+    /* Set the data bit */
+    switch (comport->databit)
+    {
+      case 0x07:
+          new_cfg.c_cflag |= CS7;
+          break;
+      case 0x06:
+          new_cfg.c_cflag |= CS6;
+          break;
+      case 0x05:
+          new_cfg.c_cflag |= CS5;
+          break;
+      default:
+          new_cfg.c_cflag |= CS8;
+          break;
+    }
+
+    /* Set the parity */
+    switch (comport->parity)
+    {
+      case 0x01:               // Odd  
+          new_cfg.c_cflag |= (PARENB | PARODD);
+          new_cfg.c_cflag |= (INPCK | ISTRIP);
+          break;
+      case 0x02:               // Even 
+          new_cfg.c_cflag |= PARENB;
+          new_cfg.c_cflag &= ~PARODD;;
+          new_cfg.c_cflag |= (INPCK | ISTRIP);
+          break;
+      case 0x03:
+          new_cfg.c_cflag &= ~PARENB;
+          new_cfg.c_cflag &= ~CSTOPB;
+          break;
+      default:
+          new_cfg.c_cflag &= ~PARENB;
+    }
+
+    /* Set Stop bit */
+    if (0x01 != comport->stopbit)
+    {
+        new_cfg.c_cflag |= CSTOPB;
+    }
+    else
+    {
+        new_cfg.c_cflag &= ~CSTOPB;
+    }
+
+    /* Set flow control */
+    switch (comport->flowctrl)
+    {
+      case 1:                  // Software control 
+      case 3:
+          new_cfg.c_cflag &= ~(CRTSCTS);
+          new_cfg.c_iflag |= (IXON | IXOFF);
+          break;
+      case 2:                  // Hardware control
+          new_cfg.c_cflag |= CRTSCTS;   // Also called CRTSCTS
+          new_cfg.c_iflag &= ~(IXON | IXOFF);
+          break;
+      default:                 // NONE
+          new_cfg.c_cflag &= ~(CRTSCTS);
+          new_cfg.c_iflag &= ~(IXON | IXOFF);
+          break;
+    }
+
+    /* Set baudrate */
+    switch (comport->baudrate)
+    {
+      case 115200:
+          tmp = B115200;
+          break;
+      case 57600:
+          tmp = B57600;
+          break;
+      case 38400:
+          tmp = B38400;
+          break;
+      case 19200:
+          tmp = B19200;
+          break;
+      case 9600:
+          tmp = B9600;
+          break;
+      case 4800:
+          tmp = B4800;
+          break;
+      case 2400:
+          tmp = B2400;
+          break;
+      case 1800:
+          tmp = B1800;
+          break;
+      case 1200:
+          tmp = B1200;
+          break;
+      case 600:
+          tmp = B600;
+          break;
+      case 300:
+          tmp = B300;
+          break;
+      case 200:
+          tmp = B200;
+          break;
+      case 150:
+          tmp = B150;
+          break;
+      case 134:
+          tmp = B134;
+          break;
+      case 110:
+          tmp = B110;
+          break;
+      case 75:
+          tmp = B75;
+          break;
+      case 50:
+          tmp = B50;
+          break;
+      default:
+          tmp = B115200;
+    }
+    cfsetispeed(&new_cfg, tmp);
+    cfsetispeed(&new_cfg, tmp);
+
+    /* Set the Com port timeout settings */
+    new_cfg.c_cc[VMIN] = 0;
+    new_cfg.c_cc[VTIME] = 0;
+
+    tcflush(comport->fd, TCIFLUSH);
+    if (0 != tcsetattr(comport->fd, TCSANOW, &new_cfg))
+    {
+        retval = -7;          // Failed to set device com port settings   
+        goto CleanUp;
+    }
+
+    COM_PRINT("Connected device \"%s\".\n", comport->dev_name);
+    comport->connected = 0x01;
+    retval = comport->fd;
+
+CleanUp:
+    COM_PRINT("Open device \"%s\" %s.\n", comport->dev_name, retval>0 ? "successfully" : "failure");
+    return retval;
+}
+
+void nonblock()
+{
+    struct termios ttystate;
+
+    //get the terminal state
+    tcgetattr(STDIN_FILENO, &ttystate);
+
+    //turn off canonical mode
+    ttystate.c_lflag &= ~ICANON;
+    //minimum of number input read.
+    ttystate.c_cc[VMIN] = 1;
+
+    //set the terminal attributes.
+    tcsetattr(STDIN_FILENO, TCSANOW, &ttystate);
+}
+
+int kbhit()
+{
+    struct timeval tv;
+    fd_set fds;
+    tv.tv_sec = 0;
+    tv.tv_usec = 0;
+    FD_ZERO(&fds);
+    FD_SET(STDIN_FILENO, &fds); //STDIN_FILENO is 0
+    select(STDIN_FILENO + 1, &fds, NULL, NULL, &tv);
+    return FD_ISSET(STDIN_FILENO, &fds);
+}
+
+int comport_recv(cp_comport_t * comport, char *buf, int buf_size, unsigned long timeout)
+{
+    int retval = 0;             // Function return value
+    int iRet;
+    fd_set stReadFds, stExcpFds;
+    struct timeval stTime;
+
+    if (NULL == buf || 0 >= buf_size)
+    {
+        COM_PRINT("%s() usage error.\n", __FUNCTION__);
+        retval = -1;
+        goto CleanUp;
+    }
+
+    if (0x01 != comport->connected)
+    {
+        COM_PRINT("%s() comport not connected.\n", __FUNCTION__);
+        retval = -2;
+        goto CleanUp;
+    }
+
+    //printf("bufsize=%d timeout=%lu\n", buf_size, timeout);
+
+    FD_ZERO(&stReadFds);
+    FD_ZERO(&stExcpFds);
+    FD_SET(comport->fd, &stReadFds);
+    FD_SET(comport->fd, &stExcpFds);
+
+    if (0xFFFFFFFF != timeout)
+    {
+        stTime.tv_sec = (time_t) (timeout / 1000);
+        stTime.tv_usec = (long)(1000 * (timeout % 1000));
+
+        iRet = select(comport->fd + 1, &stReadFds, 0, &stExcpFds, &stTime);
+        if (0 == iRet)
+        {
+            retval = 0;         // No data in Com port buffer
+            goto CleanUp;
+        }
+        else if (0 < iRet)
+        {
+            if (0 != FD_ISSET(comport->fd, &stExcpFds))
+            {
+                retval = -6;  // Error during checking recv status    
+                COM_PRINT("Error checking recv status.\n");
+                goto CleanUp;
+            }
+
+            if (0 == FD_ISSET(comport->fd, &stReadFds))
+            {
+                retval = 0;  // No incoming data 
+                COM_PRINT("No incoming data.\n");
+                goto CleanUp;
+            }
+        }
+        else
+        {
+            if (EINTR == errno)
+            {
+                COM_PRINT("catch interrupt signal.\n");
+                retval = 0;  // Interrupted signal catched
+            }
+            else
+            {
+                COM_PRINT("Check recv status failure.\n");
+                retval = -7;  // Error during checking recv status
+            }
+
+            goto CleanUp;
+        }
+    }
+
+    usleep(10000); /* sleep for 10ms for data incoming */
+
+    // Get data from Com port
+    iRet = read(comport->fd, buf, buf_size);
+    if (0 > iRet)
+    {
+        if (EINTR == errno)
+            retval = 0;      // Interrupted signal catched
+        else
+            retval = -3;      // Failed to read Com port
+
+        goto CleanUp;
+    }
+
+#if 0
+    {
+        int   i=0;
+        printf("Receive %d bytes data: \n", iRet);
+        for(i=0; i<iRet; i++)
+        {
+            printf("0x%02x ", buf[i]);
+        }
+        printf("\n");
+    }
+#endif
+
+    retval = iRet;
+
+  CleanUp:
+    return retval;
+
+}
+
+int comport_send(cp_comport_t * comport, char *buf, int send_bytes)
+{
+    char *ptr, *end;
+    int retval = 0;
+    int send = 0;
+
+    if (NULL == buf || 0 >= send_bytes)
+    {
+        COM_PRINT("%s() Usage error.\n", __FUNCTION__);
+        retval = -1;
+        goto CleanUp;
+    }
+
+    if (0x01 != comport->connected)    // Comport not opened ?
+    {
+        retval = -3;
+        COM_PRINT("Serail not connected.\n");
+        goto CleanUp;
+    }
+
+    //printf("Send %s with %d bytes.\n", buf, send_bytes);
+
+    // Large data, then slice them and send
+    if (comport->frag_size < send_bytes)
+    {
+        ptr = buf;
+        end = buf + send_bytes;
+
+        do
+        {
+            // Large than frag_size
+            if (comport->frag_size < (end - ptr))
+            {
+                send = write(comport->fd, ptr, comport->frag_size);
+                if (0 >= send || comport->frag_size != send)
+                {
+                    retval = -4;
+                    goto CleanUp;
+                }
+                ptr += comport->frag_size;
+            }
+            else                // Less than frag_size, maybe last fragmention.
+            {
+                send = write(comport->fd, ptr, (end - ptr));
+                if (0 >= send || (end - ptr) != send)
+                {
+                    retval = -4;
+                    goto CleanUp;
+                }
+                ptr += (end - ptr);
+            }
+        }
+        while (ptr < end);
+    }
+    else                        // The send data is not large than a fragmention.
+    {
+        send = write(comport->fd, buf, send_bytes);
+        if (0 >= send || send_bytes != send)
+        {
+            retval = -5;
+            goto CleanUp;
+        }
+    }
+
+  CleanUp:
+    return retval;
+}
+
diff --git a/monitord/cp_comport.h b/monitord/cp_comport.h
new file mode 100644
index 0000000..5c08b9b
--- /dev/null
+++ b/monitord/cp_comport.h
@@ -0,0 +1,67 @@
+/*********************************************************************************
+ *      Copyright:  (C) 2012 Guo Wenxue <guowenxue@gmail.com>
+ *                  All rights reserved.
+ *
+ *       Filename:  cp_comport.h
+ *    Description:  This head file is for the common TTY/Serial port operator library 
+ *                   
+ *        Version:  1.0.0(10/17/2011~)
+ *         Author:  Guo Wenxue <guowenxue@gmail.com>
+ *      ChangeLog:  1, Release initial version on "10/17/2011 03:33:25 PM"
+ *                     
+ ********************************************************************************/
+#ifndef  _CP_COMPORT_H
+#define  _CP_COMPORT_H
+
+#include  <stdio.h>
+#include  <stdlib.h>
+#include  <unistd.h>
+#include  <string.h>
+#include  <getopt.h>
+#include  <fcntl.h>
+#include  <errno.h>
+#include  <termios.h>
+#include  <sys/stat.h>
+#include  <sys/wait.h>
+#include  <sys/types.h>
+#include  <sys/stat.h>
+#include  <sys/select.h>
+
+#define BUF_64  64
+
+#ifndef DEVNAME_LEN
+#define DEVNAME_LEN          64
+#endif
+
+//#define COM_DEBUG
+#ifdef  COM_DEBUG
+#define COM_PRINT(format,args...) printf(format, ##args)
+#else
+#define COM_PRINT(format,args...) do{} while(0);
+#endif
+
+//#define msleep(m)               {struct timespec cSleep; cSleep.tv_sec = 0; cSleep.tv_nsec = m * 1000; nanosleep(&cSleep, 0);}
+
+typedef struct cp_comport_s
+{
+    unsigned char databit, parity, stopbit, flowctrl, connected;
+    char dev_name[DEVNAME_LEN];
+    unsigned char  used;     /* This comport used or not now */
+    int fd;
+    int frag_size;
+    long baudrate;
+} cp_comport_t;
+
+cp_comport_t *comport_init(const char *dev_name, int baudrate, const char *settings);
+void comport_close(cp_comport_t * comport);
+int comport_open(cp_comport_t * comport);
+void cp_comport_term(cp_comport_t * comport);
+int comport_recv(cp_comport_t * comport, char *buf, int buf_size, unsigned long timeout);
+int comport_send(cp_comport_t * comport, char *buf, int send_bytes);
+
+void set_settings(cp_comport_t * comport, const char *settings);
+void disp_settings(cp_comport_t * comport);
+void nonblock();
+int kbhit();
+
+#endif
diff --git a/monitord/cp_logger.c b/monitord/cp_logger.c
new file mode 100644
index 0000000..efb04e5
--- /dev/null
+++ b/monitord/cp_logger.c
@@ -0,0 +1,433 @@
+/*********************************************************************************
+ *      Copyright:  (C) 2012 Guo Wenxue <guowenxue@gmail.com>
+ *                  All rights reserved.
+ *
+ *       Filename:  cp_log.c
+ *    Description:  This file is the linux infrastructural logger system library
+ *                 
+ *        Version:  1.0.0(08/08/2012~)
+ *         Author:  Guo Wenxue <guowenxue@gmail.com>
+ *      ChangeLog:  1, Release initial version on "08/08/2012 04:24:01 PM"
+ *                 
+ ********************************************************************************/
+
+#include "cp_logger.h"
+//#include "cp_common.h"
+
+#define PRECISE_TIME_FACTOR 1000
+
+static unsigned long log_rollback_size = LOG_ROLLBACK_NONE;
+
+static cp_logger *logger = NULL;
+
+char *log_str[LOG_LEVEL_MAX + 1] = { "", "F", "E", "W", "N", "D", "I", "T", "M" };
+
+static char *cp_time_format = DEFAULT_TIME_FORMAT;
+
+void cp_log_set_time_format(char *time_format)
+{
+    cp_time_format = time_format;
+}
+
+static void cp_log_default_signal_handler(int sig)
+{
+    if(!logger)
+        return ;
+
+    if (sig == SIGHUP)
+    {
+        signal(SIGHUP, cp_log_default_signal_handler);
+        log_fatal("SIGHUP received - reopenning log file [%s]", logger->file);
+        cp_log_reopen();
+    }
+}
+
+static void log_banner(char *prefix)
+{
+    if(!logger)
+        return ;
+
+    fprintf(logger->fp, "%s log \"%s\" on level [%s] size [%lu] KiB, log system version %s\n",
+            prefix, logger->file, log_str[logger->level], log_rollback_size / 1024, LOG_VERSION_STR);
+#ifdef LOG_FILE_LINE
+    fprintf(logger->fp, " [Date]    [Time]   [Level] [PID/TID] [File/Line]  [Content]\n");
+#else
+    fprintf(logger->fp, " [Date]    [Time]   [Level] [PID/TID] [Content]\n");
+#endif
+    fprintf(logger->fp, "-------------------------------------------------------------\n");
+}
+
+static void check_and_rollback(void)
+{
+    if(!logger)
+        return ;
+
+    if (log_rollback_size != LOG_ROLLBACK_NONE)
+    {
+        long _curOffset = ftell(logger->fp);
+
+        if ((_curOffset != -1) && (_curOffset >= log_rollback_size))
+        {
+            char cmd[512];
+
+            snprintf(cmd, sizeof(cmd), "cp -f %s %s.roll", logger->file, logger->file);
+            system(cmd);
+
+            if (-1 == fseek(logger->fp, 0L, SEEK_SET))
+                fprintf(logger->fp, "log rollback fseek failed \n");
+
+            rewind(logger->fp);
+
+            truncate(logger->file, 0);
+            log_banner("Already rollback");
+        }
+    }
+}
+
+cp_logger *cp_log_init(cp_logger *log, char *filename, int level, int log_size)
+{
+    if(NULL == log)
+    {
+        logger = malloc(sizeof(cp_logger));
+        memset(logger, 0, sizeof(cp_logger));
+        logger->flag |= CP_LOGGER_MALLOC; 
+    }
+    else
+    {
+        logger = log;
+        logger->flag |= CP_LOGGER_ARGUMENT; 
+    }
+
+    if(NULL == logger)
+    {
+        return NULL;
+    }
+
+    strncpy(logger->file, filename, FILENAME_LEN); 
+    logger->level = level;
+    logger->size = log_size; 
+
+    return logger;
+}
+
+int cp_log_open(void)
+{
+    struct sigaction act;
+    char *filemode;
+
+    if(!logger)
+    {
+        return -1;
+    }
+
+    log_rollback_size = logger->size <= 0 ? LOG_ROLLBACK_NONE : logger->size*1024;    /* Unit KiB */
+        
+    if ('\0' == logger->file)
+        return -1;
+
+    if (!strcmp(logger->file, DBG_LOG_FILE))
+    {
+        logger->fp = stderr;
+        log_rollback_size = LOG_ROLLBACK_NONE;
+        logger->flag |= CP_LOGGER_CONSOLE;
+        goto OUT;
+    }
+
+    filemode = (log_rollback_size==LOG_ROLLBACK_NONE) ? "a+" : "w+";
+
+    logger->fp = fopen(logger->file, filemode);
+    if (NULL == logger->fp)
+    {
+        fprintf(stderr, "Open log file \"%s\" in %s failure\n", logger->file, filemode);
+        return -2;
+    }
+
+    act.sa_handler = cp_log_default_signal_handler;
+    sigemptyset(&act.sa_mask);
+    act.sa_flags = 0;
+    sigaction(SIGHUP, &act, NULL);
+
+  OUT:
+    log_banner("Initialize");
+
+    return 0;
+}
+
+void cp_log_close(void)
+{
+    if (!logger || !logger->fp )
+        return;
+
+    log_banner("\nTerminate");
+    cp_log_raw("\n\n\n\n");
+
+    fflush(logger->fp);
+
+    fclose(logger->fp);
+    logger->fp = NULL;
+
+    return ;
+}
+
+int cp_log_reopen(void)
+{
+    int rc = 0;
+    char *filemode;
+
+    if( !logger )
+        return -1;
+
+    log_rollback_size = logger->size <= 0 ? LOG_ROLLBACK_NONE : logger->size*1024;    /* Unit KiB */
+
+    if (logger->flag & CP_LOGGER_CONSOLE )
+    {
+        fflush(logger->fp);
+        logger->fp = stderr;
+        return 0;
+    }
+
+    if (logger->fp)
+    {
+        cp_log_close();
+        filemode = log_rollback_size==LOG_ROLLBACK_NONE ? "a+" : "w+";
+        logger->fp = fopen(logger->file, filemode); 
+        
+        if (logger->fp == NULL)
+            rc = -2;
+    }
+    else
+    {
+        rc = -3;
+    }
+
+    if (!rc)
+    {
+        log_banner("\nReopen");
+    }
+    return rc;
+}
+
+void cp_log_term(void)
+{
+    if(!logger)
+        return ;
+
+    cp_log_close();
+
+    if (logger->flag & CP_LOGGER_MALLOC )
+    {
+        free(logger);
+    }
+    logger = NULL;
+}
+
+void cp_log_raw(const char *fmt, ...)
+{
+    va_list argp;
+
+    if (!logger || !logger->fp)
+        return;
+
+    check_and_rollback();
+
+    va_start(argp, fmt);
+    vfprintf(logger->fp, fmt, argp);
+    va_end(argp);
+}
+
+static void cp_printout(char *level, char *fmt, va_list argp)
+{
+    char buf[MAX_LOG_MESSAGE_LEN];
+    struct tm *local;
+    struct timeval now;
+    char timestr[256];
+
+    if(!logger)
+        return ;
+
+    pthread_t tid;
+
+    check_and_rollback();
+
+#ifdef MULTHREADS
+    tid = pthread_self();
+#else 
+    tid = getpid();
+#endif
+
+    gettimeofday(&now, NULL);
+    local = localtime(&now.tv_sec);
+
+    strftime(timestr, 256, cp_time_format, local);
+    vsnprintf(buf, MAX_LOG_MESSAGE_LEN, fmt, argp);
+
+#ifdef DUMPLICATE_OUTPUT
+    printf("%s.%03ld [%s] [%06lu]: %s",
+           timestr, now.tv_usec / PRECISE_TIME_FACTOR, level, tid, buf);
+#endif
+
+    if (logger->fp)
+        fprintf(logger->fp, "%s.%03ld [%s] [%06lu]: %s", timestr, now.tv_usec / PRECISE_TIME_FACTOR,
+                level, tid, buf);
+
+    if (logger->fp)
+        fflush(logger->fp);
+}
+
+static void cp_printout_line(char *level, char *fmt, char *file, int line, va_list argp)
+{
+    char buf[MAX_LOG_MESSAGE_LEN];
+    struct tm *local;
+    struct timeval now;
+    char timestr[256];
+
+    if(!logger)
+        return ;
+
+    pthread_t tid;
+
+    check_and_rollback();
+
+#ifdef MULTHREADS
+    tid = pthread_self();
+#else 
+    tid = getpid();
+#endif
+
+    gettimeofday(&now, NULL);
+    local = localtime(&now.tv_sec);
+
+    strftime(timestr, 256, cp_time_format, local);
+    vsnprintf(buf, MAX_LOG_MESSAGE_LEN, fmt, argp);
+
+#ifdef DUMPLICATE_OUTPUT
+    printf("%s.%03ld [%s] [%06lu] (%s [%04d]) : %s",
+           timestr, now.tv_usec / PRECISE_TIME_FACTOR, level, tid, file, line, buf);
+#endif
+
+    if (logger->fp)
+        fprintf(logger->fp, "%s.%03ld [%s] [%06lu] (%s [%04d]) : %s",
+                timestr, now.tv_usec / PRECISE_TIME_FACTOR, level, tid, file, line, buf);
+
+    if (logger->fp)
+        fflush(logger->fp);
+}
+
+void cp_log_str(int level, const char *msg)
+{
+    if (!logger || level>logger->level)
+        return;
+
+    check_and_rollback();
+
+    if (logger->fp)
+        fwrite(msg, 1, strlen(msg), logger->fp);
+
+    if(logger->fp)
+        fflush(logger->fp);
+}
+
+void cp_log(int level, char *fmt, ...)
+{
+    va_list argp;
+
+    if (!logger || level>logger->level)
+        return;
+
+    va_start(argp, fmt);
+    cp_printout(log_str[level], fmt, argp);
+    va_end(argp);
+}
+
+void cp_log_line(int level, char *file, int line, char *fmt, ...)
+{
+    va_list argp;
+
+    if (!logger || level>logger->level)
+        return;
+
+    va_start(argp, fmt);
+    cp_printout_line(log_str[level], fmt, file, line, argp);
+
+    va_end(argp);
+}
+
+#define LINELEN 81
+#define CHARS_PER_LINE 16
+static char *print_char =
+    "                "
+    "                "
+    " !\"#$%&'()*+,-./"
+    "0123456789:;<=>?"
+    "@ABCDEFGHIJKLMNO"
+    "PQRSTUVWXYZ[\\]^_"
+    "`abcdefghijklmno"
+    "pqrstuvwxyz{|}~ "
+    "                "
+    "                "
+    " ???????????????"
+    "????????????????" 
+    "????????????????" 
+    "????????????????" 
+    "????????????????" 
+    "????????????????";
+
+void cp_log_dump(int level, char *buf, int len)
+{
+    int rc;
+    int idx;
+    char prn[LINELEN];
+    char lit[CHARS_PER_LINE + 2];
+    char hc[4];
+    short line_done = 1;
+
+    if (!logger || level>logger->level)
+        return;
+
+    rc = len;
+    idx = 0;
+    lit[CHARS_PER_LINE] = '\0';
+
+    while (rc > 0)
+    {
+        if (line_done)
+            snprintf(prn, LINELEN, "%08X: ", idx);
+
+        do
+        {
+            unsigned char c = buf[idx];
+            snprintf(hc, 4, "%02X ", c);
+            strncat(prn, hc, LINELEN);
+
+            lit[idx % CHARS_PER_LINE] = print_char[c];
+        }
+        while (--rc > 0 && (++idx % CHARS_PER_LINE != 0));
+
+        line_done = (idx % CHARS_PER_LINE) == 0;
+        if (line_done)
+        {
+#ifdef DUMPLICATE_OUTPUT
+            printf("%s  %s\n", prn, lit);
+#endif
+            if (logger->fp)
+                fprintf(logger->fp, "%s  %s\n", prn, lit);
+        }
+    }
+
+    if (!line_done)
+    {
+        int ldx = idx % CHARS_PER_LINE;
+        lit[ldx++] = print_char[(int)buf[idx]];
+        lit[ldx] = '\0';
+
+        while ((++idx % CHARS_PER_LINE) != 0)
+            strncat(prn, "   ", LINELEN);
+
+#ifdef DUMPLICATE_OUTPUT
+        printf("%s  %s\n", prn, lit);
+#endif
+        if (logger->fp)
+            fprintf(logger->fp, "%s  %s\n", prn, lit);
+
+    }
+}
diff --git a/monitord/cp_logger.h b/monitord/cp_logger.h
new file mode 100644
index 0000000..7548514
--- /dev/null
+++ b/monitord/cp_logger.h
@@ -0,0 +1,111 @@
+/********************************************************************************
+ *      Copyright:  (C) 2012 Guo Wenxue <guowenxue@gmail.com>
+ *                  All rights reserved.
+ *
+ *       Filename:  cp_logger.h
+ *    Description:  This file is the linux infrastructural logger system library
+ *
+ *        Version:  1.0.0(08/08/2012~)
+ *         Author:  Guo Wenxue <guowenxue@gmail.com>
+ *      ChangeLog:  1, Release initial version on "08/08/2012 05:16:56 PM"
+ *                 
+ ********************************************************************************/
+
+#ifndef __CP_LOG_H
+#define __CP_LOG_H
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+#include <time.h>
+#include <errno.h>
+
+#include <pthread.h>
+#include <sys/types.h>
+#include <sys/time.h>
+
+#define LOG_VERSION_STR             "1.0.0"
+
+#ifndef FILENAME_LEN
+#define FILENAME_LEN                64
+#endif
+
+#define DEFAULT_LOGFILE             "cp_logger.log"
+#define DBG_LOG_FILE                "console"  /*  Debug mode log file is console */ 
+
+#define LOG_ROLLBACK_SIZE           512    /* Default rollback log size  */
+#define LOG_ROLLBACK_NONE           0      /* Set rollback size to 0 will not rollback  */
+
+#define DEFAULT_TIME_FORMAT         "%Y-%m-%d %H:%M:%S"
+#define MAX_LOG_MESSAGE_LEN         0x1000
+
+//#define DUMPLICATE_OUTPUT  /* Log to file and printf on console  */
+#define LOG_FILE_LINE      /* Log the file and line */
+
+enum
+{
+    LOG_LEVEL_DISB = 0,               /*  Disable "Debug" */
+    LOG_LEVEL_FATAL,                  /*  Debug Level "Fatal" */
+    LOG_LEVEL_ERROR,                  /*  Debug Level "ERROR" */
+    LOG_LEVEL_WARN,                   /*  Debug Level "warnning" */
+    LOG_LEVEL_NRML,                   /*  Debug Level "Normal" */
+    LOG_LEVEL_DEBUG,                  /*  Debug Level "Debug" */
+    LOG_LEVEL_INFO,                   /*  Debug Level "Information" */
+    LOG_LEVEL_TRACE,                  /*  Debug Level "Trace" */
+    LOG_LEVEL_MAX,
+};
+
+#define CP_LOGGER_MALLOC              1<<0
+#define CP_LOGGER_ARGUMENT            0<<0
+
+#define CP_LOGGER_CONSOLE             1<<1
+#define CP_LOGGER_FILE                0<<1
+
+#define CP_LOGGER_LEVEL_OPT           1<<2 /*  The log level is sepcified by the command option */
+typedef struct _cp_logger
+{
+    unsigned char      flag;  /* This logger pointer is malloc() or passed by argument */
+    char               file[FILENAME_LEN];
+    int                level;
+    int                size;
+
+    FILE               *fp;
+} cp_logger;
+
+extern char *log_str[];
+
+extern cp_logger *cp_log_init(cp_logger *log, char *filename, int level, int log_size);
+extern int  cp_log_open(void);
+extern void cp_log_set_time_format(char *time_format);
+extern int  cp_log_reopen(void);
+extern void cp_log_term(void);
+extern void cp_log_raw(const char *fmt, ...);
+extern void cp_log(int level, char *fmt, ...);
+extern void cp_log_line(int level, char *file, int line, char *fmt, ...);
+extern void cp_log_str(int level, const char *msg);
+
+extern void cp_log_dump(int level, char *buf, int len);
+
+#ifdef LOG_FILE_LINE
+#define log_trace(fmt, ...) cp_log_line(LOG_LEVEL_TRACE, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
+#define log_info(fmt, ...)  cp_log_line(LOG_LEVEL_INFO,  __FILE__, __LINE__, fmt, ##__VA_ARGS__)
+#define log_dbg(fmt, ...)   cp_log_line(LOG_LEVEL_DEBUG, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
+#define log_nrml(fmt, ...)  cp_log_line(LOG_LEVEL_NRML,  __FILE__, __LINE__, fmt, ##__VA_ARGS__)
+#define log_warn(fmt, ...)  cp_log_line(LOG_LEVEL_WARN,  __FILE__, __LINE__, fmt, ##__VA_ARGS__)
+#define log_err(fmt, ...)   cp_log_line(LOG_LEVEL_ERROR, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
+#define log_fatal(fmt, ...) cp_log_line(LOG_LEVEL_FATAL, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
+#else
+#define log_trace(fmt, ...) cp_log(LOG_LEVEL_TRACE, fmt, ##__VA_ARGS__)
+#define log_info(fmt, ...) cp_log(LOG_LEVEL_INFO, fmt, ##__VA_ARGS__)
+#define log_dbg(fmt, ...) cp_log(LOG_LEVEL_DEBUG, fmt, ##__VA_ARGS__)
+#define log_nrml(fmt, ...) cp_log(LOG_LEVEL_NRML, fmt, ##__VA_ARGS__)
+#define log_warn(fmt, ...) cp_log(LOG_LEVEL_WARN, fmt, ##__VA_ARGS__)
+#define log_err(fmt, ...) cp_log(LOG_LEVEL_ERROR, fmt, ##__VA_ARGS__)
+#define log_fatal(fmt, ...) cp_log(LOG_LEVEL_FATAL, fmt, ##__VA_ARGS__)
+#endif
+
+
+#endif /* __CP_LOG_H  */
diff --git a/monitord/cp_proc.c b/monitord/cp_proc.c
new file mode 100644
index 0000000..769ec5c
--- /dev/null
+++ b/monitord/cp_proc.c
@@ -0,0 +1,342 @@
+/*********************************************************************************
+ *      Copyright:  (C) 2012 Guo Wenxue<guowenxue@gmail.com>  
+ *                  All rights reserved.
+ *
+ *       Filename:  cp_proc.c
+ *    Description:  This file is the process API
+ *                 
+ *        Version:  1.0.0(11/06/2012~)
+ *         Author:  Guo Wenxue <guowenxue@gmail.com>
+ *      ChangeLog:  1, Release initial version on "11/06/2012 09:19:02 PM"
+ *                 
+ ********************************************************************************/ 
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <libgen.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <pthread.h>
+
+#include "cp_proc.h"
+#include "cp_logger.h"
+
+CP_PROC_SIG     g_cp_signal={0};
+
+void cp_proc_sighandler(int sig)
+{
+    switch(sig)
+    {
+        case SIGINT:
+            log_warn("SIGINT - stopping\n");
+            g_cp_signal.stop = 1;
+            break;
+
+        case SIGTERM:
+            log_warn("SIGTERM - stopping\n");
+            g_cp_signal.stop = 1;
+            break;
+        case SIGSEGV:
+            log_warn("SIGSEGV - stopping\n");
+#if 0
+            if(g_cp_signal.stop)
+                exit(0);
+
+            g_cp_signal.stop = 1;
+#endif
+            break;
+
+        case SIGPIPE:
+            log_warn("SIGPIPE - warnning\n");
+            break;
+    
+        default:
+            break;
+    }
+}
+
+
+void cp_install_proc_signal(void)
+{
+    struct sigaction sigact, sigign;
+
+    log_nrml("Install default signal handler.\n");
+
+    /*  Initialize the catch signal structure. */
+    sigemptyset(&sigact.sa_mask);
+    sigact.sa_flags = 0;
+    sigact.sa_handler = cp_proc_sighandler;
+
+    /*  Setup the ignore signal. */
+    sigemptyset(&sigign.sa_mask);
+    sigign.sa_flags = 0;
+    sigign.sa_handler = SIG_IGN;
+
+    sigaction(SIGTERM, &sigact, 0); /*  catch terminate signal "kill" command */
+    sigaction(SIGINT,  &sigact, 0); /*  catch interrupt signal CTRL+C */
+    //sigaction(SIGSEGV, &sigact, 0); /*  catch segmentation faults  */
+    sigaction(SIGPIPE, &sigact, 0); /*  catch broken pipe */
+#if 0
+    sigaction(SIGCHLD, &sigact, 0); /*  catch child process return */
+    sigaction(SIGUSR2, &sigact, 0); /*  catch USER signal */ 
+#endif
+}
+
+
+/* ****************************************************************************
+ * FunctionName: daemonize
+ * Description : Set the programe runs as daemon in background
+ * Inputs      : nodir: DON'T change the work directory to / :  1:NoChange 0:Change
+ *               noclose: close the opened file descrtipion or not 1:Noclose 0:Close
+ * Output      : NONE
+ * Return      : NONE
+ * *****************************************************************************/
+void daemonize(int nochdir, int noclose)
+{ 
+    int retval, fd; 
+    int i; 
+    
+    /*  already a daemon */ 
+    if (1 == getppid()) 
+        return; 
+    
+    /*  fork error */
+    retval = fork(); 
+    if (retval < 0) exit(1); 
+    
+    /*  parent process exit */
+    if (retval > 0)
+        exit(0); 
+    
+    /*  obtain a new process session group */
+    setsid(); 
+    
+    if (!noclose)
+    {
+        /*  close all descriptors */
+        for (i = getdtablesize(); i >= 0; --i)
+        {
+            //if (i != g_logPtr->fd)
+                close(i);
+        } 
+
+        /*  Redirect Standard input [0] to /dev/null */
+        fd = open("/dev/null", O_RDWR); 
+
+        /* Redirect Standard output [1] to /dev/null */
+        dup(fd);  
+
+        /* Redirect Standard error [2] to /dev/null */
+        dup(fd);  
+    } 
+    
+    umask(0); 
+    
+    if (!nochdir)
+        chdir("/"); 
+    
+    return;
+}
+
+/* ****************************************************************************
+ * FunctionName: record_daemon_pid
+ * Description : Record the running daemon program PID to the file "pid_file"
+ * Inputs      : pid_file:The record PID file path
+ * Output      : NONE
+ * Return      : 0: Record successfully  Else: Failure
+ * *****************************************************************************/
+int record_daemon_pid(const char *pid_file)
+{ 
+    struct stat fStatBuf; 
+    int fd = -1; 
+    int mode = S_IROTH | S_IXOTH | S_IRGRP | S_IXGRP | S_IRWXU;
+    char ipc_dir[64] = { 0 }; 
+    
+    strncpy(ipc_dir, pid_file, 64); 
+
+    /* dirname() will modify ipc_dir and save the result */ 
+    dirname(ipc_dir);  
+    
+    /* If folder pid_file PATH doesnot exist, then we will create it" */
+    if (stat(ipc_dir, &fStatBuf) < 0) 
+    { 
+        if (mkdir(ipc_dir, mode) < 0) 
+        { 
+            log_fatal("cannot create %s: %s\n", ipc_dir, strerror(errno)); 
+            return -1; 
+        } 
+        
+        (void)chmod(ipc_dir, mode); 
+    } 
+    
+    /*  Create the process running PID file */ 
+    mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
+    if ((fd = open(pid_file, O_RDWR | O_CREAT | O_TRUNC, mode)) >= 0)
+    {
+        char pid[PID_ASCII_SIZE]; 
+        snprintf(pid, sizeof(pid), "%u\n", (unsigned)getpid()); 
+        write(fd, pid, strlen(pid)); 
+        close(fd); 
+
+        log_dbg("Record PID<%u> to file %s.\n", getpid(), pid_file);
+    } 
+    else 
+    {
+        log_fatal("cannot create %s: %s\n", pid_file, strerror(errno));
+        return -1;
+    }
+
+    return 0;
+}
+
+/* ****************************************************************************
+ * FunctionName: get_daemon_pid
+ * Description : Get the daemon process PID from the PID record file "pid_file"
+ * Inputs      : pid_file: the PID record file
+ * Output      : NONE
+ * Return      : pid_t: The daemon process PID number
+ * *****************************************************************************/
+pid_t get_daemon_pid(const char *pid_file)
+{ 
+    FILE *f; 
+    pid_t pid; 
+    
+    if ((f = fopen(pid_file, "rb")) != NULL)
+    { 
+        char pid_ascii[PID_ASCII_SIZE]; 
+        (void)fgets(pid_ascii, PID_ASCII_SIZE, f); 
+        (void)fclose(f); 
+        pid = atoi(pid_ascii); 
+    } 
+    else
+    {
+        log_fatal("Can't open PID record file %s: %s\n", pid_file, strerror(errno));
+        return -1;
+    } 
+    return pid;
+}     
+
+/* ****************************************************************************
+ * FunctionName: check_daemon_running
+ * Description : Check the daemon program already running or not
+ * Inputs      : pid_file: The record running daemon program PID
+ * Output      : NONE
+ * Return      : 1: The daemon program alread running   0: Not running
+ * *****************************************************************************/
+int check_daemon_running(const char *pid_file)
+{
+    int retVal = -1; 
+    struct stat fStatBuf;
+
+    retVal = stat(pid_file, &fStatBuf); 
+    if (0 == retVal) 
+    { 
+        pid_t pid = -1; 
+        printf("PID record file \"%s\" exist.\n", pid_file);
+
+        pid = get_daemon_pid(pid_file);
+        if (pid > 0)  /*  Process pid exist */
+        { 
+            if ((retVal = kill(pid, 0)) == 0) 
+            { 
+                printf("Program with PID[%d] seems running.\n", pid); 
+                return 1; 
+            } 
+            else   /* Send signal to the old process get no reply. */ 
+            { 
+                printf("Program with PID[%d] seems exit.\n", pid); 
+                remove(pid_file); 
+                return 0; 
+            } 
+        } 
+        else if (0 == pid) 
+        { 
+            printf("Can not read program PID form record file.\n"); 
+            remove(pid_file); 
+            return 0; 
+        } 
+        else  /* Read pid from file "pid_file" failure */
+        { 
+            printf("Read record file \"%s\" failure, maybe program still running.\n", pid_file); 
+            return 1; 
+        } 
+    } 
+    
+    return 0;
+}
+
+/* ****************************************************************************
+ * FunctionName: set_daemon_running
+ * Description : Set the programe running as daemon if it's not running and record 
+ *               its PID to the pid_file.
+ * Inputs      : pid_file: The record running daemon program PID
+ * Output      : NONE
+ * Return      : 0: Successfully. 1: Failure
+ * *****************************************************************************/
+int set_daemon_running(const char *pid_file)
+{ 
+    daemonize(0, 1); 
+    log_nrml("Program running as daemon [PID:%d].\n", getpid()); 
+    
+    if (record_daemon_pid(pid_file) < 0) 
+    { 
+        log_fatal("Record PID to file \"%s\" failure.\n", pid_file); 
+        return -2;
+    }
+
+    return 0;
+}
+
+
+int thread_start(pthread_t * thread_id, THREAD_BODY * thread_workbody, void *thread_arg)
+{
+    int        retval = 0;
+
+    pthread_attr_t thread_attr; 
+
+    /* Initialize the thread  attribute */
+    retval = pthread_attr_init(&thread_attr); 
+    if(retval)
+        return -1;
+
+    /* Set the stack size of the thread */
+    retval = pthread_attr_setstacksize(&thread_attr, 120 * 1024); 
+    if(retval)
+        goto CleanUp;
+    
+    /* Set thread to detached state:Don`t need pthread_join */
+    retval = pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED); 
+    if(retval)
+        goto CleanUp;
+    
+    /* Create the thread */
+    retval = pthread_create(thread_id, &thread_attr, thread_workbody, thread_arg);
+    if(retval)
+        goto CleanUp;
+    
+CleanUp:
+    /* Destroy the  attributes  of  thread */
+    pthread_attr_destroy(&thread_attr); 
+    return retval;
+}
+
+
+void exec_system_cmd(const char *format, ...)
+{
+    char                cmd[256];
+    va_list             args;
+    //int                 done = 0; 
+    
+    memset(cmd, 0, sizeof(cmd)); 
+    
+    va_start(args, format); 
+    //done = vsnprintf(cmd, sizeof(cmd), format, args);
+    vsnprintf(cmd, sizeof(cmd), format, args);
+    va_end(args); 
+    
+    system(cmd);
+}
+
+
diff --git a/monitord/cp_proc.h b/monitord/cp_proc.h
new file mode 100644
index 0000000..f79abe8
--- /dev/null
+++ b/monitord/cp_proc.h
@@ -0,0 +1,42 @@
+/********************************************************************************
+ *      Copyright:  (C) 2012 Guo Wenxue<guowenxue@gmail.com>
+ *                  All rights reserved.
+ *
+ *       Filename:  cp_proc.h
+ *    Description:  This head file is for Linux process API
+ *
+ *        Version:  1.0.0(11/06/2012~)
+ *         Author:  Guo Wenxue <guowenxue@gmail.com>
+ *      ChangeLog:  1, Release initial version on "11/06/2012 09:21:33 PM"
+ *                 
+ ********************************************************************************/
+
+#ifndef __CP_PROC_H
+#define __CP_PROC_H
+
+#include <signal.h>
+
+#define PID_ASCII_SIZE  11
+
+typedef struct __CP_PROC_SIG
+{
+    int       signal;
+    unsigned  stop;     /* 0: Not term  1: Stop  */
+}  CP_PROC_SIG;
+
+typedef void *(THREAD_BODY) (void *thread_arg);
+
+extern CP_PROC_SIG     g_cp_signal;
+extern void cp_install_proc_signal(void);
+
+extern void daemonize(int nochdir, int noclose);
+extern int record_daemon_pid(const char *pid_file);
+extern pid_t get_daemon_pid(const char *pid_file);
+extern int check_daemon_running(const char *pid_file);
+extern int set_daemon_running(const char *pid_file);
+
+extern void exec_system_cmd(const char *format, ...);
+
+extern int thread_start(pthread_t * thread_id, THREAD_BODY * thread_workbody, void *thread_arg);
+
+#endif
diff --git a/monitord/cp_socket.c b/monitord/cp_socket.c
new file mode 100644
index 0000000..7773281
--- /dev/null
+++ b/monitord/cp_socket.c
@@ -0,0 +1,357 @@
+/*********************************************************************************
+ *      Copyright:  (C) 2014 Guo Wenxue<guowenxue@gmail.com>
+ *                  All rights reserved.
+ *
+ *       Filename:  cp_socket.c
+ *    Description:  This file 
+ *                 
+ *        Version:  1.0.0(11/18/2014)
+ *         Author:  Guo Wenxue <guowenxue@gmail.com>
+ *      ChangeLog:  1, Release initial version on "11/18/2014 11:15:04 PM"
+ *                 
+ ********************************************************************************/
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <sys/un.h>
+#include <sys/types.h>
+#include <linux/sockios.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include "cp_logger.h"
+#include "cp_socket.h"
+
+int cp_sock_block_connect(cp_socket_t *sock, char *servaddr, unsigned short servport)
+{
+    int                 rv = -1;
+    int                 sock_fd = -1;
+    char                service[20];
+    struct addrinfo     hints, *rp;
+    struct addrinfo     *res = NULL;
+    struct in_addr      inaddr;
+    char                ipstr[20];
+    int                 len;
+
+    if(!sock || !servaddr || !servport )
+    {
+        log_err("Invalid input argument\n");
+        return -1;
+    }
+
+    if(SOCK_STAT_CONNECTED == sock->status)
+    {
+        return 0;
+    }
+
+    len = strlen(servaddr);
+    len = len>DOMAIN_MAX_LEN ? DOMAIN_MAX_LEN : len;
+
+    memcpy(sock->servaddr, servaddr, strlen(servaddr));
+    sock->servport = servport;
+
+    log_nrml("Start socket connect to [%s:%d]...\n", sock->servaddr, sock->servport);
+
+    memset(&hints, 0, sizeof(struct addrinfo));
+    hints.ai_family = AF_INET; /*   Only support IPv4 */
+    hints.ai_socktype = SOCK_STREAM;
+
+    /*  If Hostname is a valid IP address, then don't use name resolution */
+    if( inet_aton(sock->servaddr, &inaddr) )
+    {
+        log_info("%s is a valid IP address, don't use name resolution.\n", sock->servaddr);
+        hints.ai_flags |= AI_NUMERICHOST;
+    }  
+
+    /*  Obtain address(es) matching servaddr/servport */
+    snprintf(service, sizeof(service), "%d", sock->servport);
+    if( (rv=getaddrinfo(sock->servaddr, service, &hints, &res)) )
+    {
+        log_err("getaddrinfo() parser [%s:%s] failed: %s\n", sock->servaddr, service, gai_strerror(rv));
+        rv = -2;
+        goto out;
+    }   
+
+    /*  getaddrinfo() returns a list of address structures. Try each address until connected */
+    rv = -3; /* default return value set be connect failure  */
+    sock->status = SOCK_STAT_DISCONNECT;
+    for (rp=res; rp!=NULL; rp=rp->ai_next)
+    {
+        /*  create the socket */ 
+        sock_fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); 
+        if( sock_fd < 0) 
+        { 
+            log_err("socket() create failed: %s\n", strerror(errno));
+            rv = -4;
+            continue;
+        }
+
+        inet_ntop(AF_INET, &(((struct sockaddr_in *)(rp->ai_addr))->sin_addr), ipstr, sizeof(ipstr));
+        log_dbg("DNS resolve IP address [%s]\n", ipstr);
+        
+        /* connect to the remote server successfully  */
+        if(0==connect(sock_fd, rp->ai_addr, rp->ai_addrlen))
+        {
+            memcpy(&sock->saddr, &rp->ai_addr, sizeof(sock->saddr));
+            sock->fd = sock_fd;
+            sock->status = SOCK_STAT_CONNECTED;
+            rv = 0;
+            goto out;
+        }
+        else /* Connect to server failed. */
+        {
+            rv = -5;
+            log_err("connect() to server IP[%s] failed: %s\n", ipstr, strerror(errno));
+        }
+
+        close(sock_fd);
+    }
+
+
+out:
+    if( rv < 0 )
+    {
+        log_err("create socket connect to [%s:%d] failed: %s\n", sock->servaddr, sock->servport, strerror(errno));
+        sock->status = SOCK_STAT_DISCONNECT;
+        sock->fd = -1;
+    }
+    else
+    {
+        log_nrml("create socket connect to [%s:%d] successfully\n", sock->servaddr, sock->servport);
+        sock->status = SOCK_STAT_CONNECTED;
+    }
+
+    if(res)
+    {
+        freeaddrinfo(res); 
+    }
+
+    return rv;
+}
+
+int cp_sock_nonblock_connect(cp_socket_t *sock, char *servaddr, unsigned short servport)
+{
+    int                 rv = -1;
+    int                 sock_fd = -1;
+    char                service[20];
+    struct addrinfo     hints, *rp;
+    struct addrinfo     *res = NULL;
+    struct in_addr      inaddr;
+    char                ipstr[20];
+
+    if( !sock || !servaddr || !servport )
+    {
+        log_err("Invalid input argument\n");
+        return -1;
+    }
+
+    if(SOCK_STAT_CONNECTED == sock->status)
+    {
+        return 0;
+    }
+    else if(SOCK_STAT_CONNECTING == sock->status)
+    {
+        goto connecting;
+    }
+
+    log_nrml("Start socket connect to [%s:%d]...\n", sock->servaddr, sock->servport);
+
+    memset(&hints, 0, sizeof(struct addrinfo));
+    hints.ai_family = AF_INET; /*   Only support IPv4 */
+    hints.ai_socktype = SOCK_STREAM;
+
+    /*  If Hostname is a valid IP address, then don't use name resolution */
+    if( inet_aton(sock->servaddr, &inaddr) )
+    {
+        log_info("%s is a valid IP address, don't use name resolution.\n", sock->servaddr);
+        hints.ai_flags |= AI_NUMERICHOST;
+    }  
+
+    /*  Obtain address(es) matching servaddr/servport */
+    snprintf(service, sizeof(service), "%d", sock->servport);
+    if( (rv=getaddrinfo(sock->servaddr, service, &hints, &res)) )
+    {
+        log_err("getaddrinfo() parser [%s:%s] failed: %s\n", sock->servaddr, service, gai_strerror(rv));
+        rv = -2;
+        goto failed;
+    }   
+
+
+    /*  getaddrinfo() returns a list of address structures. Try each 
+     *  address until we successfully connect or bind 
+     */
+    rv = -3; /* Connect failure  */
+    for (rp=res; rp!=NULL; rp=rp->ai_next)
+    {
+        /*  Create the socket */ 
+        sock_fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); 
+        if( sock_fd < 0) 
+        { 
+            log_err("socket() create failed: %s\n", strerror(errno));
+            rv = -4;
+            continue;
+        }
+
+        inet_ntop(AF_INET, &(((struct sockaddr_in *)(rp->ai_addr))->sin_addr), ipstr, sizeof(ipstr));
+        log_dbg("DNS resolve IP address [%s]\n", ipstr);
+        
+        cp_sock_set_nonblock(sock_fd);
+
+        /* Nono block Connect to the remote server */
+        if(0==connect(sock_fd, rp->ai_addr, rp->ai_addrlen))
+        {
+            /* Conenct to server successfully */
+            memcpy(&sock->saddr, &rp->ai_addr, sizeof(sock->saddr));
+            sock->fd = sock_fd;
+            sock->status = SOCK_STAT_CONNECTED;
+            rv = 0;
+            goto connected;
+        }
+        else
+        {
+            if(EINPROGRESS == errno)
+            {
+                /* Connect to server now in progress  */
+                memcpy(&sock->saddr, &rp->ai_addr, sizeof(sock->saddr));
+                sock->fd = sock_fd;
+                sock->status = SOCK_STAT_CONNECTING; 
+                rv = 0; 
+                goto connecting;
+            }
+            else
+            {
+                /* Connect to server failed. */
+                close(sock_fd);
+                rv = -5;
+                log_err("connect() to server failed: %s\n", strerror(errno));
+                goto failed;
+            }
+        }
+
+        close(sock_fd);
+    }
+
+
+failed:
+    log_err("create socket connect to [%s:%d] failed: %s\n", sock->servaddr, sock->servport, strerror(errno));
+    sock->status = SOCK_STAT_DISCONNECT;
+    sock->fd = -1;
+    return rv;
+
+connecting:
+    if(SOCK_STAT_CONNECTING == sock->status)
+    {
+        int         len;
+
+        len = sizeof(sock->saddr);
+
+        errno = 0;
+        if( 0 == connect(sock->fd, &sock->saddr, len) )
+        {
+            /* connect() return 0 means it already connected */
+            sock->status = SOCK_STAT_CONNECTED;
+            rv = 0;
+            goto connected;
+        }
+
+        /* Connect failure will continue to check */
+        switch (errno)
+        {
+            case EISCONN:
+                sock->status = SOCK_STAT_CONNECTED;
+                rv = 0;
+                goto connected;
+
+            case EALREADY:
+            case EINPROGRESS:
+                log_dbg("socket[%d] connect to remote [%s:%d] in progress\n", sock->fd, sock->servaddr, sock->servport);
+                rv = 0;
+                goto cleanup;
+
+            default:
+                log_err("socket[%d] connect to remote [%s:%d] failed: %s\n", sock->fd, sock->servaddr, sock->servport, strerror(errno));
+                sock->status = SOCK_STAT_DISCONNECT;
+                rv = -7;
+                break;
+        }
+    }
+
+connected:
+    if(SOCK_STAT_CONNECTED == sock->status)
+    {
+        rv = 0;
+        log_nrml("socket[%d] connected to remote server [%s:%d]\n", sock->fd, sock->servaddr, sock->servport);
+        goto cleanup;
+    }
+
+cleanup:
+    if(res)
+        freeaddrinfo(res);  /* No longer needed */
+
+    return rv;
+}
+
+
+int cp_sock_set_nonblock(int sockfd)
+{
+    int opts;
+    /*
+     * fcntl may set: 
+     *
+     * EACCES, EAGAIN: Operation is prohibited by locks held by other 
+     *          processes. Or, operation is prohibited because the file has 
+     *          been memory-mapped by another process. 
+     * EBADF:   fd is not an open file descriptor, or the command was F_SETLK 
+     *          or F_SETLKW and the file descriptor open mode doesn't match 
+     *          with the type of lock requested.
+     * EDEADLK: It was detected that the specified F_SETLKW command would 
+     *          cause a deadlock.
+     * EFAULT:  lock is outside your accessible address space.
+     * EINTR:   For F_SETLKW, the command was interrupted by a signal. For 
+     *          F_GETLK and F_SETLK, the command was interrupted by a signal 
+     *          before the lock was checked or acquired. Most likely when 
+     *          locking a remote file (e.g. locking over NFS), but can 
+     *          sometimes happen locally.
+     * EINVAL:  For F_DUPFD, arg is negative or is greater than the maximum 
+     *          allowable value. For F_SETSIG, arg is not an allowable signal 
+     *          number.
+     * EMFILE:  For F_DUPFD, the process already has the maximum number of 
+     *          file descriptors open. 
+     * ENOLCK:  Too many segment locks open, lock table is full, or a remote 
+     *          locking protocol failed (e.g. locking over NFS).
+     * EPERM:   Attempted to clear the O_APPEND flag on a file that has the 
+     *          append-only attribute set.
+     */
+    opts = fcntl(sockfd, F_GETFL);
+    if (opts < 0)
+    {
+        log_warn("fcntl() get socket options failure: %s\n", strerror(errno));
+        return -1;
+    }
+
+    opts |= O_NONBLOCK;
+    if (fcntl(sockfd, F_SETFL, opts) < 0)
+    {
+        log_warn("fcntl() set socket options failure: %s\n", strerror(errno));
+        return -1;
+    }
+
+    log_dbg("Set socket[%d] none blocking\n", sockfd);
+    return opts;
+}
+
+
+
+void cp_sock_close(cp_socket_t *sock)
+{
+    close(sock->fd);
+    sock->fd = 0;
+    sock->status = SOCK_STAT_INIT;
+}
+
diff --git a/monitord/cp_socket.h b/monitord/cp_socket.h
new file mode 100644
index 0000000..ada48c1
--- /dev/null
+++ b/monitord/cp_socket.h
@@ -0,0 +1,65 @@
+/********************************************************************************
+ *      Copyright:  (C) 2014 Guo Wenxue<guowenxue@gmail.com>
+ *                  All rights reserved.
+ *
+ *       Filename:  cp_socket.h
+ *    Description:  This head file 
+ *
+ *        Version:  1.0.0(11/19/2014)
+ *         Author:  Guo Wenxue <guowenxue@gmail.com>
+ *      ChangeLog:  1, Release initial version on "11/19/2014 12:16:45 AM"
+ *                 
+ ********************************************************************************/
+#ifndef __CP_SOCKET_H_
+#define __CP_SOCKET_H_
+
+#include <sys/types.h> 
+#include <sys/socket.h>
+
+#define DOMAIN_MAX_LEN             128
+
+#define SOCK_STAT_INIT             0
+#define SOCK_STAT_CONNECTING       1
+#define SOCK_STAT_CONNECTED        2
+#define SOCK_STAT_DISCONNECT       3
+
+typedef struct cp_socket_s 
+{
+    char               servaddr[DOMAIN_MAX_LEN];      /*  connect server hostname or IP address */
+    unsigned short     servport;                      /*  connect server port  */
+    int                fd;                            /*  socket fd  */ 
+    struct sockaddr    saddr;                         /*  sockaddr for none-block connect */ 
+    unsigned char      status;                        /*  socket connect status: 0:disconnect 1:connecting 2:connected  */
+} cp_socket_t;
+
+
+/* Description: create socket object and connect to server in block mode
+ * $sock:       socket object, if it's NULL will be malloced.
+ * $servaddr:   connect server hostname or IP address
+ * $servport:   connect to server port
+ *
+ * Return:      socket object address
+ */
+extern int cp_sock_block_connect(cp_socket_t *sock, char * servaddr, unsigned short servport);
+
+
+/* Description: set socket to none block mode  */
+extern int cp_sock_set_nonblock(int sockfd);
+
+/* Description: create socket object and connect to server in none block mode
+ * $sock:       socket object, if it's NULL will be malloced.
+ * $servaddr:   connect server hostname or IP address
+ * $servport:   connect to server port
+ *
+ * Return:      0: connecting or connected  <0: connect failure 
+ */
+
+extern int cp_sock_nonblock_connect(cp_socket_t *sock, char * servaddr, unsigned short servport);
+
+
+/* Description: close socket  */
+extern void cp_sock_close(cp_socket_t *sock);
+
+
+#endif
+
diff --git a/monitord/makefile b/monitord/makefile
new file mode 100644
index 0000000..684dac6
--- /dev/null
+++ b/monitord/makefile
@@ -0,0 +1,68 @@
+#*********************************************************************************
+#      Copyright:  (C) 2012 Guo Wenxue<Email:guowenxue@gmail.com QQ:281143292>
+#                  All rights reserved.
+#
+#       Filename:  Makefile
+#    Description:  This Makefile used to compile all the C source code file in current 
+#                  folder to one excutable binary files.
+#                      
+#        Version:  1.0.0(10/08/2011~)
+#                  Author:  Guo Wenxue <guowenxue@gmail.com>
+#      ChangeLog:  1, Release initial version on "11/11/2011 01:29:33 PM"
+#                       
+#********************************************************************************/
+
+PWD=$(shell pwd)
+INSTPATH=/usr/bin
+
+CFLAGS+=-I${PWD}
+#CFLAGS+=-Wall -Werror
+
+LDFLAGS+=-lwiringPi
+LDFLAGS+=-lpthread
+
+VPATH= .
+SRCS = $(wildcard ${VPATH}/*.c)
+OBJS = $(patsubst %.c,%.o,$(SRCS))
+
+#CC=arm-linux-
+export CC=${CROSS_COMPILE}gcc
+export CXX=${CROSS_COMPILE}g++
+export AR=${CROSS_COMPILE}ar
+export AS=${CROSS_COMPILE}as
+export RANLIB=${CROSS_COMPILE}ranlib
+export STRIP=${CROSS_COMPILE}strip
+export CFLAGS
+export LDFLAGS
+
+SRCFILES = $(wildcard *.c)
+IMAGE_NAME=$(shell basename ${PWD})
+
+all: entry binary
+entry: 
+	@echo " ";
+	@echo " =========================================================";
+	@echo " **        Compile \"${BINARIES}\" for ${ARCH}         ";
+	@echo " =========================================================";
+
+binary:  ${SRCFILES}
+	$(CC) $(CFLAGS) -o ${IMAGE_NAME} $^  ${LDFLAGS}
+	@echo " Compile over"
+
+tag: 
+	@ctags --c-kinds=+defglmnstuvx --langmap=c:.c.h.ho.hem.het.hec.hev.him.hit.hic.hiv -R .  
+	@cscope -Rbq
+
+install:
+	@cp $(IMAGE_NAME) ${INSTPATH}
+
+clean: 
+	@rm -f version.h 
+	@rm -f *.o $(IMAGE_NAME) 
+	@rm -rf *.gdb *.a *.so *.elf*
+
+distclean: clean
+	@rm -f  tags cscope*
+
+.PHONY: clean entry
+
diff --git a/monitord/monitord.c b/monitord/monitord.c
new file mode 100644
index 0000000..f786fd0
--- /dev/null
+++ b/monitord/monitord.c
@@ -0,0 +1,186 @@
+/*********************************************************************************
+ *      Copyright:  (C) 2018 LingYun IoT System Studio
+ *                  All rights reserved.
+ *
+ *       Filename:  monitord.c
+ *    Description:  This file is the monitord program, which use infrared to detect human 
+ *                  incoming, then turn on the LED by relay and take a photo for it.
+ *                 
+ *        Version:  1.0.0(2018年05月29日)
+ *         Author:  Guo Wenxue <guowenxue@gmail.com>
+ *      ChangeLog:  1, Release initial version on "2018年05月29日 21时03分54秒"
+ *                 
+ ********************************************************************************/
+
+#include <unistd.h>
+#include <libgen.h>
+#include <getopt.h>
+#include "monitord.h"
+#include "cp_logger.h"
+#include "cp_proc.h"
+
+
+/* Show program version information, can used by 'monitord --version or monitord -v'*/
+static inline void prog_version(const char *progname)
+{
+    printf("%s Version 1.0.0 Build(%s)\n", progname, __DATE__);
+    return ;
+}
+
+
+/* Show program help information, can used by 'monitord --help or monitord -h'*/
+static void prog_usage(const char *progname)
+{
+    prog_version(progname);
+    
+    printf("Usage: %s [OPTION]...\n", progname);
+    printf("Receive date from a serial port and transfer the data to remote server by socket.\n");
+    printf("\nMandatory arguments to long options are mandatory for short options too:\n");
+
+    printf(" -d[debug   ]  Running in debug mode\n");
+    printf(" -l[level   ]  Set the log level as [0..%d]\n", LOG_LEVEL_MAX-1);
+    printf(" -s[server  ]  Socket connect server host and port, format as: Hostname:Port, default as 127.0.0.1:8900\n");
+
+    printf(" -v[version ]  Display program version\n");
+    printf(" -h[help    ]  Display this help information\n");
+    return ;
+}
+
+void *infrared_worker(void *arg);
+
+int main (int argc, char **argv)
+{
+    const char             *progname=NULL;
+
+    int                    opt;
+    int                    debug = 0;            /* program running information log to stdard output */
+    char                   pid_file[64] = { 0 }; /*   The file used to record the PID */
+    int                    log_level = LOG_LEVEL_TRACE;  /* program running information log to file level  */
+    cp_logger             *logger;
+    char                  *log_file="monitord.log";        /* program running information log file name  */
+
+    char                  *server="127.0.0.1:8900";    /* default connect server address, can use '-s' option to change */
+
+    int                    rv;
+    pthread_t              tid;
+
+    /* progranm command options  */
+    struct option long_options[] = { 
+        {"debug", no_argument, NULL, 'd'},          /* monitord -d or monitord --debug, log to standard output or not */
+        {"level", required_argument, NULL, 'l'},    /* monitord -l 7, specify log to file level */
+        {"server", required_argument, NULL, 's'},   /* monitord -s 192.168.0.5:9999, specify server address and port */
+        {"version", no_argument, NULL, 'v'},        /* monitord -v or monitord --version to check program version information */
+        {"help", no_argument, NULL, 'h'},           /* monitord -h or monitord --help to get program help information  */
+        {NULL, 0, NULL, 0}                          /* array end flag */
+    }; 
+
+
+    progname = basename(argv[0]);
+
+    /* Parser the command line options */
+    while ((opt = getopt_long(argc, argv, "s:dl:vh", long_options, NULL)) != -1)
+    {
+        switch (opt)
+        {
+            case 'd': /* monitord -d or monitord --debug */
+                debug = 1;
+                log_file = DBG_LOG_FILE;
+                break;
+
+            case 'l': /* monitord -l 7 */
+                rv = atoi(optarg);
+                log_level = rv>LOG_LEVEL_MAX ? LOG_LEVEL_MAX-1 : rv;
+                break;
+
+            case 'v':  /* monitord -v */
+                prog_version(progname); 
+                return EXIT_SUCCESS;
+
+            case 'h':  /* monitord -h */
+                prog_usage(progname);
+                return 0;
+
+            default:
+                break;
+        } /*  end of "switch(opt)" */
+    }
+
+
+    /* parser hostname and port by server*/
+    {
+        char       *ptr;
+
+        ptr=strchr(server, ':');
+        if( !ptr )
+        {
+            printf("Invalid server host[%s], which format should be [HostName:Port] such as \"127.0.0.1:8900\"", server);
+            return -1;
+        }
+    }
+
+    
+
+    /* check program already running on background or not */
+    if( !debug )
+    {   
+        snprintf(pid_file, sizeof(pid_file), "/var/run/%s.pid", progname);
+        if( check_daemon_running(pid_file) )
+        {   
+            printf("Programe already running, exit now.\n");
+            return -1; 
+        }   
+    }
+    
+    /* initialise logger system  */
+    if( !(logger=cp_log_init(NULL, log_file, log_level, 0)) || cp_log_open()<0  )
+    {
+        printf("Init logger system failed, program exit now...\n");
+        return -1;
+    }
+    /* set program running in background */
+    if( !debug )
+    {
+        if( set_daemon_running(pid_file) )
+        {
+            log_fatal("Set program \"%s\" running as daemon failure.\n", progname);
+            return -2;
+        }
+    }
+
+    /* install signal process handler  */
+    cp_install_proc_signal();
+
+    /* start infrared detected thread */
+    thread_start(&tid, infrared_worker, NULL); 
+    
+    while( !g_cp_signal.stop )
+    {
+        /* control/main thread do nothing here  */
+        sleep(1);
+    }
+
+    return 0;
+} 
+
+void *infrared_worker(void *arg)
+{
+    int                    rv = 0;
+
+#if 0
+    if( !arg ) 
+    {
+        log_err("Invalid arguments\n");
+        return NULL;
+    }
+#endif
+
+    log_nrml("Thread worker for infrared start\n");
+
+    while( !g_cp_signal.stop )
+    {
+    }
+
+    return NULL;
+}
+
+
diff --git a/monitord/monitord.h b/monitord/monitord.h
new file mode 100644
index 0000000..24b8f70
--- /dev/null
+++ b/monitord/monitord.h
@@ -0,0 +1,18 @@
+/********************************************************************************
+ *      Copyright:  (C) 2018 LingYun IoT System Studio
+ *                  All rights reserved.
+ *
+ *       Filename:  monitord.h
+ *    Description:  This head file 
+ *
+ *        Version:  1.0.0(2018年05月29日)
+ *         Author:  Guo Wenxue <guowenxue@gmail.com>
+ *      ChangeLog:  1, Release initial version on "2018年05月29日 21时05分43秒"
+ *                 
+ ********************************************************************************/
+
+#ifndef  _MONITORD_H_
+#define  _MONITORD_H_
+
+
+#endif   /* ----- #ifndef _MONITORD_H_  ----- */
diff --git a/mqttd/ds18b20.c b/mqttd/ds18b20.c
new file mode 100644
index 0000000..2aa9116
--- /dev/null
+++ b/mqttd/ds18b20.c
@@ -0,0 +1,105 @@
+/*********************************************************************************
+ *      Copyright:  (C) 2018 LingYun IoT System Studio
+ *                  All rights reserved.
+ *
+ *       Filename:  ds18b20.c
+ *    Description:  This file is temperature sensor DS18B20 code
+ *                 
+ *        Version:  1.0.0(2018/10/14)
+ *         Author:  Guo Wenxue <guowenxue@gmail.com>
+ *      ChangeLog:  1, Release initial version on "2018/10/14 12:13:26"
+ *                 
+ ********************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <string.h>
+#include <time.h>
+#include <errno.h>
+
+/* File Content:
+   pi@raspberrypi:~/guowenxue $ cat /sys/bus/w1/devices/28-041731f7c0ff/w1_slave 
+   3a 01 4b 46 7f ff 0c 10 a5 : crc=a5 YES
+   3a 01 4b 46 7f ff 0c 10 a5 t=19625
+ */
+
+int ds18b20_get_temperature(float *temp)
+{
+    char            w1_path[50] = "/sys/bus/w1/devices/";
+    char            chip[20];
+    char            buf[128];
+    DIR            *dirp;
+    struct dirent  *direntp;
+    int             fd =-1;
+    char           *ptr;
+    float           value;
+    int             found = 0;
+
+    if( !temp )
+    {
+            return -1;
+    }
+
+    /*+-------------------------------------------------------------------+
+     *|  open dierectory /sys/bus/w1/devices to get chipset Serial Number |
+     *+-------------------------------------------------------------------+*/
+    if((dirp = opendir(w1_path)) == NULL)
+    {
+        printf("opendir error: %s\n", strerror(errno));
+        return -2;
+    }
+
+    while((direntp = readdir(dirp)) != NULL)
+    {
+        if(strstr(direntp->d_name,"28-"))
+        {
+            /* find and get the chipset SN filename */
+            strcpy(chip,direntp->d_name);
+            found = 1;
+	    break;
+        }
+    }
+    closedir(dirp);
+
+    if( !found )
+    {
+            printf("Can not find ds18b20 in %s\n", w1_path);
+            return -3;
+    }
+
+    /* get DS18B20 sample file full path: /sys/bus/w1/devices/28-xxxx/w1_slave */
+    strncat(w1_path, chip, sizeof(w1_path)-strlen(w1_path));
+    strncat(w1_path, "/w1_slave", sizeof(w1_path)-strlen(w1_path));
+
+    /* open file /sys/bus/w1/devices/28-xxxx/w1_slave to get temperature */
+    if( (fd=open(w1_path, O_RDONLY)) < 0 ) 
+    { 
+            printf("open %s error: %s\n", w1_path, strerror(errno)); 
+            return -4;
+    } 
+    
+    if(read(fd, buf, sizeof(buf)) < 0)
+    {
+            printf("read %s error: %s\n", w1_path, strerror(errno)); 
+            return -5;
+    } 
+    
+    ptr = strstr(buf, "t=");
+    if( !ptr )
+    {
+            printf("ERROR: Can not get temperature\n");
+            return -6;
+    }
+
+    ptr+=2;
+
+    /* convert string value to float value */
+    *temp = atof(ptr)/1000;
+   
+    close(fd);
+
+    return 0;
+}
diff --git a/mqttd/ds18b20.h b/mqttd/ds18b20.h
new file mode 100644
index 0000000..6c019f6
--- /dev/null
+++ b/mqttd/ds18b20.h
@@ -0,0 +1,19 @@
+/*********************************************************************************
+ *      Copyright:  (C) 2018 LingYun IoT System Studio
+ *                  All rights reserved.
+ *
+ *       Filename:  ds18b20.c
+ *    Description:  This file is temperature sensor DS18B20 code
+ *                 
+ *        Version:  1.0.0(2018/10/14)
+ *         Author:  Guo Wenxue <guowenxue@gmail.com>
+ *      ChangeLog:  1, Release initial version on "2018/10/14 12:13:26"
+ *                 
+ ********************************************************************************/
+
+#ifndef __DS18B20_H
+#define __DS18B20_H
+
+extern int ds18b20_get_temperature(float *temp);
+
+#endif
diff --git a/mqttd/led.c b/mqttd/led.c
new file mode 100644
index 0000000..23a4181
--- /dev/null
+++ b/mqttd/led.c
@@ -0,0 +1,60 @@
+/*********************************************************************************
+ *      Copyright:  (C) 2018 LingYun IoT System Studio
+ *                  All rights reserved.
+ *
+ *       Filename:  led.c
+ *    Description:  This file is used to control RGB 3-colours LED
+ *
+ *     pi@raspberrypi:~ $ gpio readall show BCM and wPi pinmap  
+ *
+ *                 LED      BCM           wPi 
+ *                  G ---- GPIO.13  ---- GPIO.23
+ *                  R ---- GPIO.19  ---- GPIO.24    
+ *                  B ---- GPIO.26  ---- GPIO.25
+ *                  I ---- GND      ----
+ *                 
+ *        Version:  1.0.0(2018/10/14)
+ *         Author:  Guo Wenxue <guowenxue@gmail.com>
+ *      ChangeLog:  1, Release initial version on "2018/10/14 12:13:26"
+ *                 
+ ********************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <string.h>
+#include <time.h>
+#include <errno.h>
+
+#include <wiringPi.h>
+#include "led.h"
+
+void init_led(void)
+{
+	int         i;
+
+    wiringPiSetup();
+
+	for(i=0; i<LED_MAX; i++)
+	{
+	       	pinMode( led_gpio[i], OUTPUT );
+	}
+}
+
+int turn_led(int which, int cmd)
+{
+	if( which<0 || which>=LED_MAX )
+		return -1;
+
+
+	if( OFF == cmd )
+	       	digitalWrite (led_gpio[which], LOW);
+	else
+	       	digitalWrite (led_gpio[which], HIGH);
+
+	return 0;
+}
+
+
diff --git a/mqttd/led.h b/mqttd/led.h
new file mode 100644
index 0000000..dfc411c
--- /dev/null
+++ b/mqttd/led.h
@@ -0,0 +1,48 @@
+/*********************************************************************************
+ *      Copyright:  (C) 2018 LingYun IoT System Studio
+ *                  All rights reserved.
+ *
+ *       Filename:  led.h
+ *    Description:  This file is used to control RGB 3-colours LED
+ *
+ *     pi@raspberrypi:~ $ gpio readall show BCM and wPi pinmap  
+ *
+ *                 LED      BCM           wPi 
+ *                  G ---- GPIO.13  ---- GPIO.23
+ *                  R ---- GPIO.19  ---- GPIO.24    
+ *                  B ---- GPIO.26  ---- GPIO.25
+ *                  I ---- GND      ----
+ *                 
+ *        Version:  1.0.0(2018/10/14)
+ *         Author:  Guo Wenxue <guowenxue@gmail.com>
+ *      ChangeLog:  1, Release initial version on "2018/10/14 12:13:26"
+ *                 
+ ********************************************************************************/
+
+#ifndef __LED_H
+#define __LED_H
+
+#define OFF   0
+#define ON    1
+
+/* Three LEDs code */
+enum
+{
+	LED_R = 0,
+	LED_G,
+	LED_B,
+	LED_MAX,
+};
+
+/* 3 LEDs WiringPi GPIO port */
+                               
+                              /* LED_R  LED_G   LED_B */
+static int led_gpio[LED_MAX]= {   24,    23,     25  };
+
+
+void init_led(void);
+int turn_led(int which, int cmd);
+
+
+#endif
+
diff --git a/mqttd/main.c b/mqttd/main.c
new file mode 100644
index 0000000..1ec682b
--- /dev/null
+++ b/mqttd/main.c
@@ -0,0 +1,92 @@
+/*********************************************************************************
+ *      Copyright:  (C) 2019 LingYun IoT System Studio
+ *                  All rights reserved.
+ *
+ *       Filename:  main.c
+ *    Description:  This file 
+ *                 
+ *        Version:  1.0.0(29/01/19)
+ *         Author:  Guo Wenxue <guowenxue@gmail.com>
+ *      ChangeLog:  1, Release initial version on "29/01/19 15:34:41"
+ *                 
+ ********************************************************************************/
+#include <stdio.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "led.h"
+#include "ds18b20.h"
+#include "sht20.h"
+
+int hal_init(void);
+
+/********************************************************************************
+ *  Description:
+ *   Input Args:
+ *  Output Args:
+ * Return Value:
+ ********************************************************************************/
+int main (int argc, char **argv)
+{
+    float              temp;
+    float              rh;
+
+    if( hal_init() < 0 )
+    {
+        printf("Initialise hardware failure\n");
+        return -1;
+    }
+    
+    while(1)
+    {
+        turn_led(LED_R, ON);
+        sleep(1);
+        turn_led(LED_R, OFF);
+        sleep(1);
+
+        turn_led(LED_G, ON);
+        sleep(1);
+        turn_led(LED_G, OFF);
+        sleep(1);
+
+        turn_led(LED_B, ON);
+        sleep(1);
+        turn_led(LED_B, OFF);
+        sleep(1);
+
+        if(sht2x_get_temp_humidity(&temp, &rh) < 0)
+        {
+            printf("SHT2X get temperature and relative humidity failure\n");
+        }
+        else
+        {
+            printf("SHT2X Temperature=%lf ℃ relative humidity=%lf%\n", temp, rh);
+        }
+
+
+        if( ds18b20_get_temperature(&temp) < 0)
+        {
+            printf("DS18B20 get temperature failure\n");
+        }
+        else
+        {
+            printf("DS18B20 get temperature=%lf ℃ \n", temp);
+        }
+    }
+
+    return 0;
+} /* ----- End of main() ----- */
+
+
+int hal_init(void)
+{
+    init_led();
+
+    if( sht2x_init() < 0 )
+    {
+        printf("Initialise SHT20 failure\n");
+        return -2;
+    }
+
+    return 0;
+}
diff --git a/mqttd/makefile b/mqttd/makefile
new file mode 100644
index 0000000..684dac6
--- /dev/null
+++ b/mqttd/makefile
@@ -0,0 +1,68 @@
+#*********************************************************************************
+#      Copyright:  (C) 2012 Guo Wenxue<Email:guowenxue@gmail.com QQ:281143292>
+#                  All rights reserved.
+#
+#       Filename:  Makefile
+#    Description:  This Makefile used to compile all the C source code file in current 
+#                  folder to one excutable binary files.
+#                      
+#        Version:  1.0.0(10/08/2011~)
+#                  Author:  Guo Wenxue <guowenxue@gmail.com>
+#      ChangeLog:  1, Release initial version on "11/11/2011 01:29:33 PM"
+#                       
+#********************************************************************************/
+
+PWD=$(shell pwd)
+INSTPATH=/usr/bin
+
+CFLAGS+=-I${PWD}
+#CFLAGS+=-Wall -Werror
+
+LDFLAGS+=-lwiringPi
+LDFLAGS+=-lpthread
+
+VPATH= .
+SRCS = $(wildcard ${VPATH}/*.c)
+OBJS = $(patsubst %.c,%.o,$(SRCS))
+
+#CC=arm-linux-
+export CC=${CROSS_COMPILE}gcc
+export CXX=${CROSS_COMPILE}g++
+export AR=${CROSS_COMPILE}ar
+export AS=${CROSS_COMPILE}as
+export RANLIB=${CROSS_COMPILE}ranlib
+export STRIP=${CROSS_COMPILE}strip
+export CFLAGS
+export LDFLAGS
+
+SRCFILES = $(wildcard *.c)
+IMAGE_NAME=$(shell basename ${PWD})
+
+all: entry binary
+entry: 
+	@echo " ";
+	@echo " =========================================================";
+	@echo " **        Compile \"${BINARIES}\" for ${ARCH}         ";
+	@echo " =========================================================";
+
+binary:  ${SRCFILES}
+	$(CC) $(CFLAGS) -o ${IMAGE_NAME} $^  ${LDFLAGS}
+	@echo " Compile over"
+
+tag: 
+	@ctags --c-kinds=+defglmnstuvx --langmap=c:.c.h.ho.hem.het.hec.hev.him.hit.hic.hiv -R .  
+	@cscope -Rbq
+
+install:
+	@cp $(IMAGE_NAME) ${INSTPATH}
+
+clean: 
+	@rm -f version.h 
+	@rm -f *.o $(IMAGE_NAME) 
+	@rm -rf *.gdb *.a *.so *.elf*
+
+distclean: clean
+	@rm -f  tags cscope*
+
+.PHONY: clean entry
+
diff --git a/mqttd/sht20.c b/mqttd/sht20.c
new file mode 100644
index 0000000..66af731
--- /dev/null
+++ b/mqttd/sht20.c
@@ -0,0 +1,439 @@
+/*********************************************************************************
+ *      Copyright:  (C) 2018 LingYun IoT System Studio
+ *                  All rights reserved.
+ *
+ *       Filename:  sht20.c
+ *    Description:  This file is temperature and relative humidity sensor SHT20 code
+ *                 
+ *        Version:  1.0.0(2018/10/14)
+ *         Author:  Guo Wenxue <guowenxue@gmail.com>
+ *      ChangeLog:  1, Release initial version on "2018/10/14 12:13:26"
+ *                 
+ ********************************************************************************/
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <linux/types.h>
+#include <sys/stat.h>
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h> 
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <string.h>
+#include <stdint.h>
+#include <time.h>
+#include <errno.h>
+#include <string.h>
+
+#include "sht20.h"
+
+static int s_sht2x_fd = -1;
+
+void sht2x_term(void)
+{
+    close(s_sht2x_fd);
+    s_sht2x_fd = -1;
+    printf("Terminate SHT2X\n");
+}
+
+#ifdef I2C_API_RDWR  /* Use I2C userspace driver read/write API */
+
+int sht2x_softreset(int fd)
+{
+	uint8_t           buf[4];
+
+	if( fd<0 )
+	{
+		printf("%s line [%d] %s() get invalid input arguments\n", __FILE__, __LINE__, __func__ );
+		return -1;
+	}
+
+	/* software reset SHT2x */
+	memset(buf, 0, sizeof(buf));
+
+	buf[0] = SOFTRESET;
+	write(fd, buf, 1);
+
+	msleep(50);
+
+	return 0;
+}
+
+int sht2x_init(void)
+{
+	
+	if( (s_sht2x_fd=open("/dev/i2c-1", O_RDWR)) < 0)
+	{
+		printf("i2c device open failed: %s\n", strerror(errno));
+        return -1;
+	}
+	
+	/* set I2C mode and SHT2x slave address */
+	ioctl(s_sht2x_fd, I2C_TENBIT, 0);    /* Not 10-bit but 7-bit mode */
+	ioctl(s_sht2x_fd, I2C_SLAVE, 0x40); /* set SHT2x slava address 0x40*/
+
+	if( sht2x_softreset(s_sht2x_fd) < 0 )
+	{
+		printf("SHT2x softreset failure\n");
+        sht2x_term();
+		return -2;
+	}
+
+	return s_sht2x_fd;
+}
+
+int sht2x_get_temp_humidity(float *temp, float *rh)
+{
+	uint8_t           buf[4];
+
+	if( !temp || !rh )
+	{
+		printf("%s line [%d] %s() get invalid input arguments\n", __FILE__, __LINE__, __func__ );
+		return -1;
+	}
+
+    if( s_sht2x_fd < 0 )
+    {
+        if( sht2x_init() < 0)
+        {
+            printf("SHT2x initialise failure\n");
+            return -2;
+        }
+    }
+
+	/* send trigger temperature measure command and read the data */
+	memset(buf, 0, sizeof(buf));
+	buf[0]=TRIGGER_TEMPERATURE_NO_HOLD;
+	write(s_sht2x_fd, buf, 1);
+
+	msleep(85); /* datasheet: typ=66, max=85 */
+
+	memset(buf, 0, sizeof(buf));
+	read(s_sht2x_fd, buf, 3);
+	//dump_buf("Temperature sample data: ", buf, 3);
+	*temp = 175.72 * (((((int) buf[0]) << 8) + buf[1]) / 65536.0) - 46.85;
+	
+	/* send trigger humidity measure command and read the data */
+	memset(buf, 0, sizeof(buf));
+	buf[0] = TRIGGER_HUMIDITY_NO_HOLD;	
+	write(s_sht2x_fd, buf, 1);
+
+	msleep(29); /* datasheet: typ=22, max=29 */
+	memset(buf, 0, sizeof(buf));
+
+	read(s_sht2x_fd, buf, 3);
+	//dump_buf("Relative humidity sample data: ", buf, 3);
+	*rh = 125 * (((((int) buf[0]) << 8) + buf[1]) / 65536.0) - 6;
+
+	return 0;
+}
+
+int sht2x_get_serialnumber(uint8_t *serialnumber, int size)
+{
+	uint8_t           buf[4];
+
+	if( !serialnumber || size!=8 )
+	{
+		printf("%s line [%d] %s() get invalid input arguments\n", __FILE__, __LINE__, __func__ );
+		return -1;
+	}
+
+    if( s_sht2x_fd < 0 )
+    {
+        if( sht2x_init() < 0)
+        {
+            printf("SHT2x initialise failure\n");
+            return -2;
+        }
+    }
+
+	/* Read SerialNumber from Location 1 */
+	memset(buf, 0, sizeof(buf));
+	buf[0] = 0xfa;  /* command for readout on-chip memory */
+	buf[1] = 0x0f;  /* on-chip memory address */
+	write(s_sht2x_fd, buf, 2);
+
+	memset(buf, 0, sizeof(buf));
+	read(s_sht2x_fd, buf, 4);
+
+	serialnumber[5]=buf[0]; /* Read SNB_3 */
+	serialnumber[4]=buf[1]; /* Read SNB_2 */
+	serialnumber[3]=buf[2]; /* Read SNB_1 */
+	serialnumber[2]=buf[3]; /* Read SNB_0 */
+	
+	/* Read SerialNumber from Location 2 */
+	memset(buf, 0, sizeof(buf) );
+	buf[0]=0xfc;  /* command for readout on-chip memory */
+	buf[1]=0xc9;  /* on-chip memory address */
+	write(s_sht2x_fd, buf, 2);
+
+	memset(buf, 0, sizeof(buf) );
+	read(s_sht2x_fd, buf, 4);
+
+	serialnumber[1]=buf[0]; /* Read SNC_1 */
+	serialnumber[0]=buf[1]; /* Read SNC_0 */
+	serialnumber[7]=buf[2]; /* Read SNA_1 */
+	serialnumber[6]=buf[3]; /* Read SNA_0 */
+
+	//dump_buf("SHT2x Serial number: ", serialnumber, 8);
+
+	return 0;
+}
+
+#elif (defined I2C_API_IOCTL)  /* Use I2C userspace driver read/write API */
+
+int sht2x_softreset(int fd)
+{
+    struct i2c_msg               msg;
+	struct i2c_rdwr_ioctl_data   sht2x_data;
+	uint8_t                      buf[2];
+
+	if( fd<0 )
+	{
+		printf("%s line [%d] %s() get invalid input arguments\n", __FILE__, __LINE__, __func__ );
+		return -1;
+	}
+
+	msg.addr= 0x40; 
+	msg.flags=0; //write
+	msg.len= 1; 
+	msg.buf= buf; 
+	msg.buf[0]=SOFTRESET;
+
+	sht2x_data.nmsgs= 1; 
+	sht2x_data.msgs= &msg;
+
+	if( ioctl(fd, I2C_RDWR, &sht2x_data) < 0 )
+	{
+		printf("%s() ioctl failure: %s\n", __func__, strerror(errno));
+        sht2x_term();
+		return -2;
+	}
+
+	msleep(50);
+
+	return 0;
+}
+
+
+int sht2x_init(void)
+{
+	if( (s_sht2x_fd=open("/dev/i2c-1", O_RDWR)) < 0)
+	{
+		printf("i2c device open failed: %s\n", strerror(errno));
+	       	return -1;
+	}
+
+	if( sht2x_softreset(s_sht2x_fd) < 0 )
+	{
+		printf("SHT2x softreset failure\n");
+        sht2x_term();
+		return -2;
+	}
+
+    return 0;
+}
+
+int sht2x_get_serialnumber(uint8_t *serialnumber, int size)
+{
+    struct i2c_msg               msgs[2];
+	struct i2c_rdwr_ioctl_data   sht2x_data;
+	uint8_t                      sbuf[2];
+	uint8_t                      rbuf[4];
+
+	if( !serialnumber || size!=8 )
+	{
+		printf("%s line [%d] %s() get invalid input arguments\n", __FILE__, __LINE__, __func__ );
+		return -1;
+	}
+
+    if( s_sht2x_fd < 0 )
+    {
+        if( sht2x_init() < 0)
+        {
+            printf("SHT2x initialise failure\n");
+            return -2;
+        }
+    }
+
+	/*+------------------------------------------+
+	 *|     Read SerialNumber from Location 1    |
+	 *+------------------------------------------+*/
+
+	msgs[0].addr= 0x40; 
+	msgs[0].flags=0; //write
+	msgs[0].len= 2; 
+	msgs[0].buf= sbuf; 
+	msgs[0].buf[0]=0xfa;  /* command for readout on-chip memory */
+	msgs[0].buf[1]=0x0f;  /* on-chip memory address */
+	
+	msgs[1].addr=0x40; 
+	msgs[1].flags=I2C_M_RD; //write
+	msgs[1].len= 4; 
+	msgs[1].buf= rbuf; 
+
+	sht2x_data.nmsgs= 2; 
+	sht2x_data.msgs= msgs;
+
+	if( ioctl(s_sht2x_fd, I2C_RDWR, &sht2x_data) < 0 )
+	{
+		printf("%s() ioctl failure: %s\n", __func__, strerror(errno));
+        sht2x_term();
+		return -2;
+	}
+	
+	serialnumber[5]=rbuf[0]; /* Read SNB_3 */
+    serialnumber[4]=rbuf[1]; /* Read SNB_2 */
+    serialnumber[3]=rbuf[2]; /* Read SNB_1 */
+    serialnumber[2]=rbuf[3]; /* Read SNB_0 */
+
+
+	/*+------------------------------------------+
+	 *|     Read SerialNumber from Location 2    |
+	 *+------------------------------------------+*/
+	
+	msgs[0].addr= 0x40; 
+	msgs[0].flags=0; //write
+	msgs[0].len= 2; 
+	msgs[0].buf= sbuf; 
+	msgs[0].buf[0]=0xfc;  /* command for readout on-chip memory */
+	msgs[0].buf[1]=0xc9;  /* on-chip memory address */
+	
+	msgs[1].addr=0x40; 
+	msgs[1].flags=I2C_M_RD; //write
+	msgs[1].len= 4; 
+	msgs[1].buf= rbuf; 
+
+	sht2x_data.nmsgs= 2; 
+	sht2x_data.msgs= msgs;
+
+	if( ioctl(s_sht2x_fd, I2C_RDWR, &sht2x_data) < 0 )
+	{
+		printf("%s() ioctl failure: %s\n", __func__, strerror(errno));
+        sht2x_term();
+		return -2;
+	}
+	
+	serialnumber[1]=rbuf[0]; /* Read SNC_1 */
+	serialnumber[0]=rbuf[1]; /* Read SNC_0 */
+	serialnumber[7]=rbuf[2]; /* Read SNA_1 */
+	serialnumber[6]=rbuf[3]; /* Read SNA_0 */
+
+	//dump_buf("SHT2x Serial number: ", serialnumber, 8);
+
+	return 0;
+}
+
+
+int sht2x_get_temp_humidity(float *temp, float *rh)
+{
+    struct i2c_msg               msg;
+	struct i2c_rdwr_ioctl_data   sht2x_data;
+	uint8_t                      buf[4];
+
+	if( !temp || !rh )
+	{
+		printf("%s line [%d] %s() get invalid input arguments\n", __FILE__, __LINE__, __func__ );
+		return -1;
+	}
+
+    if( s_sht2x_fd < 0 )
+    {
+        if( sht2x_init() < 0)
+        {
+            printf("SHT2x initialise failure\n");
+            return -2;
+        }
+    }
+	
+	/*+------------------------------------------+
+	 *|       measure and get temperature        |
+	 *+------------------------------------------+*/
+
+	msg.addr= 0x40; 
+	msg.flags=0; //write
+	msg.len= 1; 
+	msg.buf= buf; 
+	msg.buf[0]=TRIGGER_TEMPERATURE_NO_HOLD;  /* trigger temperature without hold I2C bus */
+
+	sht2x_data.nmsgs= 1; 
+	sht2x_data.msgs= &msg;
+
+	if( ioctl(s_sht2x_fd, I2C_RDWR, &sht2x_data) < 0 )
+	{
+		printf("%s() ioctl failure: %s\n", __func__, strerror(errno));
+        sht2x_term();
+		return -2;
+	}
+
+	msleep(85);
+	
+	memset(buf, 0, sizeof(buf));
+	msg.addr=0x40; 
+	msg.flags=I2C_M_RD; //write
+	msg.len= 3; 
+	msg.buf= buf; 
+
+	sht2x_data.nmsgs= 1; 
+	sht2x_data.msgs= &msg;
+
+	if( ioctl(s_sht2x_fd, I2C_RDWR, &sht2x_data) < 0 )
+	{
+		printf("%s() ioctl failure: %s\n", __func__, strerror(errno));
+        sht2x_term();
+		return -2;
+	}
+	
+	//dump_buf("Temperature sample data: ", buf, 3);
+	*temp = 175.72 * (((((int) buf[0]) << 8) + buf[1]) / 65536.0) - 46.85;
+
+	
+	/*+------------------------------------------+
+	 *|    measure and get relative humidity     |
+	 *+------------------------------------------+*/
+
+	msg.addr= 0x40; 
+	msg.flags=0; //write
+	msg.len= 1; 
+	msg.buf= buf; 
+	msg.buf[0]=TRIGGER_HUMIDITY_NO_HOLD;  /* trigger humidity without hold I2C bus */
+
+	sht2x_data.nmsgs= 1; 
+	sht2x_data.msgs= &msg;
+
+	if( ioctl(s_sht2x_fd, I2C_RDWR, &sht2x_data) < 0 )
+	{
+		printf("%s() ioctl failure: %s\n", __func__, strerror(errno));
+        sht2x_term();
+		return -2;
+	}
+
+	msleep(29);
+	
+	memset(buf, 0, sizeof(buf));
+	msg.addr=0x40; 
+	msg.flags=I2C_M_RD; //write
+	msg.len= 3; 
+	msg.buf= buf; 
+
+	sht2x_data.nmsgs= 1; 
+	sht2x_data.msgs= &msg;
+
+	if( ioctl(s_sht2x_fd, I2C_RDWR, &sht2x_data) < 0 )
+	{
+		printf("%s() ioctl failure: %s\n", __func__, strerror(errno));
+        sht2x_term();
+		return -2;
+	}
+
+	//dump_buf("Relative humidity sample data: ", buf, 3);
+       	*rh = 125 * (((((int) buf[0]) << 8) + buf[1]) / 65536.0) - 6;
+	
+	return 0;
+}
+
+#endif
+
diff --git a/mqttd/sht20.h b/mqttd/sht20.h
new file mode 100644
index 0000000..467fbfa
--- /dev/null
+++ b/mqttd/sht20.h
@@ -0,0 +1,74 @@
+/*********************************************************************************
+ *      Copyright:  (C) 2018 LingYun IoT System Studio
+ *                  All rights reserved.
+ *
+ *       Filename:  sht20.c
+ *    Description:  This file is temperature and relative humidity sensor SHT20 code
+ *                 
+ *        Version:  1.0.0(2018/10/14)
+ *         Author:  Guo Wenxue <guowenxue@gmail.com>
+ *      ChangeLog:  1, Release initial version on "2018/10/14 12:13:26"
+ *                 
+ ********************************************************************************/
+#ifndef __SHT20_H
+#define __SHT20_H
+
+#include <stdint.h>
+#include <time.h>
+
+#define SOFTRESET                        0xFE
+#define TRIGGER_TEMPERATURE_NO_HOLD      0xF3
+#define TRIGGER_HUMIDITY_NO_HOLD         0xF5
+
+//#define I2C_API_IOCTL  /* Use I2C userspace driver ioctl API */
+#define I2C_API_RDWR /* Use I2C userspace driver read/write API */
+
+void sht2x_term(void);
+int sht2x_init(void);
+int sht2x_get_serialnumber(uint8_t *serialnumber, int size);
+int sht2x_get_temp_humidity(float *temp, float *rh);
+ 
+static inline void msleep(unsigned long ms) 
+{
+       	struct timespec cSleep;
+       	unsigned long ulTmp;
+       
+	cSleep.tv_sec = ms / 1000;
+       	if (cSleep.tv_sec == 0)
+       	{   
+		ulTmp = ms * 10000;
+	       	cSleep.tv_nsec = ulTmp * 100;
+       	}   
+	else
+       	{   
+		cSleep.tv_nsec = 0;
+       	}   
+	
+	nanosleep(&cSleep, 0); 
+}
+
+static inline void dump_buf(const char *prompt, uint8_t *buf, int size)
+{
+	int          i;
+
+	if( !buf )
+	{
+		return ;
+	}
+
+	if( prompt )
+	{
+		printf("%s ", prompt);
+	}
+
+	for(i=0; i<size; i++)
+	{
+		printf("%02x ", buf[i]);
+	}
+	printf("\n");
+
+	return ;
+}
+
+#endif
+

--
Gitblit v1.9.1