guowenxue
2019-01-30 542454b6e29fd5359fca69b71e1666ad71a7b7d7
Add monitred and mqttd source code
21 files added
3448 ■■■■■ changed files
monitord/beep.c 216 ●●●●● patch | view | raw | blame | history
monitord/beep.h 38 ●●●●● patch | view | raw | blame | history
monitord/cp_comport.c 600 ●●●●● patch | view | raw | blame | history
monitord/cp_comport.h 67 ●●●●● patch | view | raw | blame | history
monitord/cp_logger.c 433 ●●●●● patch | view | raw | blame | history
monitord/cp_logger.h 111 ●●●●● patch | view | raw | blame | history
monitord/cp_proc.c 342 ●●●●● patch | view | raw | blame | history
monitord/cp_proc.h 42 ●●●●● patch | view | raw | blame | history
monitord/cp_socket.c 357 ●●●●● patch | view | raw | blame | history
monitord/cp_socket.h 65 ●●●●● patch | view | raw | blame | history
monitord/makefile 68 ●●●●● patch | view | raw | blame | history
monitord/monitord.c 186 ●●●●● patch | view | raw | blame | history
monitord/monitord.h 18 ●●●●● patch | view | raw | blame | history
mqttd/ds18b20.c 105 ●●●●● patch | view | raw | blame | history
mqttd/ds18b20.h 19 ●●●●● patch | view | raw | blame | history
mqttd/led.c 60 ●●●●● patch | view | raw | blame | history
mqttd/led.h 48 ●●●●● patch | view | raw | blame | history
mqttd/main.c 92 ●●●●● patch | view | raw | blame | history
mqttd/makefile 68 ●●●●● patch | view | raw | blame | history
mqttd/sht20.c 439 ●●●●● patch | view | raw | blame | history
mqttd/sht20.h 74 ●●●●● patch | view | raw | blame | history
monitord/beep.c
New file
@@ -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);
    }
}
monitord/beep.h
New file
@@ -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
monitord/cp_comport.c
New file
@@ -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;
}
monitord/cp_comport.h
New file
@@ -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
monitord/cp_logger.c
New file
@@ -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);
    }
}
monitord/cp_logger.h
New file
@@ -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  */
monitord/cp_proc.c
New file
@@ -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);
}
monitord/cp_proc.h
New file
@@ -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
monitord/cp_socket.c
New file
@@ -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;
}
monitord/cp_socket.h
New file
@@ -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
monitord/makefile
New file
@@ -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
monitord/monitord.c
New file
@@ -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;
}
monitord/monitord.h
New file
@@ -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_  ----- */
mqttd/ds18b20.c
New file
@@ -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;
}
mqttd/ds18b20.h
New file
@@ -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
mqttd/led.c
New file
@@ -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;
}
mqttd/led.h
New file
@@ -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
mqttd/main.c
New file
@@ -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;
}
mqttd/makefile
New file
@@ -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
mqttd/sht20.c
New file
@@ -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
mqttd/sht20.h
New file
@@ -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