#include #include #include #include #include #include #include #include #include "cJSON.h" #include "json_handle.h" #include "websocket_handle.h" #include "common.h" #include "sys.h" #include "Cellular.h" #include #include "thread.h" #include "paras.h" #include "lock.h" #include "elog.h" #include "cfg.h" #if 0 #define LOGE log_e #define LOGW log_w #define LOGD log_d #else #define LOGD printf #define LOGW printf #define LOGE printf #endif //#define USE_CELL //#define GNSS_ENABLE //EC200N-CN, 不支持gnss #define RETRY_TIMES 3 #define BUF_LEN 2000 #define AT_PORT "/dev/ttyUSB1" #define BAUD_RATE B115200 #define QUERY_INTERVAL 1000 // 查询间隔,毫秒 #define RSSI_DBM_MIN1 -113 // LTE、HSDPA网络最小信号值,对应RSSI值范围0-57 #define RSSI_DBM_MIN2 -116 // TD-SCDMA网络最小信号值,对应RSSI值范围100-199 #define CONTEXT_ID "1" //1~15 #define CONNECT_ID "0" //0~11 #define CONNECT_TIMEOUT "5" #define CHUNCK_SIZE 1460 #define MQTT_VER 4 //3: v3.1 4: v3.1.1 #define MQTT_WILL 0 #define MQTT_RETAIN 0 #define MQTT_MAX 6 #define MQTT_QOS 2 #define MQTT_CHUNCK_SIZE 1500 enum { AT_OK=0, AT_ERR, AT_TOUT, }; enum { AT_STAT_UNINIT=0, AT_STAT_INITED, }; enum { SOCK_TCP=0, SOCK_UDP, }; enum { URC_SOCK=0, URC_MQTT, URC_GNSS, URC_NTP, URC_SMS, URC_CALL, URC_ERR, }; typedef int (*urc_fn_t)(int urc, void *data, int len); typedef struct { int cmd; char para[100]; }at_para_t; typedef struct { char *cmd; char *ok; char *err; int timeout; //ms }at_cmd_t; typedef struct { int cmd; char *buf; int dlen; int blen; }at_buf_t; typedef struct { at_buf_t rx; at_buf_t tx; }at_data_t; typedef struct { void *h; int sock; int cont_id; //1~15 int cont_type; //1:ipv4 2:ipv6 3:ipv4+ipv6 int conn_id; char apn[64]; char username[128]; char password[128]; int authentication; //0:none 1:PAP 2:CHAP 3:PAP OR CHAP int cdma_pwd; //0:no save 1:save }sock_conn_t; typedef struct { char host[100]; uint16_t port; char username[64]; char password[64]; }mqtt_para_t; typedef struct { int flag; int qos; int retain; char topic[256]; char message[256]; int message_len; }mqtt_will_t; typedef struct { char product_key[64]; //aliyun used char device_name[64]; //aliyun used char device_secret[64]; //aliyun/ used char product_id[64]; //onenet used char access_key[64]; //onenet used int hw_time_enable; //huawei used char product_secret[64]; //huawei used char node_id[64]; }mqtt_plat_t; typedef struct { void *h; int ver; //3:v3.1 4:v3.1.1 int pdpId; //1~15 int cliId; uint16_t msgId; int qos; int retain; mqtt_will_t will; int timeout; //1~60, default:5 int retry_times; int timeout_notice; int clean_session; int keep_alive_time; //0~3600 seconds default:120, 0:do not disconnect int ssl_enable; int ssl_ctx_id; int msg_recv_mode; //0: urc, 1: not urc int msg_len_enable; int ping_interval; //5~60, default:5 int proto_chk_enable; //0:no check 1:check int send_mode; //0:string 1:hex int recv_mode; //0:string 1:hex int view_mode; //0:no echo 1:echo int edit_mode; //0:timeout not quit 1:timeout quit int edit_time; //1~120 seconds mqtt_plat_t plat; }mqtt_conn_t; typedef struct { int fd; CellInfo_t *pcell; lock_t lck; int prod_id; int stat; cell_all_t all; int curcmd; //current cmd at_data_t data[AT_CMD_MAX]; GlobalDeviceManager *dm; }cell_handle_t; static cell_handle_t ceHandle={0}; static at_cmd_t all_cmd[AT_CMD_MAX]={ //genernal cmd {"AT", "OK", "ERROR", 300}, //测试命令 {"ATI", "OK", "ERROR", 300}, //显示MT的ID信息 {"AT+GMI", "OK", "ERROR", 300}, //请求制造商信息 {"AT+GMM", "OK", "ERROR", 300}, //请求TA型号ID {"AT+GMR", "OK", "ERROR", 300}, //请求TA固件版本ID {"AT+CGMI", "OK", "ERROR", 300}, //同GMI {"AT+CGMM", "OK", "ERROR", 300}, //同GMM {"AT+CGMR", "OK", "ERROR", 300}, //同GMR {"AT+GSN", "OK", "ERROR", 300}, //请求国际移动设备识别码(IMEI) {"AT+CGSN", "OK", "ERROR", 300}, //同GSN {"AT&F", "OK", "ERROR", 300}, //重置AT命令设置为出厂设置 {"AT&V", "OK", "ERROR", 300}, //显示当前配置 {"AT&W", "OK", "ERROR", 300}, //存储当前设置到用户自定义配置文件 {"ATZ", "OK", "ERROR", 300}, //从用户定义配置文件还原所有AT命令设置 {"ATQ", "OK", "ERROR", 300}, //设置结果码回显模式 {"ATV", "OK", "ERROR", 300}, //TA响应格式 {"ATE0", "OK", "ERROR", 300}, //设置命令回显模式 {"ATS3", "OK", "ERROR", 300}, //设置命令行终止符 {"ATS4", "OK", "ERROR", 300}, //设置响应格式字符 {"ATS5", "OK", "ERROR", 300}, //设置命令行编辑字符 {"ATX", "OK", "ERROR", 300}, //设置CONNECT结果码格式和检测呼叫进程 {"AT+CFUN", "OK", "ERROR", 15000}, //设置功能模式 {"AT+CMEE", "OK", "ERROR", 300}, //设置错误讯息格式 {"AT+CSCS", "OK", "ERROR", 300}, //选择TE字符集 {"AT+QURCCFG", "OK", "ERROR", 300}, //配置URC指示选项 {"AT+QPPPDROP", "OK", "ERROR", 300}, //终止PPP连接 //serial cmd {"AT&C", "OK", "ERROR", 300}, //设置DCD信号模式 {"AT&D", "OK", "ERROR", 300}, //设置DTR信号模式 {"AT+IFC", "OK", "ERROR", 300}, //设置串口的流控方式 {"AT+IPR", "OK", "ERROR", 300}, //设置固定的串口通信波特率 //status cmd {"AT+CPAS", "OK", "ERROR", 300}, //查询ME活动状态 {"AT+CEER", "OK", "ERROR", 300}, //上报扩展错误 {"AT+QCFG", "OK", "ERROR", 300}, //扩展命令, 较多子命令 {"AT+QINDCFG", "OK", "ERROR", 300}, //控制URC上报 //sim cmd {"AT+CIMI", "OK", "ERROR", 300}, //查询IMSI {"AT+CLCK", "OK", "ERROR", 5000}, //功能锁定 {"AT+CPIN", "OK", "ERROR", 5000}, //PIN管理 {"AT+CPWD", "OK", "ERROR", 5000}, //修改密码 {"AT+CSIM", "OK", "ERROR", 300}, //通用(U)SIM卡访问 {"AT+CRSM", "OK", "ERROR", 300}, //(U)SIM卡受限访问 {"AT+QCCID", "OK", "ERROR", 300}, //查询ICCID {"AT+QPINC", "OK", "ERROR", 300}, //获取PIN剩余重试次数 {"AT+QINISTAT", "OK", "ERROR", 300}, //查询(U)SIM卡初始化状态 {"AT+QSIMDET", "OK", "ERROR", 300}, //(U)SIM卡检测 {"AT+QSIMSTAT", "OK", "ERROR", 300}, //(U)SIM卡插拔状态上报 {"AT+QDSIM", "OK", "ERROR", 50000}, //选择(U)SIM卡 //network service cmd {"AT+COPS", "OK", "ERROR", 300000}, //选择运营商 {"AT+CREG", "OK", "ERROR", 300}, //CS域网络注册状态 {"AT+CSQ", "OK", "ERROR", 300}, //查询信号强度 {"AT+CPOL", "OK", "ERROR", 300}, //配置首选运营商列表 {"AT+COPN", "OK", "ERROR", 300}, //查询运营商名称列表 {"AT+CTZU", "OK", "ERROR", 300}, //自动更新时区 {"AT+CTZR", "OK", "ERROR", 300}, //上报时区变化 {"AT+QLTS", "OK", "ERROR", 500}, //获取通过网络同步的最新时间 {"AT+QNWINFO", "OK", "ERROR", 300}, //查询网络信息 //call cmd {"ATA", "OK", "ERROR", 90000}, //呼叫应答 {"ATD", "OK", "ERROR", 5000}, //发起呼叫 {"AT+COLP", "OK", "ERROR", 15000}, //被叫线路识别显示 {"AT+ATH", "OK", "ERROR", 90000}, //挂断现有连接 {"AT+CHUP", "OK", "ERROR", 90000}, //挂断语音通话 {"+++", "OK", "ERROR", 300}, //从数据模式切换至命令模式 {"AT+ATO", "OK", "ERROR", 300}, //从命令模式切换至数据模式 {"AT+ATSO", "OK", "ERROR", 300}, //设置自动应答前振铃次数 {"AT+CLCC", "OK", "ERROR", 300}, //查询当前 ME 呼叫 {"AT^DSCI", "OK", "ERROR", 300}, //指示呼叫状态 //phonebook cmd {"AT+CNUM", "OK", "ERROR", 300}, //查询本机号码 {"AT+CPBF", "OK", "ERROR", 300}, //搜索电话本 {"AT+CPBR", "OK", "ERROR", 300}, //读取电话本条目 {"AT+CPBS", "OK", "ERROR", 300}, //设置电话本存储器 {"AT+CPBW", "OK", "ERROR", 300}, //写入电话本 //sms cmd {"AT+CSMS", "OK", "ERROR", 300}, //选择短消息服务类型 {"AT+CMGF", "OK", "ERROR", 300}, //配置短消息模式 {"AT+CSCA", "OK", "ERROR", 300}, //设置短消息服务中心地址 {"AT+CPMS", "OK", "ERROR", 300}, //配置短消息首选存储位置 {"AT+CMGD", "OK", "ERROR", 300}, //删除短消息 {"AT+CMGL", "OK", "ERROR", 300}, //按状态读取短消息 {"AT+CMGR", "OK", "ERROR", 300}, //按照索引读取短消息 {"AT+CMGS", ">", "ERROR", 120000}, //发送短消息 {"AT+CMMS", "OK", "ERROR", 300}, //发送多条短消息 {"AT+CMGW", "OK", "ERROR", 300}, //存储短消息 {"AT+CMSS", "OK", "ERROR", 300}, //从存储器发送短消息 {"AT+CNMA", "OK", "ERROR", 300}, //新短消息确认 {"AT+CNMI", "OK", "ERROR", 300}, //设置短消息上报方式 {"AT+CSCB", "OK", "ERROR", 300}, //选择小区广播消息类型 {"AT+CSDH", "OK", "ERROR", 300}, //设置文本模式下参数显示 {"AT+CSMP", "OK", "ERROR", 300}, //设置短消息文本模式参数 {"AT+QCMGS", "OK", "ERROR", 120000}, //发送级联短消息 {"AT+QCMGR", "OK", "ERROR", 300}, //读取级联短消息 //gps cmd {"AT+QGPSCFG", "OK", "ERROR", 300}, //配置GNSS {"AT+QGPSDEL", "OK", "ERROR", 300}, //删除辅助数据 {"AT+QGPS", "OK", "ERROR", 300}, //打开GNSS {"AT+QGPSEND", "OK", "ERROR", 300}, //关闭GNSS {"AT+QGPSLOC", "OK", "ERROR", 300}, //获取定位信息 {"AT+QGPSNMEA", "OK", "ERROR", 300}, //获取指定的NMEA语句 {"AT+QAGPS", "OK", "ERROR", 300}, //启用/禁用AGPS //tcp/udp cmd {"AT+QICFG", "OK", "ERROR", 300}, //配置可选参数 {"AT+QICSGP", "OK", "ERROR", 300}, //配置TCP/IP场景参数 {"AT+QIACT", "OK", "ERROR", 10000}, //激活PDP场景 {"AT+QIDEACT", "OK", "ERROR", 10000}, //去激活PDP场景 {"AT+QIOPEN", "OK", "ERROR", 300}, //打开Socket服务 {"AT+QICLOSE", "OK", "ERROR", 300}, //关闭Socket服务 {"AT+QISTATE", "OK", "ERROR", 300}, //查询Socket服务状态 {"AT+QISEND", ">", "ERROR", 300}, //发送数据 {"AT+QIRD", "OK", "ERROR", 300}, //读取收到的TCP/IP数据 {"AT+QISENDEX", "OK", "ERROR", 300}, //发送16进制字符串数据 {"AT+QISWTMD", "OK", "ERROR", 300}, //切换数据访问模式 {"AT+QNTP", "OK", "ERROR", 300}, //进行远程服务器Ping操作 {"AT+QPING", "+QPING", "ERROR", 3000}, //使用NTP服务器同步本地时间 {"AT+QIDNSCFG", "OK", "ERROR", 300}, //配置DNS服务器地址 {"AT+QIDNSGIP", "OK", "ERROR", 300}, //用域名获取IP地址 {"AT+QISDE", "OK", "ERROR", 300}, //控制是否回显AT+QISEND要发送的 {"AT+QIGETERROR", "OK", "ERROR", 300}, //查询上一个AT命令错误代码 //mqtt cmd {"AT+QMTCFG", "OK", "ERROR", 300}, //配置MQTT可选参数 {"AT+QMTOPEN", "OK", "ERROR", 300}, //打开MQTT客户端网络 {"AT+QMTCLOSE", "OK", "ERROR", 300}, //关闭MQTT客户端网络 {"AT+QMTCONN", "OK", "ERROR", 300}, //连接客户端到MQTT服务器 {"AT+QMTDISC", "OK", "ERROR", 300}, //客户端断开与MQTT服务器的连接 {"AT+QMTSUB", "OK", "ERROR", 300}, //订阅主题 {"AT+QMTUNS", "OK", "ERROR", 300}, //退订主题 {"AT+QMTPUBEX", ">", "ERROR", 300}, //发布消息 {"AT+QMTRECV", "OK", "ERROR", 300}, //从缓存中读取消息 //domain cmd {"AT+CGATT", "OK", "ERROR", 140000}, //PS域附着或去附着 {"AT+CGDCONT", "OK", "ERROR", 3000}, //定义PDP上下文 {"AT+CGQREQ", "OK", "ERROR", 300}, //服务质量参数请求 {"AT+CGQMIN", "OK", "ERROR", 300}, //服务质量参数(最低可接受的) {"AT+CGEQREQ", "OK", "ERROR", 300}, //3G服务质量参数(请求的) {"AT+CGEQMIN", "OK", "ERROR", 300}, //3G 服务质量参数(最低可接受的) {"AT+CGACT", "OK", "ERROR", 150000}, //PDP上下文激活/去激活 {"AT+CGDATA", "OK", "ERROR", 300}, //进入数据传输状态 {"AT+CGPADDR", "OK", "ERROR", 300}, //显示PDP地址 {"AT+CGCLASS", "OK", "ERROR", 300}, //GPRS移动站点等级 {"AT+CGEREG", "OK", "ERROR", 300}, //PS域网络注册状态 {"AT+CGEREP", "OK", "ERROR", 300}, //分组域事件上报 {"AT+CGSMS", "OK", "ERROR", 300}, //选择MO短消息服务 {"AT+CEREG", "OK", "ERROR", 300}, //EPS网络注册状态 {"AT+QGDCNT", "OK", "ERROR", 300}, //流量统计 {"AT+QAUGDCNT", "OK", "ERROR", 300}, //自动保存流量统计 {"AT+QNETDEVCTL", "OK", "ERROR", 2000}, //连接USB网卡 {"AT+QCEERCATCFG", "OK", "ERROR", 300}, //配置2G/4G下AT+CEER返回格式 //hardware cmd {"AT+QPOWD", "OK", "ERROR", 300}, //关闭模块 {"AT+CCLK", "OK", "ERROR", 300}, //实时时钟 {"AT+QSCLK", "OK", "ERROR", 300}, //禁用/启用睡眠模式 }; at_para_t init_para[]={ {AT_CMD_AT, ""}, {AT_CMD_ATE, "0"}, {AT_CMD_CPIN, "?"}, {AT_CMD_CREG, "?"}, //{AT_CMD_QIDEACT, "="CONTEXT_ID}, {AT_CMD_QIACT, "="CONTEXT_ID}, {AT_CMD_CGDCONT, "="CONTEXT_ID",\"IPV4V6\",\"cmnet\""}, {AT_CMD_QCFG, "=\"usbnet\",3"}, //set module to rndis mode {AT_CMD_CMGF, "=1"}, {AT_CMD_CSCS, "=GSM"}, #ifdef GNSS_ENABLE {AT_CMD_QGPS, "=1"}, {AT_CMD_QGPSCFG, "=\"gnssconfig\",5"}, {AT_CMD_QGPSCFG, "=\"gpsnmeatype\",1"}, #endif {-1, ""}, }; /////////////////////////////////////////////////////////////////////////////////////////////////////// static at_cmd_t* data_of(int cmd) { return &all_cmd[cmd]; } static int rssi_to_dbm(int rssi) { int dbm=0; if(rssi>=0 && rssi<=31) { dbm = RSSI_DBM_MIN1+rssi*2; } else if(rssi>=100 && rssi<=191) { dbm = RSSI_DBM_MIN2+rssi; } return dbm; } static char* str_get(char *buf, char c) { int i,len=strlen(buf); for(i=0; imode = 0; pcell->Link_status = false; // 4G网络连接状态 pcell->Signal_strength = 0; // 4G信号强度 sprintf(pcell->Cellular_name, "-"); sprintf(pcell->Cellular_Num, "-"); //pcell->Cellular_IMEI[64]="-"; // IMEI号 // pcell->GPS_status = false; // GPS功能启用 pcell->GPS_latitude = 0.0; // GPS��度 pcell->GPS_longitude = 0.0; // GPS经度 pcell->GPS_altitude = 0.0; // GPS海��高度 pcell->GPS_speed = 0.0; // GPS速度,单位km/h pcell->GPS_nsat = 0; // GPS��星数量 sprintf(pcell->GPS_utc, "-"); //pcell->SMS_status = false; // 短信功能启用 } static int port_init(cell_handle_t *h) { h->fd = open(AT_PORT, O_RDWR | O_NOCTTY | O_NONBLOCK); if(h->fd<0) { return -1; } port_setup(h, BAUD_RATE); //reset_var(h->pcell); return 0; } static int port_deinit(cell_handle_t *h) { if(h->fd<0) { return -1; } return close(h->fd); } static int port_read(cell_handle_t *h, void *data, int len) { return read(h->fd, data, len); } static int port_write(cell_handle_t *h, void *data, int len) { return write(h->fd, data, len); } static int port_setup(cell_handle_t *h, int speed) { struct termios tty; if (tcgetattr(h->fd, &tty) != 0) { LOGE("Read 4G Module tcgetattr!!!\n"); return -1; } cfsetospeed(&tty, speed); cfsetispeed(&tty, speed); tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8; // 8-bit chars tty.c_iflag &= ~IGNBRK; // disable break processing tty.c_lflag = 0; // no signaling chars, no echo, // no canonical processing tty.c_oflag = 0; // no remapping, no delays tty.c_cc[VMIN] = 0; // read doesn't block tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout tty.c_iflag &= ~(IXON | IXOFF | IXANY); // shut off xon/xoff ctrl tty.c_cflag |= (CLOCAL | CREAD); // ignore modem controls, // enable reading tty.c_cflag &= ~(PARENB | PARODD); // shut off parity tty.c_cflag |= 0; tty.c_cflag &= ~CSTOPB; tty.c_cflag &= ~CRTSCTS; if (tcsetattr(h->fd, TCSANOW, &tty) != 0) { LOGE("Read 4G Module tcsetattr!!!\n"); return -1; } return 0; } static int port_wait(cell_handle_t *h, int timeout) { int r; char buf[100]; fd_set fset; struct timeval tv; tv.tv_sec = timeout/1000; tv.tv_usec = (timeout%1000)*1000; FD_ZERO(&fset); FD_SET(h->fd, &fset); r = select(h->fd + 1, &fset, NULL, NULL, &tv); if (r<=0) { if(r<0) { //LOGE("port_wait error %s\n", strerror(errno)); } else { //LOGE("port_wait timeout\n"); } } return r; } static int port_recv(cell_handle_t *h, char *buf, int buflen, int timeout) { int r; r = port_wait(h, timeout); if(r<0) { return -1; } r = port_read(h, buf, buflen); if(r<=0) { return -1; } return r; } static int send_cmd(cell_handle_t *h, int cmd, char *para, char *rcv, int rcvlen) { int i,r,l,tout,finish=0; int tlen=0,buflen,wait_step=10; char buf[BUF_LEN],*pbuf; at_cmd_t *pcmd=data_of(cmd); sprintf(buf, "%s%s\r", pcmd->cmd, para?para:""); LOGD("[tx]: %s\n", buf); for(i=0; itimeout) { l = port_wait(h, wait_step); if(l>0) { if(rcv && rcvlen>0) { pbuf = rcv; buflen = rcvlen; } else { pbuf = buf; buflen = sizeof(buf); } l = port_read(h, pbuf+tlen, buflen); if(l>0) { tlen += l; pbuf[tlen] = 0; LOGD("[rx]: %s\n", pbuf); if(pcmd->ok && strlen(pcmd->ok) && strstr(pbuf, pcmd->ok)) { return AT_OK; } if(pcmd->err && strlen(pcmd->err) && strstr(pbuf, pcmd->err)) { return AT_ERR; } } } tout += wait_step; } } cell_reset(h); return AT_TOUT; } static int send_data(cell_handle_t *h, void *data, int len, int timeout) { char buf[100]; int l,tlen=0,tout=0,wait_step=10; l = port_write(h, data, len); if(l==len) { while(tout0) { l = port_read(h, buf, sizeof(buf)); if(l>0) { tlen += l; buf[tlen] = 0; if(strstr(buf, "OK")) { return AT_OK; } else if(strstr(buf, "ERROR")) { return AT_ERR; } } } tout += wait_step; } } return AT_TOUT; } //////////////////////////////////////////////////////////////////////////// static int cell_reset(cell_handle_t *h) { int r; r = send_cmd(h, AT_CMD_CFUN, "=1,1", NULL, 0); if(r==AT_OK) { h->stat = AT_STAT_UNINIT; } return (r==AT_OK)?0:-1; } static int cell_init(cell_handle_t *h) { int i,r; at_para_t *p=init_para; if(h->stat==AT_STAT_INITED) { return 0; } for(i=0;; i++) { if(p[i].cmd==-1) { break; } if(p[i].cmd==AT_CMD_CGDCONT) { sprintf(p[i].para, "=%s,\"IPV4V6\",\"%s\"", CONTEXT_ID, h->pcell->apn); } else if(p[i].cmd==AT_CMD_QICSGP) { sprintf(p[i].para, "=%s,3,\"%s\"", CONTEXT_ID, h->pcell->apn); } r = send_cmd(h, p[i].cmd, p[i].para, NULL, 0); if(r!=AT_OK) { break; } } if(r==0) { h->stat = AT_STAT_INITED; cell_get_info(h, &h->all.info); } return r?-1:0; } static int cell_deinit(cell_handle_t *h) { if(h->stat==AT_STAT_UNINIT) { return -1; } return 0; } static int cell_get_info(cell_handle_t *h, cell_info_t *info) { int r; char buf[400]; if(h->stat==AT_STAT_UNINIT) { return -1; } memset(info, 0, sizeof(cell_info_t)); r = send_cmd(h, AT_CMD_CNUM, NULL, buf, sizeof(buf)); if(r==AT_OK) { r = sscanf(str_get(buf,'+'), "+CNUM: %*s,%s,%*d", info->cnum); } r = send_cmd(h, AT_CMD_GSN, NULL, buf, sizeof(buf)); if(r==AT_OK) { r = sscanf(str_get(buf,'+'), "%s", info->imei); } r = send_cmd(h, AT_CMD_CIMI, NULL, buf, sizeof(buf)); if(r==AT_OK) { r = sscanf(str_get(buf,'+'), "%s", info->imsi); } r = send_cmd(h, AT_CMD_CGDCONT, "?", buf, sizeof(buf)); if(r==AT_OK) { r = sscanf(str_get(buf,'+'), "+CGDCONT: %*d,\"%*[^\"]\",\"%[^\"]", info->apn); } r = send_cmd(h, AT_CMD_COPS, "?", buf, sizeof(buf)); if(r==AT_OK) { r = sscanf(str_get(buf,'+'), "+COPS: %*d,%*d,\"%[^\"]", info->isp); } LOGD("___info->apn: %s\n", info->apn); LOGD("___info->isp: %s\n", info->isp); LOGD("___info->imei: %s\n", info->imei); LOGD("___info->imsi: %s\n", info->imsi); LOGD("___info->cnum: %s\n", info->cnum); return 0; } static int cell_get_sig(cell_handle_t *h, cell_stat_t *stat) { char buf[200]; int rssi,ber,r=-1; if(h->stat==AT_STAT_UNINIT) { return -1; } r = send_cmd(h, AT_CMD_CSQ, NULL, buf, sizeof(buf)); if(r!=AT_OK) { return -1; } r = sscanf(str_get(buf,'+'), "%*s %d,%d", &rssi, &ber); if(r<2) { return -1; } stat->dbm = rssi_to_dbm(rssi); stat->ber = ber; return 0; } static int cell_get_gnss(cell_handle_t *h, cell_stat_t *stat) { int r; char buf[200],utc[32],date[32]; #ifdef GNSS_ENABLE if(h->stat==AT_STAT_UNINIT) { return -1; } r = send_cmd(h, AT_CMD_QGPSLOC, "=0", buf, sizeof(buf)); if(r!=AT_OK) { return -1; } r = sscanf(str_get(buf,'+'), "+QGPSLOC: %s,%s,%s,%*d,%d,%*d,%*d,%*d,%*d,%s,%d", utc, stat->latitude, stat->longitude, &stat->altitude, date, &stat->nsta); if(r<6) { return -1; } // #endif return 0; } static int cell_get_ping(cell_handle_t *h, cell_stat_t *stat) { int r,ret; char buf[200],utc[32],date[32]; if(h->stat==AT_STAT_UNINIT) { return -1; } r = send_cmd(h, AT_CMD_QPING, "=1,\"163.com\",3,2,", buf, sizeof(buf)); if(r!=AT_OK) { return -1; } r = sscanf(str_get(buf,'+'), "+QPING: %d", &ret); if(r<1) { return -1; } if(ret==0) { stat->linked = 1; } else { stat->linked = 0; } return 0; } static int cell_get_time(cell_handle_t *h, cell_stat_t *stat) { int r,offset; char opr,buf[200],date[24],time[24]; struct tm utc_tm; if(h->stat==AT_STAT_UNINIT) { return -1; } r = send_cmd(h, AT_CMD_QLTS, "=1", buf, sizeof(buf)); if(r!=AT_OK) { return -1; } r = sscanf(str_get(buf,'+'), "+QLTS: \"%d/%d/%d,%d:%d:%d",&utc_tm.tm_year,&utc_tm.tm_mon,&utc_tm.tm_mday,&utc_tm.tm_hour,&utc_tm.tm_min,&utc_tm.tm_sec); if(r<6) { return -1; } stat->utctime = mktime2(&utc_tm, 0); //print_time("999", &utc_tm); return 0; } static int cell_get_stat(cell_handle_t *h, cell_stat_t *stat) { if(h->stat==AT_STAT_UNINIT) { return -1; } cell_get_sig(h, stat); cell_get_gnss(h, stat); cell_get_ping(h, stat); cell_get_time(h, stat); return 0; } static int cell_sock_conn(cell_handle_t *h, int sock, char *host, uint16_t port, sock_conn_t *conn) { int r; char buf[200]; if(h->stat==AT_STAT_UNINIT) { return -1; } sprintf(buf, "=%s,%s,%s,“%s”,%d,0,1", CONTEXT_ID, CONNECT_ID, (sock==SOCK_TCP)?"TCP":"UDP", host, port); r = send_cmd(h, AT_CMD_QIOPEN, buf, NULL, 0); if(r!=AT_OK) { return -1; } conn->h = h; conn->sock = sock; conn->cont_id = atoi(CONTEXT_ID); conn->conn_id = atoi(CONNECT_ID); return 0; } static int cell_sock_disconn(sock_conn_t *conn) { int r; char buf[200]; cell_handle_t *h=(cell_handle_t*)conn->h; if(h->stat==AT_STAT_UNINIT) { return -1; } sprintf(buf, "=%s,%s", CONNECT_ID, CONNECT_TIMEOUT); r = send_cmd(h, AT_CMD_QICLOSE, buf, NULL, 0); if(r!=AT_OK) { return -1; } conn->h = NULL; conn->sock = -1; conn->cont_id = -1; conn->conn_id = -1; return 0; } static int cell_sock_send(sock_conn_t *conn, void *data, int len) { int r=0,rt,offset=0,remain_len,send_len; char buf[100],*pd=(char*)data; cell_handle_t *h=(cell_handle_t*)conn->h; if(h->stat==AT_STAT_UNINIT) { return -1; } sprintf(buf, "=%d,%d", conn->conn_id, len); rt = send_cmd(h, AT_CMD_QISEND, buf, NULL, 0); if(rt!=AT_OK) { return -1; } while(offsetCHUNCK_SIZE)?CHUNCK_SIZE:remain_len; rt = send_data(h, data+offset, send_len, 500); if(rt!=AT_OK) { r = -1; break; } offset += send_len; } return r; } static int cell_sock_stat(sock_conn_t *conn) { int r; char buf[100]; cell_handle_t *h=(cell_handle_t*)conn->h; if(h->stat==AT_STAT_UNINIT) { return -1; } r = send_cmd(h, AT_CMD_QISTATE, NULL, buf, sizeof(buf)); if(r!=AT_OK) { return -1; } return 0; } static int cell_sock_connected(cell_handle_t *h) { return 0; } static int cell_send_sms(cell_handle_t *h, char *number, char *txt) { int r=-1,rt; char tmp[100],buf[200]; if(h->stat==AT_STAT_UNINIT) { return -1; } sprintf(tmp, "=\"%s\"", number); r = send_cmd(h, AT_CMD_CMGS, tmp, buf, sizeof(buf)); if(r!=AT_OK) { return -1; } snprintf(buf, sizeof(buf), "%s\x1a", txt); r = send_data(h, buf, strlen(buf), 5000); return r; } static int cell_send_call(cell_handle_t *h, char *number, void *data, int len) { int r; char buf[100]; if(h->stat==AT_STAT_UNINIT) { return -1; } sprintf(buf, "%s", number); r = send_cmd(h, AT_CMD_ATD, NULL, buf, sizeof(buf)); if(r!=AT_OK) { return -1; } return 0; } ///////////////////////////////////////////////////////////////////////// static int conn_cfg(mqtt_conn_t *conn, char *item, char *value) { int r; char tmp[100],buf[200]; cell_handle_t *h=(cell_handle_t*)conn->h; if(h->stat==AT_STAT_UNINIT) { return -1; } sprintf(tmp, "=\"%s\",%s", item, value); r = send_cmd(h, AT_CMD_QMTCFG, NULL, buf, sizeof(buf)); if(r!=AT_OK) { return -1; } return 0; } static void conn_init(cell_handle_t *h, mqtt_conn_t *conn) { char buf[100]; conn->h = h; conn->ver = MQTT_VER; conn->pdpId = conn->cliId+1; //1~15 conn->msgId = 0; conn->qos = MQTT_QOS; conn->retain = 1; conn->will.flag = MQTT_WILL; conn->will.qos = MQTT_QOS; conn->will.retain = MQTT_RETAIN; strcpy(conn->will.topic, ""); strcpy(conn->will.message, ""); conn->will.message_len = strlen(conn->will.message); conn->timeout = 10; //1~60, default:5 conn->retry_times = 3; conn->timeout_notice = 1; conn->clean_session = 1; conn->ssl_enable = 0; conn->ssl_ctx_id = 0; conn->msg_recv_mode = 0; //0: urc, 1: not urc conn->msg_len_enable = 1; conn->ping_interval = 5; //5~60, default:5 conn->proto_chk_enable = 0; //0:no check 1:check conn->send_mode = 0; //0:string 1:hex conn->recv_mode = 0; //0:string 1:hex conn->view_mode = 0; //0:no echo 1:echo conn->edit_mode = 0; //0:timeout not quit 1:timeout quit conn->edit_time = 5; //1~120 seconds //conn->plat.product_key[64]; //aliyun used //conn->plat.device_name[64]; //aliyun used //conn->plat.device_secret[64]; //aliyun/ used //conn->plat.hw_time_enable; //huawei used //conn->plat.product_secret[64]; //huawei used //conn->plat.node_id[64]; //conn->plat.product_id[64]; //onenet used //conn->plat.access_key[64]; //onenet used sprintf(buf, "%d,%d", conn->cliId, conn->ver); conn_cfg(conn, "version", buf); sprintf(buf, "%d,%d", conn->cliId, conn->pdpId); conn_cfg(conn, "pdpcid", buf); sprintf(buf, "%d,%d", conn->cliId, conn->keep_alive_time); conn_cfg(conn, "keepalive", buf); sprintf(buf, "%d,%d", conn->cliId, conn->clean_session); conn_cfg(conn, "session", buf); sprintf(buf, "%d,%d,%d,%d", conn->cliId, conn->timeout, conn->retry_times, conn->timeout_notice); conn_cfg(conn, "timeout", buf); sprintf(buf, "%d,%d,%d", conn->cliId, conn->ssl_enable, conn->ssl_ctx_id); conn_cfg(conn, "ssl", buf); sprintf(buf, "%d,%d", conn->cliId, conn->ping_interval); conn_cfg(conn, "qmtping", buf); //sprintf(buf, "%d,%d,%d,%d,\"%s\",\"%s\"", conn->cliId, conn->will.flag, conn->will.qos, conn->will.retain, conn->will.topic, conn->will.message); //conn_cfg(conn, "will", buf); //sprintf(buf, "%d,%d,%d,%d,\"%s\",%d", conn->cliId, conn->will.flag, conn->will.qos, conn->will.retain, conn->will.topic, conn->will.message_len); //conn_cfg(conn, "willex", buf); sprintf(buf, "%d,%d", conn->cliId, conn->send_mode); conn_cfg(conn, "send/mode", buf); sprintf(buf, "%d,%d,%d", conn->cliId, conn->msg_recv_mode, conn->msg_len_enable); conn_cfg(conn, "recv/mode", buf); sprintf(buf, "%d,%d", conn->cliId, conn->view_mode); conn_cfg(conn, "view/mode", buf); sprintf(buf, "%d,%d,%d", conn->cliId, conn->edit_mode, conn->edit_time); conn_cfg(conn, "edit/timeout", buf); sprintf(buf, "%d,%d", conn->cliId, conn->proto_chk_enable); conn_cfg(conn, "protocol/check", buf); sprintf(buf, "%d,%d,%d", conn->cliId, conn->send_mode, conn->recv_mode); conn_cfg(conn, "dataformat", buf); #if 0 //aliyun sprintf(buf, "%d,\"%s\",\"%s\",\"%s\"", conn->cliId, conn->plat.product_key, conn->plat.device_name, conn->plat.device_secret); conn_cfg(conn, "aliauth", buf); #endif #if 0 //huawei sprintf(buf, "%d,\"%s\",\"%s\"", conn->cliId, conn->plat.product_id, conn->plat.device_secret); conn_cfg(conn, "hwauth", buf); sprintf(buf, "%d,\"%s\",\"%s\",\"%s\"", conn->cliId, conn->plat.product_id, conn->plat.product_secret, conn->plat.node_id); conn_cfg(conn, "hwprodid", buf); #endif #if 0 //onenet sprintf(buf, "%d,\"%s\",\"%s\"", conn->cliId, conn->plat.product_id, conn->plat.access_key); conn_cfg(conn, "onenet", buf); #endif } static int cell_test(cell_handle_t *h) { int r; cell_info_t info; cell_stat_t stat; cell_get_info(h, &info); while(1) { r = cell_get_stat(h, &stat); if(r==0) { LOGD("___dbm: %d ber: %d\n", stat.dbm, stat.ber); } else { LOGE("___ get stat failed\n"); } sleep(3); } return 0; } ///////////////////////////////////////////////////////////////////////// static int urc_handle(char *data, int len) { char *key=NULL; key = "+QIURC: "; if(strstr(data, key)) { } key = "+QMT"; if(strstr(data, key)) { } return 0; } static void* cellular_thread(void *arg) { int r; uint32_t cnt=0; char rxbuf[BUF_LEN]; thread_handle_t *th=(thread_handle_t*)arg; cell_handle_t *h=(cell_handle_t*)th->arg; port_init(h); while (th->quit==0) { cnt++; if(h->pcell->mode) { if(cnt%5==0) { cell_init(h); } if(cnt%5==0) { cell_get_stat(h, &h->all.stat); } } sleep(1); } cell_deinit(h); port_deinit(h); pthread_exit(NULL); } #endif int cellular_reset(void) { int r=-1; cell_handle_t *h=&ceHandle; #ifdef USE_CELL r = cell_reset(h); #endif return r; } int cellular_init(void) { int r; cell_handle_t *h=&ceHandle; #ifdef USE_CELL memset(h, 0, sizeof(cell_handle_t)); h->dm = &__globalDeviceManage; h->pcell = &h->dm->_globalDevInfo.cell; h->prod_id = h->dm->_globalDevInfo.product.id; h->lck = lock_d_init(); thread_start(THREAD_ID_CELLULAR, cellular_thread, h); while(1) sleep(10); #endif return 0; } int cellular_deinit(void) { cell_handle_t *h=&ceHandle; #ifdef USE_CELL lock_d_deinit(h->lck); thread_stop(THREAD_ID_CELLULAR); #endif return 0; } int cellular_get_all(cell_all_t *all) { int r=-1; cell_handle_t *h=&ceHandle; #ifdef USE_CELL if(all) { *all = h->all; r = 0; } #endif return r; } int cellular_is_connected(void) { int r=0; cell_handle_t *h=&ceHandle; #ifdef USE_CELL r = h->all.stat.linked; #endif return r; } int cellular_test(void) { cell_handle_t *h=&ceHandle; #ifdef USE_CELL cell_test(h); #endif return 0; }