update prj1_tlv source code, test socket client connect ok
7 files modified
7 files added
| | |
| | | #ifndef CRC_ITU_T_H
|
| | | #define CRC_ITU_T_H
|
| | |
|
| | | #define MAGIC_CRC 0x1E50
|
| | | #define MAGIC_CRC 0x0107
|
| | |
|
| | | extern const unsigned short crc_itu_t_table[256];
|
| | |
|
New file |
| | |
| | | /********************************************************************************* |
| | | * Copyright: (C) 2020 LingYun IoT System Studio |
| | | * All rights reserved. |
| | | * |
| | | * Filename: ds18b20.c |
| | | * Description: This file is get temperature by DS18B20 on RaspberryPi |
| | | * |
| | | * Version: 1.0.0(2020年04月15日) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "2020年04月15日 23时14分21秒" |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | #include <stdio.h> |
| | | #include <stdlib.h> |
| | | #include <unistd.h> |
| | | #include <stdint.h> |
| | | #include <fcntl.h> |
| | | #include <dirent.h> |
| | | #include <string.h> |
| | | #include <time.h> |
| | | #include <errno.h> |
| | | |
| | | #include "logger.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(uint16_t *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; |
| | | uint8_t *byte; |
| | | float value; |
| | | int found = 0; |
| | | |
| | | if( !temp ) |
| | | { |
| | | log_err("ERROR: Invalid input arguments\n"); |
| | | return -1; |
| | | } |
| | | |
| | | /*+-------------------------------------------------------------------+ |
| | | *| open dierectory /sys/bus/w1/devices to get chipset Serial Number | |
| | | *+-------------------------------------------------------------------+*/ |
| | | if((dirp = opendir(w1_path)) == NULL) |
| | | { |
| | | log_err("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 ) |
| | | { |
| | | log_err("Can not find ds18b20 in %s\n", w1_path); |
| | | return -2; |
| | | } |
| | | |
| | | /* 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 ) |
| | | { |
| | | log_err("open %s error: %s\n", w1_path, strerror(errno)); |
| | | return -2; |
| | | } |
| | | |
| | | if(read(fd, buf, sizeof(buf)) < 0) |
| | | { |
| | | log_err("read %s error: %s\n", w1_path, strerror(errno)); |
| | | close(fd); |
| | | return -2; |
| | | } |
| | | |
| | | ptr = strstr(buf, "t="); |
| | | if( !ptr ) |
| | | { |
| | | log_err("ERROR: Can not get temperature\n"); |
| | | close(fd); |
| | | return -2; |
| | | } |
| | | |
| | | ptr+=2; |
| | | |
| | | /* use two bytes to save temperature value */ |
| | | byte = (uint8_t *)temp; |
| | | byte[0] = atoi(ptr)/1000; /* integer part */ |
| | | byte[1] = (atoi(ptr)%1000)/10; /* fractional part, two digits after */ |
| | | |
| | | close(fd); |
| | | return 0; |
| | | } |
New file |
| | |
| | | /******************************************************************************** |
| | | * Copyright: (C) 2020 LingYun IoT System Studio |
| | | * All rights reserved. |
| | | * |
| | | * Filename: ds18b20.h |
| | | * Description: This head file is get temperature by DS18B20 on RaspberryPi |
| | | * |
| | | * Version: 1.0.0(2020年04月15日) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "2020年04月15日 23时37分38秒" |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | #ifndef _DS18B20_H_ |
| | | #define _DS18B20_H_ |
| | | |
| | | #include <stdint.h> |
| | | |
| | | /* description: get temperature by DS18B20 on RaspberryPi |
| | | * return value: 0: Successfully <0: Failure |
| | | * output value: $temp: temperature value saved in two bytes: |
| | | * byte[0]: integer part |
| | | * byte[1]: fractional part, two digits after |
| | | */ |
| | | int ds18b20_get_temperature(uint16_t *temp); |
| | | |
| | | #endif /* ----- #ifndef _DS18B20_H_ ----- */ |
| | | |
| | |
| | | |
| | | static unsigned long log_rollback_size = LOG_ROLLBACK_NONE; |
| | | |
| | | /* This library is not thread safe */ |
| | | static logger_t *logger = NULL; |
| | | |
| | | char *log_str[LOG_LEVEL_MAX + 1] = { "", "F", "E", "W", "N", "D", "I", "T", "M" }; |
New file |
| | |
| | | /********************************************************************************* |
| | | * Copyright: (C) 2020 LingYun IoT System Studio |
| | | * All rights reserved. |
| | | * |
| | | * Filename: socket.c |
| | | * Description: This file is for socket API |
| | | * |
| | | * Version: 1.0.0(2020年04月16日) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "2020年04月16日 13时43分28秒" |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | #include "socket.h" |
| | | #include "logger.h" |
| | | |
| | | static int proc_sock_connect(socket_t *sock); |
| | | |
| | | /* description: initialise socket context and create socket fd |
| | | * input args: $sock: socket context |
| | | * $type: SOCK_TYPE_LISTEN, SOCK_TYPE_ACCEPT or SOCK_TYPE_CONNEC |
| | | * $create: call socket() create or not |
| | | * return value: <0: failure 0: successfully |
| | | */ |
| | | int socket_ctx_init(socket_t *sock, uint8_t type, int create) |
| | | { |
| | | int fd = -1; |
| | | |
| | | if( !sock ) |
| | | { |
| | | log_err("Invalid input arguments\n"); |
| | | return -1; |
| | | } |
| | | |
| | | memset(sock, 0, sizeof(*sock)); |
| | | sock->type = type; |
| | | |
| | | sock->keepintvl=600; |
| | | sock->keepcnt = 3; |
| | | |
| | | if( create ) |
| | | { |
| | | fd = socket(AF_INET, SOCK_STREAM, 0); |
| | | if( fd < 0 ) |
| | | { |
| | | log_err("Create socket failure: %s\n", strerror(errno)); |
| | | return -2; |
| | | } |
| | | |
| | | sock->fd = fd; |
| | | } |
| | | else |
| | | { |
| | | sock->fd = -1; |
| | | } |
| | | |
| | | sock->status = SOCK_STAT_INIT; |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | /* description: close socket |
| | | * input args: $sock: socket context |
| | | * return value: <0: failure 0: successfully |
| | | */ |
| | | int socket_close(socket_t *sock) |
| | | { |
| | | int force = 0; |
| | | |
| | | if( !sock ) |
| | | { |
| | | log_err("Invalid input arguments\n"); |
| | | return -1; |
| | | } |
| | | |
| | | if(sock->fd < 0) |
| | | { |
| | | log_nrml("socket already closed\n"); |
| | | return 0; |
| | | } |
| | | |
| | | log_nrml("start close socket[%d] on port[%d] to [%s:%d]\n", sock->fd, sock->lport, sock->raddr, sock->rport); |
| | | |
| | | if(force) |
| | | { |
| | | /* If l_onoff is nonzero and l_linger is zero, TCP aborts the connection when it is closed. |
| | | * That is, TCP discards any data still remaining in the socket send buffer and sends an RST |
| | | * to the peer, not the normal four-packet connection termination sequence. */ |
| | | |
| | | struct linger so_linger; |
| | | so_linger.l_onoff = 1; /* Turn on linger */ |
| | | so_linger.l_linger = 0; /* Set the timeout to 0 */ |
| | | |
| | | setsockopt (sock->fd, SOL_SOCKET, SO_LINGER, (char *) &so_linger, sizeof (struct linger)); |
| | | } |
| | | |
| | | if( SOCK_TYPE_ACCEPT==sock->type || SOCK_TYPE_CONNECT==sock->type ) |
| | | { |
| | | shutdown(sock->fd, SHUT_RDWR); |
| | | } |
| | | |
| | | close(sock->fd); |
| | | |
| | | sock->fd = -1; |
| | | sock->status = SOCK_STAT_INIT; |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | /* description: create socket and listen on port $port |
| | | * input args: $sock: socket context |
| | | * $ipaddr: listen IP address, NULL for any address |
| | | * $port: listen port |
| | | * return value: <0: failure 0: successfully |
| | | */ |
| | | int socket_listen(socket_t *sock, char *ipaddr, int port) |
| | | { |
| | | int rv = 0; |
| | | int fd = -1; |
| | | struct sockaddr_in addr; |
| | | int backlog = 13; |
| | | |
| | | if( !sock ) |
| | | { |
| | | log_err("Invalid input arguments\n"); |
| | | return -1; |
| | | } |
| | | |
| | | if( sock->status != SOCK_STAT_INIT ) |
| | | { |
| | | socket_close(sock); |
| | | } |
| | | |
| | | /* initial listen socket bind address */ |
| | | memset(&addr, 0, sizeof(addr)); |
| | | addr.sin_family = AF_INET; |
| | | addr.sin_port = htons(port); |
| | | if( !ipaddr ) |
| | | { |
| | | addr.sin_addr.s_addr = htons(INADDR_ANY); |
| | | } |
| | | else |
| | | { |
| | | if( !inet_pton(AF_INET, ipaddr, &addr.sin_addr) ) |
| | | { |
| | | log_err("Listen IP address '%s' not valid\n"); |
| | | return -2; |
| | | } |
| | | } |
| | | |
| | | /* initial socket context and create socket fd */ |
| | | if( socket_ctx_init(sock, SOCK_TYPE_LISTEN, SOCK_CREATE) < 0) |
| | | { |
| | | log_err("socket context initial failure\n"); |
| | | return -2; |
| | | } |
| | | |
| | | strncpy(sock->laddr, (!ipaddr?"0.0.0.0":ipaddr), sizeof(sock->laddr)); |
| | | sock->lport = port; |
| | | memset(&sock->raddr, 0, sizeof(sock->raddr)); |
| | | sock->rport = 0; |
| | | |
| | | log_dbg("initial listen socket context ok\n"); |
| | | |
| | | /* set listen port reuseable */ |
| | | socket_set_reuseaddr(sock->fd); |
| | | |
| | | if( bind(sock->fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) |
| | | { |
| | | log_err("bind listen socket failure: %s\n", strerror(errno)); |
| | | rv = -3; |
| | | goto cleanup; |
| | | } |
| | | |
| | | if( listen(sock->fd, backlog) < 0 ) |
| | | { |
| | | log_err("Listen on socket[%d] failed: %s\n", sock->fd, strerror(errno)); |
| | | rv = -4; |
| | | goto cleanup; |
| | | } |
| | | |
| | | log_nrml("create socket and listen on [%s:%d] already\n", sock->laddr, sock->lport); |
| | | |
| | | cleanup: |
| | | if( rv ) |
| | | { |
| | | log_err("Create socket listen on [%s:%d] failed\n", sock->laddr, sock->lport); |
| | | socket_close(sock); |
| | | } |
| | | else |
| | | { |
| | | sock->status = SOCK_STAT_LISTENED; |
| | | log_nrml("Create socket[%p:%d] listen [%s:%d] ok\n", sock, sock->fd, sock->laddr, sock->lport); |
| | | } |
| | | |
| | | return rv; |
| | | } |
| | | |
| | | |
| | | |
| | | /* description: create socket and connect to server |
| | | * input args: $sock: socket context |
| | | * $host: IP address and port, format as "host:port", such as "127.0.0.1:8000" |
| | | * $block: block mode(1) or non-block(0) |
| | | *return value: <0: error 0: connecing in non-block mode 1:connected |
| | | */ |
| | | int socket_connect(socket_t *sock, int lport, char *host, int block) |
| | | { |
| | | int rv = 0; |
| | | char service[20]; |
| | | struct addrinfo hints, *rp; |
| | | struct addrinfo *res = NULL; |
| | | struct in_addr inaddr; |
| | | struct sockaddr_in addr; |
| | | int len = sizeof(addr); |
| | | |
| | | if( !sock ) |
| | | { |
| | | log_err("Invalid input arguments\n"); |
| | | return -1; |
| | | } |
| | | |
| | | /* socket already connected */ |
| | | if( SOCK_STAT_CONNECTED == sock->status ) |
| | | { |
| | | return 1; |
| | | } |
| | | /* socket connecting in none-block mode */ |
| | | else if( SOCK_STAT_CONNECTING == sock->status ) |
| | | { |
| | | log_dbg("socket continue connect to remote server [%s:%d]\n", sock->raddr, sock->rport); |
| | | rv = proc_sock_connect(sock); |
| | | goto out; |
| | | } |
| | | |
| | | /* socket not initial before */ |
| | | if( SOCK_STAT_UNINIT== sock->status ) |
| | | { |
| | | if( socket_ctx_init(sock, SOCK_TYPE_LISTEN, SOCK_NOT_CREATE) < 0) |
| | | { |
| | | log_err("ERROR: initial socket context failure\n"); |
| | | return -2; |
| | | } |
| | | |
| | | if( parser_host_port(sock, host)<0 || sock->rport<=0 ) |
| | | { |
| | | log_err("parser connect server hostname and port [%s] failure\n", host); |
| | | return -3; |
| | | } |
| | | |
| | | if( lport>0 ) |
| | | { |
| | | sock->lport = lport; |
| | | } |
| | | |
| | | log_dbg("initial socket context ok\n"); |
| | | } |
| | | |
| | | log_nrml("start create socket connect to server [%s:%d] now\n", sock->raddr, sock->rport); |
| | | |
| | | |
| | | /*+--------------------------------------------------+ |
| | | *| use getaddrinfo() to do domain name translation | |
| | | *+--------------------------------------------------+*/ |
| | | |
| | | memset(&hints, 0, sizeof(struct addrinfo)); |
| | | hints.ai_family = AF_INET; /* Only support IPv4 */ |
| | | hints.ai_socktype = SOCK_STREAM; |
| | | hints.ai_protocol = IPPROTO_TCP; /* TCP protocol */ |
| | | |
| | | /* If 'raddr' is a valid IP address, then don't use name resolution */ |
| | | if( inet_aton(sock->raddr, &inaddr) ) |
| | | { |
| | | log_info("%s is a valid IP address, don't use domain name resolution.\n", sock->raddr); |
| | | hints.ai_flags |= AI_NUMERICHOST; |
| | | } |
| | | |
| | | /* Obtain address(es) matching host/port */ |
| | | snprintf(service, sizeof(service), "%d", sock->rport); |
| | | if( (rv=getaddrinfo(sock->raddr, service, &hints, &res)) ) |
| | | { |
| | | log_err("getaddrinfo() parser [%s:%s] failed: %s\n", sock->raddr, service, gai_strerror(rv)); |
| | | return -3; |
| | | } |
| | | |
| | | /* close any opened socket on it */ |
| | | socket_close(sock); |
| | | |
| | | /* getaddrinfo() returns a list of address structures. Try each |
| | | address until we successfully connect or bind */ |
| | | for (rp=res; rp!=NULL; rp=rp->ai_next) |
| | | { |
| | | char ipaddr[INET_ADDRSTRLEN]; |
| | | struct sockaddr_in *sp = (struct sockaddr_in *) rp->ai_addr; |
| | | |
| | | |
| | | /* check and print domain name translation result */ |
| | | memset( ipaddr, 0, sizeof(ipaddr) ); |
| | | if( inet_ntop(AF_INET, &sp->sin_addr, ipaddr, sizeof(ipaddr)) ) |
| | | { |
| | | log_nrml("domain name resolution [%s->%s]\n", sock->raddr, ipaddr); |
| | | } |
| | | |
| | | memcpy(&sock->saddr, rp->ai_addr, sizeof(sock->saddr)); |
| | | |
| | | /* 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 = -3; |
| | | continue; |
| | | } |
| | | |
| | | log_info("socket[%d] for connect create ok\n", sock->fd); |
| | | |
| | | /* bind local port to socket if needed */ |
| | | if(sock->lport > 0) |
| | | { |
| | | memset(&addr, 0, len); |
| | | addr.sin_family = AF_INET; |
| | | addr.sin_port = htons ((u_short) sock->lport); |
| | | |
| | | if ( bind(sock->fd, (struct sockaddr *)&addr, len) ) |
| | | { |
| | | rv = -4; |
| | | close(sock->fd); |
| | | log_err("Bind port[%d] to connect socket [%d] failed: %s\n", sock->lport, sock->fd, strerror(errno)); |
| | | continue; |
| | | } |
| | | else |
| | | { |
| | | rv = 0; |
| | | log_dbg("Bind local port[%d] to connect socket [%d] OK\n", lport, sock->fd); |
| | | } |
| | | } |
| | | |
| | | /* Set socket options */ |
| | | if( !block ) |
| | | { |
| | | socket_set_nonblock(sock->fd); |
| | | } |
| | | socket_set_keepalive(sock->fd, sock->keepintvl, sock->keepcnt); |
| | | |
| | | if( (rv=proc_sock_connect(sock)) >= 0 ) |
| | | { |
| | | /* connecting or connected already */ |
| | | break; |
| | | } |
| | | else |
| | | { |
| | | /* socket connect get error, try another IP address */ |
| | | close(sock->fd); |
| | | continue; |
| | | } |
| | | } |
| | | |
| | | freeaddrinfo(res); |
| | | |
| | | out: |
| | | return rv; |
| | | } |
| | | |
| | | /* description: connect() server and check the connect result |
| | | * input args: $sock: socket context |
| | | *return value: <0: Error 0: Connecing in non-block mode 1:Connected |
| | | */ |
| | | static int proc_sock_connect(socket_t *sock) |
| | | { |
| | | int rv; |
| | | int len = sizeof(struct sockaddr); |
| | | |
| | | if( !sock || sock->fd<0 ) |
| | | { |
| | | log_err("Invalid input arguments\n"); |
| | | return -1; |
| | | } |
| | | |
| | | log_nrml("socket[%d] try to connect to server [%s:%d] now...\n", sock->fd, sock->raddr, sock->rport); |
| | | |
| | | rv = connect(sock->fd, &sock->saddr, len); |
| | | if( 0 == rv ) |
| | | { |
| | | sock->status = SOCK_STAT_CONNECTED; |
| | | rv = 1; |
| | | goto out; |
| | | } |
| | | |
| | | /* rv < 0, connect failure will continue to check */ |
| | | switch (errno) |
| | | { |
| | | case EISCONN: |
| | | sock->status = SOCK_STAT_CONNECTED; |
| | | rv = 1; |
| | | break; |
| | | |
| | | case EALREADY: |
| | | case EINPROGRESS: |
| | | sock->status = SOCK_STAT_CONNECTING; |
| | | rv = 0; |
| | | break; |
| | | |
| | | default: |
| | | sock->status = SOCK_STAT_UNINIT; |
| | | rv = -7; |
| | | break; |
| | | } |
| | | |
| | | out: |
| | | if( rv > 0 ) |
| | | { |
| | | log_nrml("socket[%d] connected to remote server [%s:%d]\n", sock->fd, sock->raddr, sock->rport); |
| | | } |
| | | else if ( rv == 0 ) |
| | | { |
| | | log_nrml("socket[%d] connect to remote server [%s:%d] in progressing\n", sock->fd, sock->raddr, sock->rport); |
| | | } |
| | | else |
| | | { |
| | | log_err("socket[%d] connect to remote [%s:%d] failed: %s\n", sock->fd, sock->raddr, sock->rport, strerror(errno)); |
| | | socket_close(sock); |
| | | } |
| | | |
| | | return rv; |
| | | } |
| | | |
| | | |
| | | /* description: accept a new client socket |
| | | * input args: $sock: socket context |
| | | * $listenfd: listen socket fd |
| | | * return value: <0: failure 0: successfully |
| | | */ |
| | | int socket_accept(socket_t *sock, int listenfd) |
| | | { |
| | | if( !sock ) |
| | | { |
| | | log_err("Invalid input arguments\n"); |
| | | return -1; |
| | | } |
| | | |
| | | } |
| | | |
| | | |
| | | /* description: send data to the socket, make sure all data send over. |
| | | * input args: $sock: socket context |
| | | * $data: send data |
| | | * $bytes: data size |
| | | * return value: <0: failure 0: successfully |
| | | */ |
| | | int socket_send(socket_t *sock, char *data, int bytes) |
| | | { |
| | | int rv = 0; |
| | | int i = 0; |
| | | int left_bytes = bytes; |
| | | |
| | | if( !sock || !data || bytes<=0 ) |
| | | { |
| | | log_err("Invalid input arguments\n"); |
| | | return -1; |
| | | } |
| | | |
| | | while( left_bytes > 0 ) |
| | | { |
| | | rv=write(sock->fd, &data[i], left_bytes); |
| | | if( rv < 0 ) |
| | | { |
| | | log_info("socket[%d] write() failure: %s, close socket now\n", sock->fd, strerror(errno)); |
| | | socket_close(sock); |
| | | return -2; |
| | | } |
| | | else if( rv == left_bytes ) |
| | | { |
| | | log_info("socket send %d bytes data over\n", bytes); |
| | | return 0; |
| | | } |
| | | else |
| | | { |
| | | /* not send over this time, continue to send left data */ |
| | | i += rv; |
| | | left_bytes -= rv; |
| | | continue; |
| | | } |
| | | } |
| | | } |
| | | |
| | | /* description: receive data from the socket in some time |
| | | * input args: $sock: socket context |
| | | * $data: send data |
| | | * $bytes: data size |
| | | * $timeout: receive data time, <=0 will don't timeout |
| | | * return value: <0: error >=0: receive data bytes; |
| | | */ |
| | | int socket_recv(socket_t *sock, char *buf, int size, int timeout) |
| | | { |
| | | int rv = 0; |
| | | int i = 0; |
| | | fd_set fdsr; |
| | | int maxsock; |
| | | |
| | | if( !sock || sock->fd<0 || !buf ||size<=0 ) |
| | | { |
| | | log_err("Invalid input arguments\n"); |
| | | return -1; |
| | | } |
| | | |
| | | memset(buf, 0, size); |
| | | |
| | | maxsock = sock->fd; |
| | | |
| | | FD_ZERO(&fdsr); |
| | | FD_SET(sock->fd, &fdsr); |
| | | |
| | | if( timeout <= 0 ) /* no timeout */ |
| | | { |
| | | rv=select(maxsock+1, &fdsr, NULL, NULL, NULL); |
| | | } |
| | | else |
| | | { |
| | | struct timeval tv; |
| | | |
| | | tv.tv_sec = timeout; |
| | | tv.tv_usec = 0; |
| | | rv=select(maxsock+1, &fdsr, NULL, NULL, &tv); |
| | | } |
| | | |
| | | |
| | | if( rv < 0 ) |
| | | { |
| | | log_err("select() read from socket[%d] failure: %s\n", sock->fd, strerror(errno)); |
| | | return -2; |
| | | } |
| | | else if( rv == 0 ) |
| | | { |
| | | log_err("select() read from socket[%d] get timeout\n", sock->fd); |
| | | return 0; |
| | | } |
| | | else |
| | | { |
| | | rv = read(sock->fd, buf, size); |
| | | if( rv < 0 ) |
| | | { |
| | | log_err("socket[%d] read() failure: %s, close socket now\n", sock->fd, strerror(errno)); |
| | | socket_close(sock); |
| | | return -2; |
| | | } |
| | | else if( rv == 0 ) |
| | | { |
| | | log_err("socket[%d] read() get peer disconnect, close socket now\n", sock->fd); |
| | | socket_close(sock); |
| | | return -2; |
| | | } |
| | | else |
| | | { |
| | | log_dbg("socket[%d] receive %d bytes data\n", sock->fd, rv); |
| | | logger_dump(LOG_LEVEL_INFO, buf, rv); |
| | | return rv; |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /* description: parser hostname and port from $host and set it into $sock |
| | | * input args: $sock: socket context |
| | | * $host: connect hostname, format as "hostname:port" |
| | | */ |
| | | int parser_host_port(socket_t *sock, char *host) |
| | | { |
| | | char *ptr = NULL; |
| | | int len = 0; |
| | | |
| | | if( !sock || !host ) |
| | | { |
| | | log_err("Invalid input arguments\n"); |
| | | return -1; |
| | | } |
| | | |
| | | ptr = strchr(host, ':'); |
| | | |
| | | if( !ptr ) |
| | | { |
| | | log_err("Invalid arguments for host, format should be 'hostname:port'\n"); |
| | | return -1; |
| | | } |
| | | |
| | | len = ptr-host; |
| | | if( len > sizeof(sock->raddr) ) |
| | | len = sizeof(sock->raddr); |
| | | |
| | | memcpy(sock->raddr, host, ptr-host); |
| | | sock->rport = atoi(ptr+1); |
| | | |
| | | log_info("paser host[%s] to '%s:%d'\n", host, sock->raddr, sock->rport); |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | |
| | | int socket_set_reuseaddr(int sockfd) |
| | | { |
| | | int opt = 1; |
| | | int len = sizeof (int); |
| | | |
| | | if (setsockopt (sockfd, SOL_SOCKET, SO_REUSEADDR, (void *) &opt, len)) |
| | | { |
| | | log_err("Set socket[%d] option SO_REUSEADDR failed:%s\n", sockfd, strerror(errno)); |
| | | return -1; |
| | | } |
| | | log_dbg("Set socket[%d] option SO_REUSEADDR ok\n", sockfd); |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | |
| | | int socket_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; |
| | | } |
| | | |
| | | int socket_set_buffer(int sockfd, int rsize, int ssize) |
| | | { |
| | | int opt; |
| | | socklen_t optlen = sizeof(opt); |
| | | |
| | | if(sockfd < 0) |
| | | return -1; |
| | | |
| | | /* Get system default receive buffer size, Linux X86: 85K */ |
| | | if (getsockopt (sockfd, SOL_SOCKET, SO_RCVBUF, (char *) &opt, &optlen)) |
| | | { |
| | | log_warn("getsockopt() get receive buffer failure: %s\n", strerror(errno)); |
| | | return -2; |
| | | } |
| | | |
| | | /* Only when current receive buffer size larger than the default one will change it */ |
| | | if(rsize > opt) |
| | | { |
| | | opt = (int) rsize; |
| | | if (setsockopt (sockfd, SOL_SOCKET, SO_RCVBUF, (char *) &opt, optlen)) |
| | | { |
| | | log_warn("setsockopt() set receive buffer to %d failure: %s\n", opt, strerror(errno)); |
| | | return -2; |
| | | } |
| | | } |
| | | |
| | | /* Get system default send buffer size, Linux X86: 16K */ |
| | | if (getsockopt (sockfd, SOL_SOCKET, SO_SNDBUF, (char *) &opt, &optlen)) |
| | | { |
| | | log_warn("getsockopt() get send buffer failure: %s\n", strerror(errno)); |
| | | return -3; |
| | | } |
| | | |
| | | /* Only when current receive buffer size larger than the default one will change it */ |
| | | if(ssize > opt) |
| | | { |
| | | opt = (int) ssize; |
| | | if (setsockopt (sockfd, SOL_SOCKET, SO_SNDBUF, (char *) &opt, optlen)) |
| | | { |
| | | log_warn("setsockopt() set send buffer to %d failure: %s\n", opt, strerror(errno)); |
| | | return -3; |
| | | } |
| | | } |
| | | |
| | | log_info("Set socket[%d] RCVBUF size:%d SNDBUF size:%d\n", sockfd, rsize, ssize); |
| | | return 0; |
| | | } |
| | | |
| | | /* |
| | | * Enable socket SO_KEEPALIVE, if the connection disconnected, any system call on socket |
| | | * will return immediately and errno will be set to "WSAENOTCONN" |
| | | * |
| | | * keepalive is not program related, but socket related, * so if you have multiple sockets, |
| | | * you can handle keepalive for each of them separately. |
| | | * |
| | | * Reference: http://tldp.org/HOWTO/html_single/TCP-Keepalive-HOWTO/ |
| | | */ |
| | | int socket_set_keepalive(int sockfd, int keepintvl, int keepcnt) |
| | | { |
| | | int opt; |
| | | |
| | | if(sockfd < 0) |
| | | return -1; |
| | | |
| | | /* Enable the KEEPALIVE flag */ |
| | | opt = 1; |
| | | if (setsockopt (sockfd, SOL_SOCKET, SO_KEEPALIVE, (char *) &opt, sizeof (opt))) |
| | | { |
| | | log_warn("setsockopt() enable SO_KEEPALIVE failure: %s\n", strerror(errno)); |
| | | return -2; |
| | | } |
| | | |
| | | if(keepintvl || keepcnt) |
| | | { |
| | | /* |
| | | * The tcp_keepidle parameter specifies the interval between the last data packet sent |
| | | * (simple ACKs are not considered data) and the first keepalive probe; after the |
| | | * connection is marked to need keepalive, this counter is not used any further. |
| | | * ~ >: cat /proc/sys/net/ipv4/tcp_keepalive_time |
| | | * 7200 |
| | | */ |
| | | opt = 3; /* 3 seconds */ |
| | | if (setsockopt (sockfd, SOL_TCP, TCP_KEEPIDLE, (char *) &opt, sizeof (opt))) |
| | | { |
| | | log_err("setsockopt() set TCP_KEEPIDLE to %d seconds failure: %s\n", opt, strerror(errno)); |
| | | return -3; |
| | | } |
| | | |
| | | if((opt=keepintvl) > 0) |
| | | { |
| | | /* |
| | | * The tcp_keepintvl parameter specifies the interval between subsequential keepalive |
| | | * probes, regardless of what the connection has exchanged in the meantime. |
| | | * ~ >: cat /proc/sys/net/ipv4/tcp_keepalive_intvl |
| | | * 75 |
| | | */ |
| | | if (setsockopt (sockfd, SOL_TCP, TCP_KEEPINTVL, (char *) &opt, sizeof (opt))) |
| | | { |
| | | log_err("setsockopt() set TCP_KEEPINTVL to %d failure: %s\n", opt, strerror(errno)); |
| | | return -4; |
| | | } |
| | | } |
| | | |
| | | if((opt=keepcnt) > 0) |
| | | { |
| | | /* |
| | | * The TCP_KEEPCNT option specifies the maximum number of unacknowledged probes to |
| | | * send before considering the connection dead and notifying the application layer |
| | | * probes to be sent. The value of TCP_KEEPCNT is an integer value between 1 and n, |
| | | * where n is the value of the systemwide tcp_keepcnt parameter. |
| | | * ~ >: cat /proc/sys/net/ipv4/tcp_keepalive_probes |
| | | * 9 |
| | | */ |
| | | if (setsockopt (sockfd, SOL_TCP, TCP_KEEPCNT, (char *) &opt, sizeof (opt))) |
| | | { |
| | | log_err("setsockopt() set TCP_KEEPCNT to %d failure: %s\n", opt, strerror(errno)); |
| | | return -5; |
| | | } |
| | | } |
| | | } |
| | | |
| | | log_dbg("Set socket[%d] KEEPINTVL:%d KEEPCNT:%d\n", sockfd, keepintvl, keepcnt); |
| | | return 0; |
| | | } |
| | | |
| | | |
New file |
| | |
| | | /******************************************************************************** |
| | | * Copyright: (C) 2020 LingYun IoT System Studio |
| | | * All rights reserved. |
| | | * |
| | | * Filename: socket.h |
| | | * Description: This head file is for socket API |
| | | * |
| | | * Version: 1.0.0(2020年04月16日) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "2020年04月16日 13时45分33秒" |
| | | * |
| | | ********************************************************************************/ |
| | | #ifndef _SOCKET_H_ |
| | | #define _SOCKET_H_ |
| | | |
| | | #include <stdio.h> |
| | | #include <stdlib.h> |
| | | #include <stdint.h> |
| | | #include <netdb.h> |
| | | #include <fcntl.h> |
| | | #include <unistd.h> |
| | | #include <sys/un.h> |
| | | #include <poll.h> |
| | | #include <errno.h> |
| | | |
| | | #include <sys/types.h> |
| | | #include <sys/socket.h> |
| | | #include <linux/sockios.h> |
| | | #include <sys/ioctl.h> |
| | | #include <sys/socket.h> |
| | | #include <netinet/in.h> |
| | | #include <netinet/tcp.h> |
| | | #include <arpa/inet.h> |
| | | |
| | | #define HOSTNAME_LEN 128 |
| | | |
| | | enum |
| | | { |
| | | SOCK_TYPE_LISTEN, /* listen socket */ |
| | | SOCK_TYPE_ACCEPT, /* accept socket */ |
| | | SOCK_TYPE_CONNECT, /* connect socket */ |
| | | }; |
| | | |
| | | enum |
| | | { |
| | | SOCK_STAT_UNINIT = 0, /* socket not initial */ |
| | | SOCK_STAT_INIT = 1, /* socket initialed */ |
| | | |
| | | SOCK_STAT_CONNECTING = 2, /* socket connecting in non-block mode */ |
| | | |
| | | SOCK_STAT_CONNECTED = 3, /* socket connected in client mdoe */ |
| | | SOCK_STAT_LISTENED = 3, /* socket listened in server mode */ |
| | | SOCK_STAT_ACCEPTED = 3, /* socket already accepted */ |
| | | }; |
| | | |
| | | typedef struct socket_s |
| | | { |
| | | int fd; /* socket fd */ |
| | | uint8_t type; /* socket type: listen, accept or accept */ |
| | | uint8_t status; /* socket status: SOCK_STAT_INIT,SOCK_STAT_CONNECTED... */ |
| | | |
| | | /* socket server/client IP address and port */ |
| | | char raddr[HOSTNAME_LEN]; /* remote IP address or domain name */ |
| | | char laddr[HOSTNAME_LEN]; /* local IP address */ |
| | | uint16_t lport; /* local listen port */ |
| | | uint16_t rport; /* remote connected port */ |
| | | |
| | | /* socket heartbeat settings */ |
| | | int keepintvl; /* keepalive detect interval */ |
| | | int keepcnt; /* keepalive count */ |
| | | |
| | | struct sockaddr saddr; /* sockaddr for connect */ |
| | | } socket_t; |
| | | |
| | | |
| | | /*+-------------------------------------------------------------------+ |
| | | *| client/server socket API functions | |
| | | *+-------------------------------------------------------------------+*/ |
| | | |
| | | /* description: initialise socket context and create socket fd if sepecified |
| | | * input args: $sock: socket context |
| | | * $type: SOCK_TYPE_LISTEN, SOCK_TYPE_ACCEPT or SOCK_TYPE_CONNEC |
| | | * $create: call socket() create or not |
| | | * return value: <0: failure 0: successfully |
| | | */ |
| | | enum |
| | | { |
| | | SOCK_NOT_CREATE, |
| | | SOCK_CREATE, |
| | | }; |
| | | int socket_ctx_init(socket_t *sock, uint8_t type, int create); |
| | | |
| | | |
| | | /* description: close socket and set socket status as SOCK_STAT_INIT |
| | | * input args: $sock: socket context |
| | | * return value: <0: failure 0: successfully |
| | | */ |
| | | int socket_close(socket_t *sock); |
| | | |
| | | |
| | | /* description: close socket |
| | | * input args: $sock: socket context |
| | | * $lport: specify use local port $lport to connect remote server |
| | | * $host: IP address and port, format as "host:port", such as "127.0.0.1:8000" |
| | | * $block: block mode(1) or none-block(0) |
| | | *return value: <0: error 0: connecing in non-block mode 1:connected |
| | | */ |
| | | enum |
| | | { |
| | | MODE_NONBLOCK, |
| | | MODE_BLOCK, |
| | | }; |
| | | int socket_connect(socket_t *sock, int lport, char *host, int block); |
| | | |
| | | |
| | | /* description: create socket and listen on port $port |
| | | * input args: $sock: socket context |
| | | * $ip: listen IP address, NULL for any address |
| | | * $port: listen port |
| | | * return value: <0: failure 0: successfully |
| | | */ |
| | | int socket_listen(socket_t *sock, char *ipaddr, int port); |
| | | |
| | | |
| | | /* description: accept a new client socket |
| | | * input args: $sock: socket context |
| | | * $listenfd: listen socket fd |
| | | * return value: <0: failure 0: successfully |
| | | */ |
| | | int socket_accept(socket_t *sock, int listenfd); |
| | | |
| | | /* description: send data to the socket, make sure all data send over. |
| | | * input args: $sock: socket context |
| | | * $data: send data |
| | | * $bytes: data size |
| | | * return value: <0: failure 0: successfully |
| | | */ |
| | | int socket_send(socket_t *sock, char *data, int bytes); |
| | | |
| | | |
| | | /* description: receive data from the socket in some time |
| | | * input args: $sock: socket context |
| | | * $data: send data |
| | | * $bytes: data size |
| | | * $timeout: receive data time, <=0 will don't timeout |
| | | * return value: <0: error >=0: receive data bytes; |
| | | */ |
| | | int socket_recv(socket_t *sock, char *buf, int size, int timeout); |
| | | |
| | | |
| | | /*+-------------------------------------------------------------------+ |
| | | *| socket utils function | |
| | | *+-------------------------------------------------------------------+*/ |
| | | |
| | | /* description: parser hostname and port from $host and set it into $sock |
| | | * input args: $sock: socket context |
| | | * $host: connect hostname, format as "hostname:port" |
| | | */ |
| | | int parser_host_port(socket_t *sock, char *host); |
| | | |
| | | |
| | | /* description: set socket listen port as reusable, fix port already used bug */ |
| | | int socket_set_reuseaddr(int sockfd); |
| | | |
| | | /* set socket as non-block mode, common socket default work as block mode */ |
| | | int socket_set_nonblock(int sockfd); |
| | | |
| | | /* set socket receive and send buffer size in linux kernel space */ |
| | | int socket_set_buffer(int sockfd, int rsize, int ssize); |
| | | |
| | | /* set heartbeat keepalive */ |
| | | int socket_set_keepalive(int sockfd, int keepintvl, int keepcnt); |
| | | |
| | | |
| | | #endif /* ----- #ifndef _SOCKET_H_ ----- */ |
| | | |
| | |
| | | !_TAG_PROGRAM_NAME Exuberant Ctags // |
| | | !_TAG_PROGRAM_URL http://ctags.sourceforge.net /official site/ |
| | | !_TAG_PROGRAM_VERSION 5.9~svn20110310 // |
| | | BUFSIZE tlv_sample.c 21;" d file: |
| | | CHARS_PER_LINE logger.c 334;" d file: |
| | | CHARS_PER_LINE tlv_sample.c 156;" d file: |
| | | CHARS_PER_LINE logger.c 335;" d file: |
| | | CHARS_PER_LINE tlv_pack.c 102;" d file: |
| | | CRC_ITU_T_H crc-itu-t.h 14;" d |
| | | DBG_LOG_FILE logger.h 35;" d |
| | | DEFAULT_TIME_FORMAT logger.h 40;" d |
| | |
| | | FLAG_LOGGER_CONSOLE logger.h 63;" d |
| | | FLAG_LOGGER_FILE logger.h 64;" d |
| | | FLAG_LOGGER_LEVEL_OPT logger.h 61;" d |
| | | LINELEN logger.c 333;" d file: |
| | | LINELEN tlv_sample.c 155;" d file: |
| | | LINELEN logger.c 334;" d file: |
| | | LINELEN tlv_pack.c 101;" d file: |
| | | LOG_FILE_LINE logger.h 92;" d |
| | | LOG_LEVEL_DEBUG logger.h /^ LOG_LEVEL_DEBUG, \/* Debug Level "Debug" *\/$/;" e enum:__anon1 |
| | | LOG_LEVEL_DISB logger.h /^ LOG_LEVEL_DISB = 0, \/* Disable "Debug" *\/$/;" e enum:__anon1 |
| | |
| | | LOG_LEVEL_WARN logger.h /^ LOG_LEVEL_WARN, \/* Debug Level "warnning" *\/$/;" e enum:__anon1 |
| | | LOG_ROLLBACK_NONE logger.h 38;" d |
| | | LOG_ROLLBACK_SIZE logger.h 37;" d |
| | | LOG_TIME_FMT logger.c 24;" d file: |
| | | LOG_TIME_FMT logger.c 25;" d file: |
| | | LOG_VERSION_STR logger.h 29;" d |
| | | MAGIC_CRC crc-itu-t.h 16;" d |
| | | MAX_LOG_MESSAGE_LEN logger.h 41;" d |
| | | OFF tlv_sample.c 18;" d file: |
| | | ON tlv_sample.c 19;" d file: |
| | | PACK_HEADER tlv_sample.c 30;" d file: |
| | | PACK_HEADER tlv_pack.h 26;" d |
| | | PID_ASCII_SIZE proc.h 18;" d |
| | | PRECISE_TIME_FACTOR logger.c 16;" d file: |
| | | TAG_CAMERA tlv_sample.c /^ TAG_CAMERA,$/;" e enum:__anon2 file: |
| | | TAG_LED tlv_sample.c /^ TAG_LED,$/;" e enum:__anon2 file: |
| | | TAG_LOGON tlv_sample.c /^ TAG_LOGON=1,$/;" e enum:__anon2 file: |
| | | TLV_FIXED_SIZE tlv_sample.c 41;" d file: |
| | | TLV_MIN_SIZE tlv_sample.c 44;" d file: |
| | | TAG_ACK tlv_pack.h /^ TAG_ACK=1,$/;" e enum:__anon2 |
| | | TAG_SN tlv_pack.h /^ TAG_SN,$/;" e enum:__anon2 |
| | | TAG_TEMP tlv_pack.h /^ TAG_TEMP,$/;" e enum:__anon2 |
| | | TAG_TIME tlv_pack.h /^ TAG_TIME,$/;" e enum:__anon2 |
| | | TLV_BUFSIZE tlv_pack.h 44;" d |
| | | TLV_FIXED_SIZE tlv_pack.h 29;" d |
| | | TLV_MIN_SIZE tlv_pack.h 32;" d |
| | | _DS18B20_H_ ds18b20.h 15;" d |
| | | _LOGGER_H_ logger.h 15;" d |
| | | _PROC_H_ proc.h 15;" d |
| | | _TLV_PACK_H_ tlv_pack.h 14;" d |
| | | _curOffset logger.c /^ long _curOffset = ftell(logger->fp);$/;" l |
| | | act logger.c /^ struct sigaction act;$/;" l |
| | | argp logger.c /^ va_list argp;$/;" l |
| | | args proc.c /^ va_list args;$/;" l |
| | | buf ds18b20.c /^ char buf[128];$/;" l |
| | | buf logger.c /^ char buf[MAX_LOG_MESSAGE_LEN];$/;" l |
| | | buf tlv_sample.c /^ char buf[BUFSIZE];$/;" l |
| | | bytes tlv_sample.c /^ int bytes;$/;" l |
| | | buf tlv_pack.h /^ char buf[TLV_BUFSIZE];$/;" m struct:tlv_buf_s access:public |
| | | byte ds18b20.c /^ uint8_t *byte;$/;" l |
| | | bytes_to_ushort crc-itu-t.c /^unsigned short bytes_to_ushort(unsigned char *bytes, int len)$/;" f signature:(unsigned char *bytes, int len) |
| | | bytes_to_ushort crc-itu-t.h /^extern unsigned short bytes_to_ushort(unsigned char *bytes, int len);$/;" p signature:(unsigned char *bytes, int len) |
| | | c logger.c /^ unsigned char c = buf[idx];$/;" l |
| | | c tlv_sample.c /^ unsigned char c = data[idx];$/;" l |
| | | c tlv_pack.c /^ unsigned char c = data[idx];$/;" l |
| | | check_and_rollback logger.c /^static void check_and_rollback(void)$/;" f file: signature:(void) |
| | | check_daemon_running proc.c /^int check_daemon_running(const char *pid_file)$/;" f signature:(const char *pid_file) |
| | | check_daemon_running proc.h /^extern int check_daemon_running(const char *pid_file);$/;" p signature:(const char *pid_file) |
| | | chip ds18b20.c /^ char chip[20];$/;" l |
| | | chmod proc.c /^ (void)chmod(ipc_dir, mode); $/;" p file: |
| | | cmd logger.c /^ char cmd[512];$/;" l |
| | | cmd proc.c /^ char cmd[256];$/;" l |
| | | cp_install_proc_signal proc.c /^void cp_install_proc_signal(void)$/;" f signature:(void) |
| | | cp_install_proc_signal proc.h /^extern void cp_install_proc_signal(void);$/;" p signature:(void) |
| | | cp_printout logger.c /^static void cp_printout(char *level, char *fmt, va_list argp)$/;" f file: signature:(char *level, char *fmt, va_list argp) |
| | | cp_printout_line logger.c /^static void cp_printout_line(char *level, char *fmt, char *file, int line, va_list argp)$/;" f file: signature:(char *level, char *fmt, char *file, int line, va_list argp) |
| | | cp_proc_sighandler proc.c /^void cp_proc_sighandler(int sig)$/;" f signature:(int sig) |
| | | crc16 tlv_sample.c /^ unsigned short crc16 = 0;$/;" l |
| | | crc16 tlv_sample.c /^ unsigned short crc16;$/;" l |
| | | crc16 tlv_pack.c /^ unsigned short crc16 = 0;$/;" l |
| | | crc16 tlv_pack.c /^ unsigned short crc16;$/;" l |
| | | crc_itu_t crc-itu-t.c /^unsigned short crc_itu_t(unsigned short crc, const unsigned char *buffer, unsigned int len)$/;" f signature:(unsigned short crc, const unsigned char *buffer, unsigned int len) |
| | | crc_itu_t crc-itu-t.h /^extern unsigned short crc_itu_t(unsigned short magic_crc, const unsigned char *buffer, unsigned int len);$/;" p signature:(unsigned short magic_crc, const unsigned char *buffer, unsigned int len) |
| | | crc_itu_t_byte crc-itu-t.h /^static inline unsigned short crc_itu_t_byte(unsigned short crc, const unsigned char data)$/;" f signature:(unsigned short crc, const unsigned char data) |
| | |
| | | crc_itu_t_table crc-itu-t.h /^extern const unsigned short crc_itu_t_table[256];$/;" x |
| | | daemonize proc.c /^void daemonize(int nochdir, int noclose)$/;" f signature:(int nochdir, int noclose) |
| | | daemonize proc.h /^extern void daemonize(int nochdir, int noclose);$/;" p signature:(int nochdir, int noclose) |
| | | data_len tlv_sample.c /^ int data_len = 0;$/;" l |
| | | direntp ds18b20.c /^ struct dirent *direntp;$/;" l |
| | | dirp ds18b20.c /^ DIR *dirp;$/;" l |
| | | done proc.c /^ int done; $/;" l |
| | | dump_buf tlv_sample.c /^void dump_buf(char *data, int len)$/;" f signature:(char *data, int len) |
| | | dump_buf tlv_sample.c /^void dump_buf(char *data, int len);$/;" p file: signature:(char *data, int len) |
| | | ds18b20_get_temperature ds18b20.c /^int ds18b20_get_temperature(uint16_t *temp)$/;" f signature:(uint16_t *temp) |
| | | ds18b20_get_temperature ds18b20.h /^int ds18b20_get_temperature(uint16_t *temp);$/;" p signature:(uint16_t *temp) |
| | | dump_buf tlv_pack.c /^void dump_buf(char *data, int len)$/;" f signature:(char *data, int len) |
| | | dump_buf tlv_pack.h /^void dump_buf(char *data, int len);$/;" p signature:(char *data, int len) |
| | | exec_system_cmd proc.c /^void exec_system_cmd(const char *format, ...)$/;" f signature:(const char *format, ...) |
| | | exec_system_cmd proc.h /^extern void exec_system_cmd(const char *format, ...);$/;" p signature:(const char *format, ...) |
| | | f proc.c /^ FILE *f; $/;" l |
| | |
| | | fStatBuf proc.c /^ struct stat fStatBuf; $/;" l |
| | | fStatBuf proc.c /^ struct stat fStatBuf;$/;" l |
| | | fclose proc.c /^ (void)fclose(f); $/;" p file: |
| | | fd ds18b20.c /^ int fd =-1;$/;" l |
| | | fd proc.c /^ int fd = -1; $/;" l |
| | | fd proc.c /^ int retval, fd; $/;" l |
| | | fgets proc.c /^ (void)fgets(pid_ascii, PID_ASCII_SIZE, f); $/;" p file: |
| | | file logger.h /^ char file[FILENAME_LEN];$/;" m struct:logger_s access:public |
| | | filemode logger.c /^ char *filemode;$/;" l |
| | | flag logger.h /^ unsigned char flag;$/;" m struct:logger_s access:public |
| | | found ds18b20.c /^ int found = 0;$/;" l |
| | | fp logger.h /^ FILE *fp;$/;" m struct:logger_s access:public |
| | | g_signal proc.c /^proc_signal_t g_signal={0};$/;" v |
| | | g_signal proc.h /^extern proc_signal_t g_signal;$/;" x |
| | | get_daemon_pid proc.c /^pid_t get_daemon_pid(const char *pid_file)$/;" f signature:(const char *pid_file) |
| | | get_daemon_pid proc.h /^extern pid_t get_daemon_pid(const char *pid_file);$/;" p signature:(const char *pid_file) |
| | | hc logger.c /^ char hc[4];$/;" l |
| | | hc tlv_sample.c /^ char hc[4];$/;" l |
| | | hc tlv_pack.c /^ char hc[4];$/;" l |
| | | i crc-itu-t.c /^ int i = 0;$/;" l |
| | | i crc-itu-t.c /^ int i = 0;$/;" l |
| | | i proc.c /^ int i; $/;" l |
| | | idx logger.c /^ int idx;$/;" l |
| | | idx tlv_sample.c /^ int idx;$/;" l |
| | | idx tlv_pack.c /^ int idx;$/;" l |
| | | install_proc_signal proc.c /^void install_proc_signal(void)$/;" f signature:(void) |
| | | install_proc_signal proc.h /^extern void install_proc_signal(void);$/;" p signature:(void) |
| | | ipc_dir proc.c /^ char ipc_dir[64] = { 0 }; $/;" l |
| | | ldx logger.c /^ int ldx = idx % CHARS_PER_LINE;$/;" l |
| | | len tlv_pack.h /^ int len;$/;" m struct:tlv_buf_s access:public |
| | | level logger.h /^ int level;$/;" m struct:logger_s access:public |
| | | line_done logger.c /^ short line_done = 1;$/;" l |
| | | line_done tlv_sample.c /^ short line_done = 1;$/;" l |
| | | line_done tlv_pack.c /^ short line_done = 1;$/;" l |
| | | lit logger.c /^ char lit[CHARS_PER_LINE + 2];$/;" l |
| | | lit tlv_sample.c /^ char lit[CHARS_PER_LINE + 1];$/;" l |
| | | lit tlv_pack.c /^ char lit[CHARS_PER_LINE + 1];$/;" l |
| | | local logger.c /^ struct tm *local;$/;" l |
| | | log_dbg logger.h 105;" d |
| | | log_dbg logger.h 97;" d |
| | |
| | | logger_t logger.h /^} logger_t;$/;" t typeref:struct:logger_s |
| | | logger_term logger.c /^void logger_term(void)$/;" f signature:(void) |
| | | logger_term logger.h /^extern void logger_term(void);$/;" p signature:(void) |
| | | main tlv_sample.c /^int main(int argc, char **argv)$/;" f signature:(int argc, char **argv) |
| | | mode proc.c /^ int mode = S_IROTH | S_IXOTH | S_IRGRP | S_IXGRP | S_IRWXU;$/;" l |
| | | now logger.c /^ struct timeval now;$/;" l |
| | | ofset tlv_sample.c /^ int ofset = 0; \/* index position for the buf *\/$/;" l |
| | | pack_len tlv_sample.c /^ int pack_len = 0;$/;" l |
| | | pack_len tlv_sample.c /^ int pack_len = TLV_FIXED_SIZE+1; \/* Only 1 byte data *\/$/;" l |
| | | packtlv_led tlv_sample.c /^int packtlv_led(char *buf, int size, int cmd)$/;" f signature:(char *buf, int size, int cmd) |
| | | packtlv_led tlv_sample.c /^int packtlv_led(char *buf, int size, int cmd);$/;" p file: signature:(char *buf, int size, int cmd) |
| | | packtlv_logon tlv_sample.c /^int packtlv_logon(char *buf, int size, char *pwd)$/;" f signature:(char *buf, int size, char *pwd) |
| | | packtlv_logon tlv_sample.c /^int packtlv_logon(char *buf, int size, char *pwd);$/;" p file: signature:(char *buf, int size, char *pwd) |
| | | ofset tlv_pack.c /^ int ofset = 0; \/* index position for the buf *\/$/;" l |
| | | pack_len tlv_pack.c /^ int pack_len = 0;$/;" l |
| | | pack_len tlv_pack.c /^ int pack_len = TLV_FIXED_SIZE+1; \/* Only 1 byte data *\/$/;" l |
| | | packtlv_ack tlv_pack.c /^int packtlv_ack(char *buf, int size, int ack)$/;" f signature:(char *buf, int size, int ack) |
| | | packtlv_ack tlv_pack.h /^int packtlv_ack (char *buf, int size, int ack);$/;" p signature:(char *buf, int size, int ack) |
| | | packtlv_led tlv_pack.c /^int packtlv_led(char *buf, int size, int cmd)$/;" f signature:(char *buf, int size, int cmd) |
| | | packtlv_msg tlv_pack.h /^int packtlv_msg(tlv_buf_t *tlv, char *sn, uint16_t temp, struct tm *tm);$/;" p signature:(tlv_buf_t *tlv, char *sn, uint16_t temp, struct tm *tm) |
| | | packtlv_sn tlv_pack.h /^int packtlv_sn (char *buf, int size, char *sn);$/;" p signature:(char *buf, int size, char *sn) |
| | | packtlv_temp tlv_pack.h /^int packtlv_temp(char *buf, int size, uint16_t temp);$/;" p signature:(char *buf, int size, uint16_t temp) |
| | | packtlv_time tlv_pack.h /^int packtlv_time(char *buf, int size, struct tm *tm);$/;" p signature:(char *buf, int size, struct tm *tm) |
| | | pid proc.c /^ char pid[PID_ASCII_SIZE]; $/;" l |
| | | pid proc.c /^ pid_t pid = -1; $/;" l |
| | | pid proc.c /^ pid_t pid = -1; $/;" l |
| | | pid proc.c /^ pid_t pid; $/;" l |
| | | pid_ascii proc.c /^ char pid_ascii[PID_ASCII_SIZE]; $/;" l |
| | | print_char logger.c /^static char *print_char =$/;" v file: |
| | | print_char tlv_sample.c /^static char *print_char =$/;" v file: |
| | | print_char tlv_pack.c /^static char *print_char =$/;" v file: |
| | | prn logger.c /^ char prn[LINELEN];$/;" l |
| | | prn tlv_sample.c /^ char prn[LINELEN];$/;" l |
| | | prn tlv_pack.c /^ char prn[LINELEN];$/;" l |
| | | proc_sighandler proc.c /^void proc_sighandler(int sig)$/;" f signature:(int sig) |
| | | proc_signal_s proc.h /^typedef struct proc_signal_s$/;" s |
| | | proc_signal_s::signal proc.h /^ int signal;$/;" m struct:proc_signal_s access:public |
| | | proc_signal_s::stop proc.h /^ unsigned stop; \/* 0: Not term 1: Stop *\/$/;" m struct:proc_signal_s access:public |
| | | proc_signal_s::threads proc.h /^ int threads; \/* threads counter *\/$/;" m struct:proc_signal_s access:public |
| | | proc_signal_t proc.h /^} proc_signal_t;$/;" t typeref:struct:proc_signal_s |
| | | ptr ds18b20.c /^ char *ptr;$/;" l |
| | | rc logger.c /^ int rc = 0;$/;" l |
| | | rc logger.c /^ int rc;$/;" l |
| | | rc tlv_sample.c /^ int rc;$/;" l |
| | | rc tlv_pack.c /^ int rc;$/;" l |
| | | record_daemon_pid proc.c /^int record_daemon_pid(const char *pid_file)$/;" f signature:(const char *pid_file) |
| | | record_daemon_pid proc.h /^extern int record_daemon_pid(const char *pid_file);$/;" p signature:(const char *pid_file) |
| | | retVal proc.c /^ int retVal = -1; $/;" l |
| | |
| | | thread_stop proc.h /^extern void thread_stop(char *prompt);$/;" p signature:(char *prompt) |
| | | threads proc.h /^ int threads; \/* threads counter *\/$/;" m struct:proc_signal_s access:public |
| | | timestr logger.c /^ char timestr[256];$/;" l |
| | | tlv_buf_s tlv_pack.h /^typedef struct tlv_buf_s $/;" s |
| | | tlv_buf_s::buf tlv_pack.h /^ char buf[TLV_BUFSIZE];$/;" m struct:tlv_buf_s access:public |
| | | tlv_buf_s::len tlv_pack.h /^ int len;$/;" m struct:tlv_buf_s access:public |
| | | tlv_buf_t tlv_pack.h /^} tlv_buf_t; $/;" t typeref:struct:tlv_buf_s |
| | | ushort_to_bytes crc-itu-t.c /^int ushort_to_bytes(unsigned char *bytes, unsigned short val)$/;" f signature:(unsigned char *bytes, unsigned short val) |
| | | ushort_to_bytes crc-itu-t.h /^extern int ushort_to_bytes(unsigned char *bytes, unsigned short val);$/;" p signature:(unsigned char *bytes, unsigned short val) |
| | | val crc-itu-t.c /^ unsigned short val = 0;$/;" l |
| | | value ds18b20.c /^ float value;$/;" l |
| | | w1_path ds18b20.c /^ char w1_path[50] = "\/sys\/bus\/w1\/devices\/";$/;" l |
New file |
| | |
| | | /********************************************************************************* |
| | | * Copyright: (C) 2020 LingYun IoT System Studio |
| | | * All rights reserved. |
| | | * |
| | | * Filename: tlv_pack.h |
| | | * Description: This head file is for TLV packet |
| | | * |
| | | * Version: 1.0.0(2020年04月14日) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "2020年04月14日 00时52分56秒" |
| | | * |
| | | ********************************************************************************/ |
| | | |
| | | #include <stdio.h> |
| | | #include <string.h> |
| | | |
| | | #include "tlv_pack.h" |
| | | #include "crc-itu-t.h" |
| | | |
| | | |
| | | int packtlv_ack(char *buf, int size, int ack) |
| | | { |
| | | unsigned short crc16 = 0; |
| | | int pack_len = 0; |
| | | int ofset = 0; /* index position for the buf */ |
| | | |
| | | if(!buf || size<TLV_MIN_SIZE ) |
| | | { |
| | | printf("Invalid input arguments\n"); |
| | | return 0; |
| | | } |
| | | |
| | | /*+-------------------------+ |
| | | *| 1.fill packet Header | |
| | | *+-------------------------+*/ |
| | | |
| | | buf[ofset] = PACK_HEADER; |
| | | ofset += 1; |
| | | |
| | | /*+-------------------------+ |
| | | *| 2.fill packet Tag | |
| | | *+-------------------------+*/ |
| | | |
| | | buf[ofset] = TAG_ACK; |
| | | ofset += 1; |
| | | |
| | | /*+-------------------------+ |
| | | *| 3.fill packet Length | |
| | | *+-------------------------+*/ |
| | | |
| | | /* ACK message only get 1B payload data */ |
| | | pack_len = TLV_FIXED_SIZE + 1; |
| | | buf[ofset] = pack_len; |
| | | ofset += 1; |
| | | |
| | | /*+-------------------------+ |
| | | *| 4.fill packet Value | |
| | | *+-------------------------+*/ |
| | | |
| | | if( ack ) |
| | | buf[ofset++] = 1; /* 1 for ACK */ |
| | | else |
| | | buf[ofset++] = 0; /* 0 for NAK */ |
| | | |
| | | /*+-------------------------+ |
| | | *| 5.fill packet CRC | |
| | | *+-------------------------+*/ |
| | | |
| | | /* Calc CRC16 checksum value from Packet Head(buf[0]) ~ Value(buf[ofset]) */ |
| | | crc16 = crc_itu_t(MAGIC_CRC, buf, ofset); |
| | | |
| | | /* Append the 2 Bytes CRC16 checksum value into the last two bytes in packet buffer */ |
| | | ushort_to_bytes(&buf[ofset], crc16); |
| | | ofset += 2; |
| | | |
| | | /* ofset value is the TLV packet length */ |
| | | return ofset; |
| | | } |
| | | |
| | | |
| | | int packtlv_sn(char *buf, int size, char *sn) |
| | | { |
| | | unsigned short crc16 = 0; |
| | | int payload_len = 0; |
| | | int pack_len = 0; |
| | | int ofset = 0; /* index position for the buf */ |
| | | |
| | | if(!buf || size<TLV_MIN_SIZE ) |
| | | { |
| | | printf("Invalid input arguments\n"); |
| | | return 0; |
| | | } |
| | | |
| | | /*+-------------------------+ |
| | | *| 1.fill packet Header | |
| | | *+-------------------------+*/ |
| | | buf[ofset] = PACK_HEADER; |
| | | ofset += 1; |
| | | |
| | | /*+-------------------------+ |
| | | *| 2.fill packet Tag | |
| | | *+-------------------------+*/ |
| | | buf[ofset] = TAG_SN; |
| | | ofset += 1; |
| | | |
| | | /*+-------------------------+ |
| | | *| 3.fill packet Length | |
| | | *+-------------------------+*/ |
| | | |
| | | /* $sn too long maybe result buffer overflow, so we need check the buffer |
| | | * is large enuf or not. If not enuf we will truncate $sn string |
| | | */ |
| | | if( strlen(sn) <= size-TLV_FIXED_SIZE ) |
| | | payload_len = strlen(sn); |
| | | else |
| | | payload_len = size-TLV_FIXED_SIZE; |
| | | |
| | | /* TLV packet length is SN length+5Byte () */ |
| | | pack_len = payload_len + TLV_FIXED_SIZE; |
| | | |
| | | buf[ofset] = pack_len; |
| | | ofset += 1; |
| | | |
| | | /*+-------------------------+ |
| | | *| 4.fill packet Value | |
| | | *+-------------------------+*/ |
| | | memcpy(&buf[ofset], sn, payload_len); |
| | | ofset += payload_len; |
| | | |
| | | /*+-------------------------+ |
| | | *| 5.fill packet CRC | |
| | | *+-------------------------+*/ |
| | | |
| | | /* Calc CRC16 checksum value from Packet Head(buf[0]) ~ Value(buf[ofset]) */ |
| | | crc16 = crc_itu_t(MAGIC_CRC, buf, ofset); |
| | | |
| | | /* Append the 2 Bytes CRC16 checksum value into the last two bytes in packet buffer */ |
| | | ushort_to_bytes(&buf[ofset], crc16); |
| | | ofset += 2; |
| | | |
| | | /* ofset value is the TLV packet length */ |
| | | return ofset; |
| | | } |
| | | |
| | | |
| | | int packtlv_temp(char *buf, int size, uint16_t temp) |
| | | { |
| | | unsigned short crc16 = 0; |
| | | int pack_len = 0; |
| | | int ofset = 0; /* index position for the buf */ |
| | | |
| | | if(!buf || size<TLV_FIXED_SIZE+2 ) |
| | | { |
| | | printf("Invalid input arguments\n"); |
| | | return 0; |
| | | } |
| | | |
| | | /*+-------------------------+ |
| | | *| 1.fill packet Header | |
| | | *+-------------------------+*/ |
| | | |
| | | buf[ofset] = PACK_HEADER; |
| | | ofset += 1; |
| | | |
| | | /*+-------------------------+ |
| | | *| 2.fill packet Tag | |
| | | *+-------------------------+*/ |
| | | |
| | | buf[ofset] = TAG_TEMP; |
| | | ofset += 1; |
| | | |
| | | /*+-------------------------+ |
| | | *| 3.fill packet Length | |
| | | *+-------------------------+*/ |
| | | |
| | | /* termperature message get 2B payload data */ |
| | | pack_len = TLV_FIXED_SIZE + 2; |
| | | buf[ofset] = pack_len; |
| | | ofset += 1; |
| | | |
| | | /*+-------------------------+ |
| | | *| 4.fill packet Value | |
| | | *+-------------------------+*/ |
| | | |
| | | /* temperature get 2 bytes, byte[0]:integer part, byte[1]:fractional part */ |
| | | memcpy(&buf[ofset], &temp, 2); |
| | | ofset += 2; |
| | | |
| | | /*+-------------------------+ |
| | | *| 5.fill packet CRC | |
| | | *+-------------------------+*/ |
| | | |
| | | /* Calc CRC16 checksum value from Packet Head(buf[0]) ~ Value(buf[ofset]) */ |
| | | crc16 = crc_itu_t(MAGIC_CRC, buf, ofset); |
| | | |
| | | /* Append the 2 Bytes CRC16 checksum value into the last two bytes in packet buffer */ |
| | | ushort_to_bytes(&buf[ofset], crc16); |
| | | ofset += 2; |
| | | |
| | | /* ofset value is the TLV packet length */ |
| | | return ofset; |
| | | } |
| | | |
| | | int packtlv_time(char *buf, int size, struct tm *tm) |
| | | { |
| | | unsigned short crc16 = 0; |
| | | int pack_len = 0; |
| | | int ofset = 0; /* index position for the buf */ |
| | | |
| | | if(!buf || size<TLV_FIXED_SIZE+6 ) |
| | | { |
| | | printf("Invalid input arguments\n"); |
| | | return 0; |
| | | } |
| | | |
| | | /*+-------------------------+ |
| | | *| 1.fill packet Header | |
| | | *+-------------------------+*/ |
| | | |
| | | buf[ofset] = PACK_HEADER; |
| | | ofset += 1; |
| | | |
| | | /*+-------------------------+ |
| | | *| 2.fill packet Tag | |
| | | *+-------------------------+*/ |
| | | |
| | | buf[ofset] = TAG_TIME; |
| | | ofset += 1; |
| | | |
| | | /*+-------------------------+ |
| | | *| 3.fill packet Length | |
| | | *+-------------------------+*/ |
| | | |
| | | /* date time message get 6B payload data */ |
| | | pack_len = TLV_FIXED_SIZE + 6; |
| | | buf[ofset] = pack_len; |
| | | ofset += 1; |
| | | |
| | | /*+-------------------------+ |
| | | *| 4.fill packet Value | |
| | | *+-------------------------+*/ |
| | | |
| | | buf[ofset++] = tm->tm_year-100; /* tm_year is since 1900, we change it it to 2000 */ |
| | | buf[ofset++] = tm->tm_mon+1; /* tm_mon is from 0~11 */ |
| | | buf[ofset++] = tm->tm_mday; |
| | | buf[ofset++] = tm->tm_hour; |
| | | buf[ofset++] = tm->tm_min; |
| | | buf[ofset++] = tm->tm_sec; |
| | | |
| | | /*+-------------------------+ |
| | | *| 5.fill packet CRC | |
| | | *+-------------------------+*/ |
| | | |
| | | /* Calc CRC16 checksum value from Packet Head(buf[0]) ~ Value(buf[ofset]) */ |
| | | crc16 = crc_itu_t(MAGIC_CRC, buf, ofset); |
| | | |
| | | /* Append the 2 Bytes CRC16 checksum value into the last two bytes in packet buffer */ |
| | | ushort_to_bytes(&buf[ofset], crc16); |
| | | ofset += 2; |
| | | |
| | | /* ofset value is the TLV packet length */ |
| | | return ofset; |
| | | } |
| | | |
| | | |
| | | |
| | | /*+------------------------------+ |
| | | *| dump_buf() implement code | |
| | | *+------------------------------+*/ |
| | | |
| | | #define LINELEN 81 |
| | | #define CHARS_PER_LINE 16 |
| | | |
| | | static char *print_char = |
| | | " " |
| | | " " |
| | | " !\"#$%&'()*+,-./" |
| | | "0123456789:;<=>?" |
| | | "@ABCDEFGHIJKLMNO" |
| | | "PQRSTUVWXYZ[\\]^_" |
| | | "`abcdefghijklmno" |
| | | "pqrstuvwxyz{|}~ " |
| | | " " |
| | | " " |
| | | " ???????????????" |
| | | "????????????????" |
| | | "????????????????" |
| | | "????????????????" |
| | | "????????????????" |
| | | "????????????????"; |
| | | |
| | | /* print every byte in the buffer as HEX and corresponding charactor, which is not printable charactor will be instead as '?' */ |
| | | void dump_buf(char *data, int len) |
| | | { |
| | | int rc; |
| | | int idx; |
| | | char prn[LINELEN]; |
| | | char lit[CHARS_PER_LINE + 1]; |
| | | char hc[4]; |
| | | short line_done = 1; |
| | | |
| | | rc = len; |
| | | idx = 0; |
| | | lit[CHARS_PER_LINE] = '\0'; |
| | | |
| | | while (rc > 0) |
| | | { |
| | | if (line_done) |
| | | snprintf(prn, LINELEN, "%08X: ", idx); |
| | | do |
| | | { |
| | | unsigned char c = data[idx]; |
| | | snprintf(hc, 4, "%02X ", c); |
| | | strncat(prn, hc, 4); |
| | | lit[idx % CHARS_PER_LINE] = print_char[c]; |
| | | ++idx; |
| | | } while (--rc > 0 && (idx % CHARS_PER_LINE != 0)); |
| | | |
| | | line_done = (idx % CHARS_PER_LINE) == 0; |
| | | |
| | | if (line_done) |
| | | printf("%s %s\n", prn, lit); |
| | | else if (rc == 0) |
| | | strncat(prn, " ", LINELEN); |
| | | } |
| | | |
| | | if (!line_done) |
| | | { |
| | | lit[(idx % CHARS_PER_LINE)] = '\0'; |
| | | |
| | | while ((++idx % CHARS_PER_LINE) != 0) |
| | | strncat(prn, " ", LINELEN); |
| | | |
| | | printf("%s %s\n", prn, lit); |
| | | |
| | | } |
| | | } |
| | | |
New file |
| | |
| | | /******************************************************************************** |
| | | * Copyright: (C) 2020 LingYun IoT System Studio |
| | | * All rights reserved. |
| | | * |
| | | * Filename: tlv_pack.h |
| | | * Description: This head file is for TLV packet |
| | | * |
| | | * Version: 1.0.0(2020年04月15日) |
| | | * Author: Guo Wenxue <guowenxue@gmail.com> |
| | | * ChangeLog: 1, Release initial version on "2020年04月15日 23时14分21秒" |
| | | * |
| | | ********************************************************************************/ |
| | | #ifndef _TLV_PACK_H_ |
| | | #define _TLV_PACK_H_ |
| | | |
| | | #include <stdint.h> |
| | | #include <time.h> |
| | | |
| | | /* TLV Packet format: |
| | | * |
| | | *+------------+---------+------------+-----------+-----------+ |
| | | *| Header(1B) | Tag(1B) | Length(1B) | Value(1B) | CRC16(2B) | |
| | | *+------------+---------+------------+-----------+-----------+ |
| | | */ |
| | | |
| | | #define PACK_HEADER 0xFD |
| | | |
| | | /* TLV packet fixed segement size, 1B Head, 1B Tag, 1B length, 2B CRC16, total 5B. */ |
| | | #define TLV_FIXED_SIZE 5 |
| | | |
| | | /* TLV packet Minimum size is fixed bytes + 1 byte data */ |
| | | #define TLV_MIN_SIZE (TLV_FIXED_SIZE+1) |
| | | |
| | | |
| | | /* Tag definition */ |
| | | enum |
| | | { |
| | | TAG_ACK=1, |
| | | TAG_SN, |
| | | TAG_TEMP, |
| | | TAG_TIME, |
| | | }; |
| | | |
| | | #define TLV_BUFSIZE 256 |
| | | |
| | | #define TLV_FLAG_TX 1<<0 /* This TLV message need to be sent by socket */ |
| | | #define TLV_FLAG_DB 1<<1 /* This TLV message need to be saved in database */ |
| | | typedef struct tlv_buf_s |
| | | { |
| | | uint8_t flag; /* TLV message flags */ |
| | | char buf[TLV_BUFSIZE]; |
| | | int len; /* data length */ |
| | | int size; /* buffer size */ |
| | | } tlv_buf_t; |
| | | |
| | | /* Packet TLV message for server reply ACK message: ACK(ack=1)/NAK(ack=0) */ |
| | | #define ACK 1 |
| | | #define NAK 0 |
| | | int packtlv_ack (char *buf, int size, int ack); |
| | | |
| | | /* Packet TLV message for SN */ |
| | | int packtlv_sn (char *buf, int size, char *sn); |
| | | |
| | | /* Packet TLV message for temperature */ |
| | | int packtlv_temp(char *buf, int size, uint16_t temp); |
| | | |
| | | /* Packet TLV message for date time */ |
| | | int packtlv_time(char *buf, int size, struct tm *tm); |
| | | |
| | | /* Packet 3 TLV message together: with SN, temperature, date&time */ |
| | | int packtlv_msg(tlv_buf_t *tlv, char *sn, uint16_t temp, struct tm *tm); |
| | | |
| | | /* print buf data in hex and string mode */ |
| | | void dump_buf(char *data, int len); |
| | | |
| | | #endif /* ----- #ifndef _TLV_PACK_H_ ----- */ |
| | | |
| | |
| | | |
| | | #include "logger.h" |
| | | #include "proc.h" |
| | | #include "ds18b20.h" |
| | | #include "socket.h" |
| | | #include "tlv_pack.h" |
| | | |
| | | #define PROG_VERSION "1.0.0" |
| | | #define RPI_SN "RPI00001" |
| | | |
| | | #define DEF_LOG_FILE "tlv_client.log" |
| | | |
| | | #define DEF_ACK_TIMEOUT 2 /* wait for ACK timeout value */ |
| | | #define DEF_RETRYTIMES 3 /* receive ACK timeout or get NAK, retry to send times */ |
| | | int socket_send_tlv_pack(socket_t *sock, tlv_buf_t *tlv, int timeout, int retry_times); |
| | | |
| | | int packtlv_msg(tlv_buf_t *tlv, char *sn, uint16_t temp, struct tm *tm); |
| | | |
| | | static void banner(void) |
| | | { |
| | |
| | | printf("This program used to connect to server and send RPi's temperature by TLV protocal.\n"); |
| | | |
| | | printf("\nMandatory arguments to long options are mandatory for short options too:\n"); |
| | | printf(" -H[Host ] Specify host server address and port, foramt as \"127.0.0.1:9000\"\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(" -h[help ] Display this help information\n"); |
| | |
| | | { |
| | | int opt; |
| | | int i = 0; |
| | | //int rv = 0; |
| | | int rv = 0; |
| | | int debug = 0; |
| | | |
| | | char pid_file[64] = { 0 }; /* The file used to record the PID */ |
| | | const char *progname=NULL; |
| | | |
| | | char *host = "192.168.2.110:10086"; |
| | | //char *host = "baidu.com:10086"; |
| | | int log_level = LOG_LEVEL_NRML; |
| | | char *log_file = DEF_LOG_FILE; |
| | | |
| | | logger_t logger; |
| | | socket_t sock; |
| | | tlv_buf_t tlv; |
| | | |
| | | uint16_t temp; |
| | | struct tm *tm; |
| | | time_t cur_time, last_time = 0; |
| | | |
| | | struct option long_options[] = { |
| | | {"Host", required_argument, NULL, 'H'}, |
| | | {"debug", no_argument, NULL, 'd'}, |
| | | {"level", required_argument, NULL, 'l'}, |
| | | {"version", no_argument, NULL, 'v'}, |
| | |
| | | {NULL, 0, NULL, 0} |
| | | }; |
| | | |
| | | memset(&sock, 0, sizeof(sock)); |
| | | memset(&logger, 0, sizeof(logger)); |
| | | |
| | | progname = basename(argv[0]); /* get program name */ |
| | | |
| | | /* parser the command line parameters */ |
| | | while ((opt = getopt_long(argc, argv, "c:dl:vh", long_options, NULL)) != -1) |
| | | while ((opt = getopt_long(argc, argv, "H:dl:vh", long_options, NULL)) != -1) |
| | | { |
| | | switch (opt) |
| | | { |
| | | case 'H': |
| | | host=optarg; |
| | | break; |
| | | |
| | | case 'd': /* set debug running */ |
| | | debug = 1; |
| | |
| | | } |
| | | } |
| | | |
| | | #if 1 |
| | | if( !host ) |
| | | { |
| | | printf("ERROR: No argument specify host server address and port, please refer to usage\n"); |
| | | // return 1; |
| | | } |
| | | |
| | | |
| | | #endif |
| | | |
| | | /* check program already running or not, if already running then exit, or set running as daemon */ |
| | | snprintf(pid_file, sizeof(pid_file), "/var/run/%s.pid", progname); |
| | | snprintf(pid_file, sizeof(pid_file), "/tmp/%s.pid", progname); |
| | | if( !debug ) |
| | | { |
| | | if( check_daemon_running(pid_file) ) |
| | |
| | | printf("Programe already running, exit now.\n"); |
| | | return -1; |
| | | } |
| | | |
| | | daemon(1, 1); |
| | | } |
| | | |
| | | record_daemon_pid(pid_file); |
| | | |
| | | /* initial and open logger system */ |
| | | if( logger_init(&logger, log_file, log_level, 512)<0 || logger_open()<0 ) |
| | | { |
| | | printf("ERROR: Initialise logger system failure\n"); |
| | | return -1; |
| | | return 2; |
| | | } |
| | | |
| | | /* install signal proc handler */ |
| | |
| | | |
| | | log_nrml("Program start running\n"); |
| | | |
| | | #if 0 |
| | | if( initial_db(&sqldb, db_file) < 0) |
| | | { |
| | | log_err("initialise sqlite database failure\n"); |
| | | return 3; |
| | | } |
| | | #endif |
| | | |
| | | last_time = 0; |
| | | |
| | | /* g_signal.stop defined in proc.c, and will be set when catch stop signal */ |
| | | while( !g_signal.stop ) |
| | | { |
| | | log_dbg("Program still running\n"); |
| | | sleep(3); |
| | | time(&cur_time); |
| | | if( cur_time-last_time > 3) |
| | | { |
| | | log_nrml("start sample temperature now.\n"); |
| | | rv = 0; |
| | | temp = 0x1122; |
| | | //rv = ds18b20_get_temperature(&temp); |
| | | if( 0 == rv ) |
| | | { |
| | | /* convert time_t to tm format */ |
| | | tm=localtime(&cur_time); |
| | | last_time = cur_time; |
| | | |
| | | packtlv_msg(&tlv, RPI_SN, temp, tm); |
| | | logger_dump(LOG_LEVEL_DEBUG, tlv.buf, tlv.len); |
| | | |
| | | /* this message need to be transmit and saved in database if send failure */ |
| | | tlv.flag = TLV_FLAG_TX | TLV_FLAG_DB; |
| | | } |
| | | else |
| | | { |
| | | log_err("DS18B20 get temperature failure\n"); |
| | | } |
| | | } |
| | | |
| | | if( SOCK_STAT_CONNECTED != sock.status ) |
| | | { |
| | | if( socket_connect(&sock, -1, host, MODE_NONBLOCK) < 0) |
| | | { |
| | | log_err("connect to server [%s:%d] failure\n", sock.raddr, sock.rport); |
| | | } |
| | | } |
| | | |
| | | if( (tlv.flag&TLV_FLAG_TX) && SOCK_STAT_CONNECTED==sock.status ) |
| | | { |
| | | if(0 == socket_send_tlv_pack(&sock, &tlv, DEF_ACK_TIMEOUT, DEF_RETRYTIMES) ) |
| | | { |
| | | tlv.flag = 0; |
| | | } |
| | | } |
| | | |
| | | #if 0 |
| | | /* need to send TLV packet in database now */ |
| | | for(i=0; i<5; i++) |
| | | { |
| | | /* get a TLV record from DB and send it by socket */ |
| | | /* rv<0: Erorr rv=0: No record >0: record count */ |
| | | rv = get_db_tlv_pack(sqldb, tlv, size) ; |
| | | if( rv <= 0) |
| | | break; |
| | | |
| | | if( 0 == socket_send_tlv_pack() ) |
| | | { |
| | | /* delete the record from DB */ |
| | | del_db_tlv_pack(); |
| | | } |
| | | } |
| | | |
| | | SAVE_DB: |
| | | if( tlv_buf.flag & TLV_FLAG_DB) |
| | | { |
| | | record_db_tlv(sqldb, tlv_buf, tlv_len); |
| | | } |
| | | #endif |
| | | |
| | | sleep(1); |
| | | } |
| | | |
| | | logger_term(); |
| | | |
| | | //db_term(); |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | /* Packet 3 TLV message together: with SN, temperature, date&time */ |
| | | int packtlv_msg(tlv_buf_t *tlv, char *sn, uint16_t temp, struct tm *tm) |
| | | { |
| | | int rv; |
| | | |
| | | if( !tlv ) |
| | | { |
| | | log_err("Invalid input arguments\n"); |
| | | return -1; |
| | | } |
| | | |
| | | memset(tlv->buf, 0, sizeof(tlv->buf)); /* clear data in buffer */ |
| | | tlv->size = sizeof(tlv->buf); /* buffer free space size */ |
| | | tlv->len = 0; /* buffer data length */ |
| | | |
| | | if( sn ) |
| | | { |
| | | rv = packtlv_sn(&tlv->buf[tlv->len], tlv->size, sn); |
| | | if( rv > 0 ) |
| | | { |
| | | tlv->len += rv; |
| | | tlv->size -= rv; |
| | | } |
| | | } |
| | | |
| | | if( temp ) |
| | | { |
| | | rv = packtlv_temp(&tlv->buf[tlv->len], tlv->size, temp); |
| | | if( rv > 0 ) |
| | | { |
| | | tlv->len += rv; |
| | | tlv->size -= rv; |
| | | } |
| | | } |
| | | |
| | | if( tm ) |
| | | { |
| | | rv = packtlv_time(&tlv->buf[tlv->len], tlv->size, tm); |
| | | if( rv > 0 ) |
| | | { |
| | | tlv->len += rv; |
| | | tlv->size -= rv; |
| | | } |
| | | } |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | int socket_send_tlv_pack(socket_t *sock, tlv_buf_t *tlv, int timeout, int retry_times) |
| | | { |
| | | int i; |
| | | int rv = 0; |
| | | char buf[128]; |
| | | |
| | | log_info("start to send tlv packet from socket now\n"); |
| | | |
| | | for(i=0; i<retry_times; i++) |
| | | { |
| | | if( (rv=socket_send(sock, tlv->buf, tlv->len)) < 0 ) |
| | | { |
| | | log_err("send tlv packet failure, rv=%d\n", rv); |
| | | return -1; |
| | | } |
| | | |
| | | if( (rv=socket_recv(sock, buf, sizeof(buf), timeout)) < 0 ) |
| | | { |
| | | log_err("read ACK from server failure, rv=%d\n"); |
| | | return -2; |
| | | } |
| | | } |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | |
New file |
| | |
| | | Initialize log "tlv_client.log" on level [N] size [512] KiB, log system version 1.0.0 |
| | | [ Date ] [ Time ] [ Level ] [ File/Line ] [ Message ] |
| | | ------------------------------------------------------------- |
| | | [2020-04-28 20:52:49.352] <N> <proc.c:0059> : Install default signal handler. |
| | | [2020-04-28 20:52:49.352] <N> <tlv_client.c:0164> : Program start running |
| | | [2020-04-28 20:52:49.352] <N> <tlv_client.c:0182> : start sample temperature now. |
| | | [2020-04-28 20:52:53.353] <N> <tlv_client.c:0182> : start sample temperature now. |
| | | [2020-04-28 20:52:57.353] <N> <tlv_client.c:0182> : start sample temperature now. |
| | | [2020-04-28 20:53:01.353] <N> <tlv_client.c:0182> : start sample temperature now. |
| | | [2020-04-28 20:53:05.354] <N> <tlv_client.c:0182> : start sample temperature now. |
| | | [2020-04-28 20:53:09.354] <N> <tlv_client.c:0182> : start sample temperature now. |
| | | [2020-04-28 20:53:13.354] <N> <tlv_client.c:0182> : start sample temperature now. |
| | | [2020-04-28 20:53:17.355] <N> <tlv_client.c:0182> : start sample temperature now. |
| | | [2020-04-28 20:53:21.355] <N> <tlv_client.c:0182> : start sample temperature now. |
| | | [2020-04-28 20:53:25.356] <N> <tlv_client.c:0182> : start sample temperature now. |
| | | [2020-04-28 20:53:29.356] <N> <tlv_client.c:0182> : start sample temperature now. |
| | | [2020-04-28 20:53:30.815] <W> <proc.c:0038> : SIGTERM - stopping |
| | | |
| | | Terminate log "tlv_client.log" on level [N] size [512] KiB, log system version 1.0.0 |
| | | [ Date ] [ Time ] [ Level ] [ File/Line ] [ Message ] |
| | | ------------------------------------------------------------- |
| | | |
| | | |
| | | |
| | | |