Guo Wenxue
2018-10-24 9e649dd24799cd8d64058eab3782d1af9f7fed4c
Add 2.Socket folder, which implement send temperature report in 1 second by TLV protocal to server
7 files added
486 ■■■■■ changed files
apue/2.Socket/ds18b20.c 102 ●●●●● patch | view | raw | blame | history
apue/2.Socket/ds18b20.h 20 ●●●●● patch | view | raw | blame | history
apue/2.Socket/makefile 17 ●●●●● patch | view | raw | blame | history
apue/2.Socket/socket_client.c 120 ●●●●● patch | view | raw | blame | history
apue/2.Socket/socket_server.c 119 ●●●●● patch | view | raw | blame | history
apue/2.Socket/tlv.c 67 ●●●●● patch | view | raw | blame | history
apue/2.Socket/tlv.h 41 ●●●●● patch | view | raw | blame | history
apue/2.Socket/ds18b20.c
New file
@@ -0,0 +1,102 @@
/*********************************************************************************
 *      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;
        }
    }
    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;
    return 0;
}
apue/2.Socket/ds18b20.h
New file
@@ -0,0 +1,20 @@
/*********************************************************************************
 *      Copyright:  (C) 2018 LingYun IoT System Studio
 *                  All rights reserved.
 *
 *       Filename:  ds18b20.h
 *    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_
int ds18b20_get_temperature(float *temp);
#endif
apue/2.Socket/makefile
New file
@@ -0,0 +1,17 @@
INST_PATH=/usr/bin
BIN_FILES=socket_client socket_server
all: clean ${BIN_FILES}
socket_client:
    gcc socket_client.c ds18b20.c tlv.c -o socket_client
socket_server:
    gcc socket_server.c tlv.c -o socket_server
clean:
    rm -f ${BIN_FILES}
install:
    @cp ${BIN_FILES} ${INST_PATH}
apue/2.Socket/socket_client.c
New file
@@ -0,0 +1,120 @@
/*********************************************************************************
 *      Copyright:  (C) 2018 LingYun IoT Studio
 *                  All rights reserved.
 *
 *       Filename:  socket_client.c
 *    Description:  This file is socket client sample source code, it will connect
 *                  socket server and send to/receive from it.
 *
 *        Version:  1.0.0(10/23/2018)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "2018-10-23 01:38:08 PM"
 *
 ********************************************************************************/
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <math.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "ds18b20.h"
#include "tlv.h"
#define SERVER_IP          "127.0.0.1"
#define SERVER_PORT        8889
int main(int argc, char **argv)
{
    int                     conn_fd = -1;
    int                     rv = -1;
    char                    buf[1024];
    struct sockaddr_in      serv_addr;
    float                   temp;
    conn_fd = socket(AF_INET, SOCK_STREAM, 0);
    if(conn_fd < 0)
    {
        printf("create socket failure: %s\n", strerror(errno));
        return -1;
    }
    memset(&serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(SERVER_PORT);
    inet_aton( SERVER_IP, &serv_addr.sin_addr );
    if( connect(conn_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr))  < 0)
    {
        printf("connect to server [%s:%d] failure: %s\n", SERVER_IP, SERVER_PORT, strerror(errno));
        return 0;
    }
    while(1)
    {
        if( ds18b20_get_temperature(&temp) < 0 )
        {
            printf("DS18B20 get temperature failure\n");
            continue;
        }
        printf("Current temperature: %f\n", temp);
        /*+-----------------------------------------------+
         *| TLV Format:  Tag(1B) Length(1B) Value(2B)     |
         *+-----------------------------------------------+*/
        memset(buf, 0, sizeof(buf));
        buf[0] = TAG_TEMP;
        buf[1] = 2;  /*Length segement*/
        /*Value: 1st Bytes is integer part and 2nd bytes is fractional part */
        buf[2] = (int)temp & 0xFF;
        buf[3] = ( ((int)(temp*100))%100 )  & 0xFF ;
        //tlv_dump_buf("Temperature buff: ", buf, 4);
        if( write(conn_fd, buf, 4) < 0 )
        {
            printf("Write data to server [%s:%d] failure: %s\n", SERVER_IP, SERVER_PORT, strerror(errno));
            goto cleanup;
        }
        memset(buf, 0, sizeof(buf));
        rv = read(conn_fd, buf, sizeof(buf));
        if(rv < 0)
        {
            printf("Read data from server failure: %s\n", strerror(errno));
            goto cleanup;
        }
        else if( 0 == rv )
        {
            printf("Client connect to server get disconnected\n");
            goto cleanup;
        }
        tlv_dump_buf("Receive data from server: ", buf, rv);
        if( rv >= 2)
        {
            if( TAG_NAK == buf[0] )
            {
                printf("Parser TLV packet and get NOT Acknowledge reply from server!\n");
            }
            else if( TAG_ACK == buf[0] )
            {
                printf("Parser TLV packet and get Acknowledge reply from server!\n");
            }
        }
        //printf("Read %d bytes data from server: '%s'\n", rv, buf);
    }
cleanup:
    close(conn_fd);
}
apue/2.Socket/socket_server.c
New file
@@ -0,0 +1,119 @@
/*********************************************************************************
 *      Copyright:  (C) 2018 LingYun IoT Studio
 *                  All rights reserved.
 *
 *       Filename:  socket_server.c
 *    Description:  This file is socket server sample source code, it will echo back
 *                  the receive data from client.
 *
 *        Version:  1.0.0(10/23/2018)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "2017-10-23 01:41:05 PM"
 *
 ********************************************************************************/
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "tlv.h"
#define LISTEN_PORT          8889
#define BACKLOG              13
int main(int argc, char **argv)
{
    int                     rv = -1;
    int                     listen_fd,  client_fd = -1;
    struct sockaddr_in      serv_addr;
    struct sockaddr_in      cli_addr;
    socklen_t               cliaddr_len;
    char                    buf[1024];
    int                     reuse = 1;
    listen_fd = socket(AF_INET, SOCK_STREAM, 0);
    if(listen_fd < 0 )
    {
        printf("create socket failure: %s\n", strerror(errno));
        return -1;
    }
    printf("socket create fd[%d]\n", listen_fd);
    memset(&serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(LISTEN_PORT);
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    if( bind(listen_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0 )
    {
        printf("create socket failure: %s\n", strerror(errno));
        return -2;
    }
    printf("socket[%d] bind on port[%d] for all IP address ok\n", listen_fd, LISTEN_PORT);
    /* Fix port can not be used when stop server program and run it again immediately.*/
    setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
    listen(listen_fd, BACKLOG);
    while(1)
    {
        printf("\nStart waiting and accept new client connect...\n", listen_fd);
        client_fd = accept(listen_fd, (struct sockaddr*)&cli_addr, &cliaddr_len);
        if(client_fd < 0)
        {
            printf("accept new socket failure: %s\n", strerror(errno));
            return -2;
        }
        printf("Accept new client[%s:%d] with fd [%d]\n", inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port), client_fd);
    while(1)
    {
        memset(buf, 0, sizeof(buf));
        if( (rv=read(client_fd, buf, sizeof(buf))) < 0)
               {
                   printf("Read data from client socket[%d] failure: %s\n", client_fd, strerror(errno));
                   close(client_fd);
            break;
               }
               else if( rv == 0 )
               {
                   printf("client socket[%d] disconnected\n", client_fd);
                   close(client_fd);
            break;
               }
        //tlv_dump_buf("Read TLV data from client: ", buf, rv);
        if(buf[0] == TAG_TEMP )
               {
                   /* Tag+Length is 2 bytes, buf[1] is the data length,  */
                   if(2+buf[1]>rv)
                   {
                       printf("Receive TLV packet is not integrated\n");
                rv=tlv_pack_nak(buf, sizeof(buf));
                   }
                   else
                   {
                       printf("Parser TLV packet and get temperature: %d.%d\n", buf[2], buf[3]);
                rv=tlv_pack_ack(buf, sizeof(buf));
                   }
               }
        if( write(client_fd, buf, rv) < 0 )
               {
                   printf("Write %d bytes data back to client[%d] failure: %s\n", rv, client_fd, strerror(errno));
                   close(client_fd);
               }
    }
        close(client_fd);
    }
    close(listen_fd);
}
apue/2.Socket/tlv.c
New file
@@ -0,0 +1,67 @@
/*********************************************************************************
 *      Copyright:  (C) 2018 LingYun IoT System Studio
 *                  All rights reserved.
 *
 *       Filename:  tlv.c
 *    Description:  This file is TLV(Tag Length Value) protocal head file
 *
 *        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 "tlv.h"
void tlv_dump_buf(const char *prompt, char *buf, int size)
{
    int           i;
    if(!buf)
               return ;
    if(prompt)
               printf("%s", prompt);
    for(i=0; i<size; i++ )
           {
               printf("0x%02x ", buf[i]);
           }
    printf("\n");
}
int tlv_pack_ack(char *buf, int size)
{
    if( !buf )
        return 0;
    if(size < 2)
        return 0;
    buf[0]=TAG_ACK;  /* tag */
    buf[1]=0;        /*length*/
    /*No data here*/
    return 2;
}
int tlv_pack_nak(char *buf, int size)
{
    if( !buf )
        return 0;
    if(size < 2)
        return 0;
    buf[0]=TAG_NAK; /* tag */
    buf[1]=0;       /* length*/
    /*No data here*/
    return 2;
}
apue/2.Socket/tlv.h
New file
@@ -0,0 +1,41 @@
/*********************************************************************************
 *      Copyright:  (C) 2018 LingYun IoT System Studio
 *                  All rights reserved.
 *
 *       Filename:  tlv.h
 *    Description:  This file is TLV(Tag Length Value) protocal head file
 *
 *        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 __TLV_H_
#define __TLV_H_
/*+-----------------------------------------------+
 *| TLV Format:  Tag(1B) Length(1B) Value(2B)     |
 *+-----------------------------------------------+*/
/*TLV Format Tag definition */
enum
{
           TAG_TEMP = 1,  /* Temperature */
           TAG_HUMI,      /* Relative Humidity */
           TAG_DOOR,      /* Door open status */
    TAG_NAK=0xFD,  /* NAK packet */
    TAG_ACK=0xFE,  /* ACK packet */
};
void tlv_dump_buf(const char *prompt, char *buf, int size);
int tlv_pack_ack(char *buf, int size);
int tlv_pack_nak(char *buf, int size);
#endif