From c13c9806f957ebc675462737f4b328d3ab89e028 Mon Sep 17 00:00:00 2001 From: guowenxue <guowenxue@gmail.com> Date: Mon, 10 Jul 2023 17:29:22 +0800 Subject: [PATCH] update gpsd.c --- gpsd/booster/atcmd.c | 296 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 296 insertions(+), 0 deletions(-) diff --git a/gpsd/booster/atcmd.c b/gpsd/booster/atcmd.c new file mode 100644 index 0000000..623bd96 --- /dev/null +++ b/gpsd/booster/atcmd.c @@ -0,0 +1,296 @@ +/* + * Copyright (c) 2023 Guo Wenxue + * Author: Guo Wenxue <guowenxue@gmail.com> + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GPL license. + */ + +#include <ctype.h> + +#include "logger.h" +#include "atcmd.h" + +/* Description: this function used to send an AT command from serial port and wait for reply message from + * the communication module, and it will return once get expet/error string or timeout. + * + * Arugments: + * $comport: the serial port which connected to GPRS/3G/4G/NB-IoT/WiFi/BLE/Zigbee/LoRa... + * $at: the AT command need to be sent, without "\r\n" + * $timeout: wait for module reply for AT command timeout value, unit micro seconds(ms) + * $exepct: the expect string reply from communication module + * $error: the error string reply from communication module + * $reply: the module reply message output buffer + * $size: the output buffer ($reply) size + * + * Return value: <0: Function error 0: Got error string 1: Got expect string 2: Receive util timeout + * + */ + +int send_atcmd(comport_t *comport, char *at, unsigned long timeout, char *expect, char *error, char *reply, int size) +{ + int i, rv = 0; + int res = ATRES_TIMEOUT; + int bytes = 0; + char buf[ATCMD_REPLY_LEN] = {'\0'}; + char atcmd[ATCMD_LEN] = {'\0'}; + + if( !comport || !at ) + { + log_error("Invalid input arguments\n"); + return -1; + } + + if( comport->fd <= 0 ) + { + log_error("comport[%s] not opened\n"); + return -2; + } + + /* flushes both data received but not read, and data written but not transmitted in serial port */ + tcflush(comport->fd, TCIOFLUSH); + + snprintf(atcmd, sizeof(atcmd), "%s%s", at, AT_SUFFIX); + rv=comport_send( comport, atcmd, strlen(atcmd) ); + if(rv < 0) + { + log_error("send AT command \"%s\" to \"%s\" failed, rv=%d\n", at, comport->devname, rv); + return -3; + } + + res = ATRES_TIMEOUT; + memset( buf, 0, sizeof(buf) ); + + for(i=0; i<timeout/10; i++) + { + if( bytes >= sizeof(buf) ) + break; + + rv=comport_recv( comport, buf+bytes, sizeof(buf)-bytes, 10); + if(rv < 0) + { + log_error("send AT command \'%s\' to \'%s\' failed, rv=%d\n", at, comport->devname, rv); + return -3; + } + + bytes += rv; + + if( expect && strstr(buf, expect) ) + { + log_debug("send AT command \"%s\" and got reply \"OK\"\n", at); + res = ATRES_EXPECT; + break; + } + + if( error && strstr(buf, error) ) + { + log_debug("send AT command \"%s\" and got reply \"ERROR\"\n", at); + res = ATRES_ERROR; + break; + } + } + + if( bytes > 0 ) + log_trace("AT command reply:%s", buf); + + if( reply && size>0 ) + { + bytes = strlen(buf)>size ? size : strlen(buf); + memset(reply, 0, size); + strncpy(reply, buf, bytes); + + log_debug("copy out AT command \"%s\" reply message: \n%s", at, reply); + } + + return res; +} + + +/* + * Description: Send AT command which will only reply by "OK" or "ERROR", such as AT: + * Reply: \r\nOK\r\n + * Return Value: 0: OK -X: Failure + */ +int send_atcmd_check_ok(comport_t *comport, char *at, unsigned long timeout) +{ + int rv; + + if( !comport || !at ) + { + log_error("Invalid input arguments\n"); + return -1; + } + + rv=send_atcmd(comport, at, timeout, AT_OKSTR, AT_ERRSTR, NULL, 0); + if( ATRES_EXPECT == rv ) + { + return 0; + } + else + { + return -2; + } +} + + +/* + * Description: Send AT command which will reply by a value directly in a single line, such as AT+CGMM: + * Reply: \r\nEC20F\r\nOK\r\n + * + * Return Value: 0: OK -X: Failure + */ +int send_atcmd_check_value(comport_t *comport, char *at, unsigned long timeout, char *reply, int size) +{ + int rv, len; + char buf[ATCMD_REPLY_LEN]; + char *ptr_start = buf; + char *ptr_end; + + if( !comport || !at || !reply || size<=0 ) + { + log_error("Invalid input arguments\n"); + return -1; + } + + rv = send_atcmd(comport, at, timeout, AT_OKSTR, AT_ERRSTR, buf, ATCMD_REPLY_LEN); + if( rv <= 0 ) + { + return -2; + } + + /* Skip the echo back command line */ + if( !strncmp(buf, at, strlen(at)) ) + { + ptr_start=strchr(buf, '\n'); + if( !ptr_start ) + { + log_error("reply message got wrong\n"); + return -3; + } + + ptr_start++; /* skip '\n' */ + } + + /* find end reply string "\r\nOK\r\n" */ + ptr_end = strstr(ptr_start, AT_OKSTR); + if( ptr_end ) + { + len = ptr_end - ptr_start; + } + else + { + len = strlen(buf) - (ptr_start-buf); + } + + memset(reply, 0, size); + + len = len>size ? size : len; + memcpy(reply, ptr_start, len); + + return 0; +} + +/* + * Description: Parser the $value from $key like "xxx: " line, such as AT+CSQ: + * Reply: \r\n+CSQ: 26,99\r\nOK\r\n + * + * Return Value: 0: OK -X: Failure + */ +int parser_request_value(char *buf, char *key, char *value, int size) +{ + char *ptr; + int i = 0; + + if( !buf || !key || !value || size<=0 ) + { + log_error("Invalid input arguments\n"); + return -1; + } + + ptr = strstr(buf, key); + if( !ptr ) + { + log_debug("Not found key \"%s\" in %s\n", key, buf); + return -2; + } + + ptr=strchr(ptr, ':'); /* found ':' before the value */ + if( !ptr ) + { + log_debug("Not found ':' before value\n"); + return -3; + } + ptr++; /* skip ':' */ + + if( *ptr == '\"' ) /* skip " */ + ptr++; + + memset(value, 0, size); + while(*ptr!='\r' && i<size-1) + { + if( !isspace(*ptr) && *ptr!='\"') /* skip space,\r,\n ... */ + value[i++] = *ptr; + ptr ++; + } + + ptr++; /* skip */ + + return 0; +} + +/* + * Description: Send AT command which will reply by the value with a prefix "+CMD: " line, such as AT+CSQ: + * Reply: \r\n+CSQ: 26,99\r\nOK\r\n + * + * Return Value: 0: OK -X: Failure + */ +int send_atcmd_check_request(comport_t *comport, char *at, unsigned long timeout, char *reply, int size) +{ + int i = 0; + int rv; + char buf[ATCMD_REPLY_LEN]; + char *ptr; + + if( !comport || !at || !reply || size<=0 ) + { + log_error("Invalid input arguments\n"); + return -1; + } + + rv = send_atcmd(comport, at, timeout, AT_OKSTR, AT_ERRSTR, buf, ATCMD_REPLY_LEN); + if( rv <= 0 ) + { + return -2; + } + + ptr=strchr(buf, '+'); /* found '+' before the value */ + if( !ptr ) + { + log_error("reply message got wrong\n"); + return -3; + } + ptr++; /* skip '+' */ + + + ptr=strchr(buf, ':'); /* found ':' before the value */ + if( !ptr ) + { + log_error("reply message got wrong\n"); + return -3; + } + ptr++; /* skip ':' */ + + if( *ptr == '\"' ) /* skip " */ + ptr++; + + memset(reply, 0, size); + while(*ptr!='\r' && i<size-1) + { + if( !isspace(*ptr) && *ptr!='\"') /* skip space,\r,\n ... */ + reply[i++] = *ptr; + ptr ++; + } + + return 0; +} + -- Gitblit v1.9.1