我们公司和移远有合作所以得到了他们EC20的二次开发的开发板。下面是我开发4G图像传输的总结(工作方式有两种,一种AT一种socket)。
下面先是AT命令
一.在linux下解压文件
解压如下文件

二.安装SDK
每次开新的终端进行编译都要进行环境变量的设置

三.进入历程

四.修改历程
#include "ql_oe.h" #include
#include
#include
#include
#include
#include
#include
#include
//those define was added by myself #define MAXLINE 1024 //一次读取最大的字节数 #define QUEC_AT_PORT "/dev/smd8" static int smd_fd = -1; int Ql_SendAT(char* atCmd, char* finalRsp, long timeout_ms, int should_Add); int main(int argc, char* argv[]) { FILE *from_file; //need send to server char buf[MAXLINE]; char receive_buf[100]; int read_len; char str[10]; printf("< Quectel OpenLinux: AT example >\n"); smd_fd = open(QUEC_AT_PORT, O_RDWR | O_NONBLOCK | O_NOCTTY); //打开虚拟串口 printf("< open(\"%s\")=%d >\n", QUEC_AT_PORT, smd_fd); Ql_SendAT("AT+COPS?", "OK", 1000, 0); //检查网络 if((from_file=open("timg.jpg",O_RDWR))==NULL) //打开要读取的文件 { printf("Can't open the file \n"); exit(1); } Ql_SendAT("AT+QIOPEN=1,2,\"UDP SERVICE\",\"127.0.0.1\",0,3030,0", "OK", 1000, 0); //建立UDP服务 Ql_SendAT("AT+QISTATE=0,1", "OK", 1000, 0); while ( (read_len = read(from_file, buf, MAXLINE)) > 0 ) //读取文件知道读完 { printf("read_len = %d\n", read_len); sprintf(str,"%d",read_len); //将int型整数转为char型 sprintf(receive_buf, "AT+QISEND=2,%s,\"148.70.42.237\",3333", str); //合成发送命令 Ql_SendAT(receive_buf, "OK", 1000, 0); //发送发送命令 Ql_SendAT(buf, "SEND OK", 5000, read_len); //添加发送的数据 bzero(receive_buf, 100); //清空数组 bzero(buf, MAXLINE); } printf("read_len = %d\n", read_len); Ql_SendAT("AT+QICLOSE=2", "OK", 1000, 0); close(from_file); //关闭文件 close(smd_fd); //关闭虚拟串口 printf("< Quectel OpenLinux: AT example end >\n\n"); return 0; } int Ql_SendAT(char* atCmd, char* finalRsp, long timeout_ms, int should_Add)//should_Add是判断是否末尾要加入\r\n,如果不添加则还代表atCmd数据的长度 { int iRet; int iLen; fd_set fds; int rdLen; #define lenToRead 100 char strAT[100]; char strFinalRsp[100]; char strResponse[100]; struct timeval timeout = {0, 0}; boolean bRcvFinalRsp = FALSE; sprintf(strFinalRsp, "\r\n%s", finalRsp); timeout.tv_sec = timeout_ms / 1000; timeout.tv_usec = timeout_ms % 1000; // Send AT if( should_Add != 0 ) { iRet = write(smd_fd, atCmd, should_Add); printf("iLen = %d", should_Add); } else { memset(strAT, 0x0, sizeof(strAT)); iLen = sizeof(atCmd); strncpy(strAT, atCmd, iLen);iLen = strlen(atCmd); if ((atCmd[iLen-1] != '\r') && (atCmd[iLen-1] != '\n')) { iLen = sprintf(strAT, "%s\r\n", atCmd); strAT[iLen] = 0; } iRet = write(smd_fd, strAT, iLen); } //printf(">>Send AT: \"%s\", iRet=%d\n", atCmd, iRet); // Wait for the response while (1) { FD_ZERO(&fds); FD_SET(smd_fd, &fds); //printf("timeout.tv_sec=%d, timeout.tv_usec: %d \n", (int)timeout.tv_sec, (int)timeout.tv_usec); switch (select(smd_fd + 1, &fds, NULL, NULL, &timeout)) //switch (select(smd_fd + 1, &fds, NULL, NULL, NULL)) // block mode { case -1: printf("< select error >\n"); return -1; case 0: printf("< time out >\n"); return 1; default: if (FD_ISSET(smd_fd, &fds)) { do { memset(strResponse, 0x0, sizeof(strResponse)); rdLen = read(smd_fd, strResponse, lenToRead); //printf(">>Read response/urc, len=%d, content:\n%s\n", rdLen, strResponse); //printf("rcv:%s", strResponse); //printf("final rsp:%s", strFinalRsp); if ((rdLen > 0) && strstr(strResponse, strFinalRsp)) { if (strstr(strResponse, strFinalRsp) // final OK response || strstr(strResponse, "+CME ERROR:") // +CME ERROR || strstr(strResponse, "+CMS ERROR:") // +CMS ERROR || strstr(strResponse, "ERROR")) // Unknown ERROR { //printf("\n< match >\n"); bRcvFinalRsp = TRUE; }else{ printf("\n< not final rsp >\n"); } } } while ((rdLen > 0) && (lenToRead == rdLen)); }else{ printf("FD is missed\n"); } break; } // Found the final response , return back if (bRcvFinalRsp) { break; } } return 0; }
然后make编译 注意字符串格式获取长度少用strlen,因为0x00是字符串的结束符。如果发送二进制遇到0x13,0x10这些出问题可以修改串口的属性。
五.进入开发板的linux系统

六.上传文件
使用Zmoden上传文件。注意移远给的系统只有usrdata是可写的。然后修改权限为可执行。
chmod 777 example_at
七.运行程序
./example_at
下面是socket程序,运行方法和上方一样
先要拨号,不然无法socket运行起来,下面是拨号程序
#include
#include
#include
#include
#include
#include
#include "ql_wwan_v2.h" static void data_call_state_callback(ql_data_call_state_s *state) { printf("profile id %d ", state->profile_idx); printf("IP family %s ", QL_DATA_CALL_TYPE_IPV4 == state->ip_family ? "v4" : "v6"); if(QL_DATA_CALL_CONNECTED == state->state) { printf("is Connected\n"); printf("Interface Name: %s\n", state->name); if(QL_DATA_CALL_TYPE_IPV4 == state->ip_family) { printf("IP address: %s\n", inet_ntoa(state->v4.ip)); printf("Gateway address: %s\n", inet_ntoa(state->v4.gateway)); printf("Primary DNS address: %s\n", inet_ntoa(state->v4.pri_dns)); printf("Second DNS address: %s\n", inet_ntoa(state->v4.sec_dns)); } else { char ipv6_buffer[INET6_ADDRSTRLEN]; inet_ntop(AF_INET6, (void *)&state->v6.ip, ipv6_buffer, INET6_ADDRSTRLEN); printf("IP address: %s\n", ipv6_buffer); inet_ntop(AF_INET6, (void *)&state->v6.gateway, ipv6_buffer, INET6_ADDRSTRLEN); printf("Gateway address: %s\n", ipv6_buffer); inet_ntop(AF_INET6, (void *)&state->v6.pri_dns, ipv6_buffer, INET6_ADDRSTRLEN); printf("Primary DNS address: %s\n", ipv6_buffer); inet_ntop(AF_INET6, (void *)&state->v6.sec_dns, ipv6_buffer, INET6_ADDRSTRLEN); printf("Second DNS address: %s\n", ipv6_buffer); } printf("\n"); } else { printf("is disconnected, and reason code 0x%x\n", state->err); } } int main(int argc, char argv) { int retry = 10; int loop; ql_data_call_s data_call[3]; ql_data_call_info_s data_call_info; ql_data_call_error_e err = QL_DATA_CALL_ERROR_NONE; memset(&data_call, 0, sizeof(data_call)); /* * The dialup API relies on the Quectel Manager service. If the program is not initialized successfully, * debugging these API interfaces will fail, so here is judged whether the service is started normally. */ while(0 != QL_Data_Call_Init_Precondition() && 0 != retry) { printf("The Quectel manager service is not initialized, about 500ms try again.\n"); usleep(500*1000); retry--; } if(0 == retry) { printf("Data call failure\n"); exit(0); } if(QL_Data_Call_Init(data_call_state_callback)) { printf("Initialization data call failure\n"); exit(0); } for(loop = 0; loop < sizeof(data_call)/sizeof(data_call[0]); loop++) { memset(&data_call_info, 0, sizeof(data_call_info)); err = QL_DATA_CALL_ERROR_NONE; data_call[loop].profile_idx = loop+1; /* * If your data call program is coredump, the data call status will not disappear automatically. * When your program is start again, you need to call the QL_Data_Call_Info_Get interface to get * the data call status. Because it is already in the data call state, you call QL_Data_Call_Start * again without callback function */ if(QL_Data_Call_Info_Get(data_call[loop].profile_idx, QL_DATA_CALL_TYPE_IPV4, &data_call_info, &err)) { printf("get profile index %d information failure: errno 0x%x\n", data_call[loop].profile_idx, err); continue; } if(QL_DATA_CALL_CONNECTED == data_call_info.v4.state) { printf("the profile index %d is already connected, don't up\n", data_call[loop].profile_idx); continue; } data_call[loop].ip_family = QL_DATA_CALL_TYPE_IPV4; data_call[loop].reconnect = true; err = QL_DATA_CALL_ERROR_NONE; if(QL_Data_Call_Start(&data_call[loop], &err)) { printf("the profile index %d start data call failure: 0x%x\n", data_call[loop].profile_idx, err); } printf("the profile index %d start data call success\n", data_call[loop].profile_idx); usleep(500*1000); } sleep(3600); return 0; }
然后soket传输图像
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define SERVER_PORT 3333 #define MAXLINE 1024 int main(int argc,char argv) { //new add /*int retry = 10; int loop; ql_data_call_s data_call[3]; ql_data_call_info_s data_call_info; ql_data_call_error_e err = QL_DATA_CALL_ERROR_NONE; memset(&data_call, 0, sizeof(data_call));*/ int sockfd; int read_len; FILE *from_file; //need send to server char buf[MAXLINE]; struct sockaddr_in cliaddr; bzero(&cliaddr, sizeof(cliaddr)); cliaddr.sin_family = AF_INET; cliaddr.sin_port = htons(3333); cliaddr.sin_addr.s_addr = inet_addr("148.70.42.237"); sockfd=socket(AF_INET,SOCK_DGRAM,0); if(sockfd<0) { fprintf(stderr,"Socket Error:%s\n",strerror(errno)); exit(1); } if((from_file=open("timg.jpg",O_RDWR))==NULL) { printf("Can't open the file \n"); exit(1); } while ( (read_len = read(from_file, buf, MAXLINE)) > 0 ) { sendto(sockfd, buf ,read_len, 0 , (struct sockaddr*)&cliaddr, sizeof(cliaddr)); bzero(buf, MAXLINE); } close(from_file); close(sockfd); }
程序也是先运行拨号的再运行socket
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/221202.html原文链接:https://javaforall.net
