移远EC20二次开发之4G图像传输

原文地址::https://blog.csdn.net/qq_35570735/article/details/87180048?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.edu_weight&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.edu_weight

相关文章

1、移远 EC20 模组(4G通信模组)AT指令测试 TCP 通信过程----https://blog.csdn.net/Mculover666/article/details/105877183?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.edu_weight&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.edu_weight

2、EC20 HTTP 图片传输----https://blog.csdn.net/m0_37777700/article/details/104696505?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.edu_weight&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.edu_weight

 

 

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

     下面先是AT命令

      一.在linux下解压文件

              解压如下文件

           

      二.安装SDK

             每次开新的终端进行编译都要进行环境变量的设置

      三.进入历程

           

      四.修改历程

           

 
  1. #include "ql_oe.h"

  2. #include

  3. #include

  4. #include

  5. #include

  6. #include

  7. #include

  8. #include

  9. #include

  10.  
  11. //those define was added by myself

  12. #define MAXLINE 1024 //一次读取最大的字节数

  13.  
  14. #define QUEC_AT_PORT "/dev/smd8"

  15.  
  16. static int smd_fd = -1;

  17. int Ql_SendAT(char* atCmd, char* finalRsp, long timeout_ms, int should_Add);

  18.  
  19. int main(int argc, char* argv[])

  20. {

  21. FILE *from_file; //need send to server

  22. char buf[MAXLINE];

  23. char receive_buf[100];

  24. int read_len;

  25. char str[10];

  26. printf("< Quectel OpenLinux: AT example >\n");

  27.  
  28. smd_fd = open(QUEC_AT_PORT, O_RDWR | O_NONBLOCK | O_NOCTTY); //打开虚拟串口

  29. printf("< open(\"%s\")=%d >\n", QUEC_AT_PORT, smd_fd);

  30.  
  31. Ql_SendAT("AT+COPS?", "OK", 1000, 0); //检查网络

  32.  
  33. if((from_file=open("timg.jpg",O_RDWR))==NULL) //打开要读取的文件

  34. {

  35. printf("Can't open the file \n");

  36. exit(1);

  37. }

  38.  
  39. Ql_SendAT("AT+QIOPEN=1,2,\"UDP SERVICE\",\"127.0.0.1\",0,3030,0", "OK", 1000, 0); //建立UDP服务

  40. Ql_SendAT("AT+QISTATE=0,1", "OK", 1000, 0);

  41.  
  42. while ( (read_len = read(from_file, buf, MAXLINE)) > 0 ) //读取文件知道读完

  43. {

  44.  
  45. printf("read_len = %d\n", read_len);

  46. sprintf(str,"%d",read_len); //将int型整数转为char型

  47.  
  48. sprintf(receive_buf, "AT+QISEND=2,%s,\"148.70.42.237\",3333", str); //合成发送命令

  49.  
  50. Ql_SendAT(receive_buf, "OK", 1000, 0); //发送发送命令

  51.  
  52. Ql_SendAT(buf, "SEND OK", 5000, read_len); //添加发送的数据

  53. bzero(receive_buf, 100); //清空数组

  54. bzero(buf, MAXLINE);

  55. }

  56. printf("read_len = %d\n", read_len);

  57. Ql_SendAT("AT+QICLOSE=2", "OK", 1000, 0);

  58. close(from_file); //关闭文件

  59. close(smd_fd); //关闭虚拟串口

  60. printf("< Quectel OpenLinux: AT example end >\n\n");

  61. return 0;

  62. }

  63.  
  64.  
  65. int Ql_SendAT(char* atCmd, char* finalRsp, long timeout_ms, int should_Add)//should_Add是判断是否末尾要加入\r\n,如果不添加则还代表atCmd数据的长度

  66. {

  67. int iRet;

  68. int iLen;

  69. fd_set fds;

  70. int rdLen;

  71. #define lenToRead 100

  72. char strAT[100];

  73. char strFinalRsp[100];

  74. char strResponse[100];

  75. struct timeval timeout = {0, 0};

  76. boolean bRcvFinalRsp = FALSE;

  77.  
  78. sprintf(strFinalRsp, "\r\n%s", finalRsp);

  79.  
  80. timeout.tv_sec = timeout_ms / 1000;

  81. timeout.tv_usec = timeout_ms % 1000;

  82.  
  83. // Send AT

  84. if( should_Add != 0 )

  85. {

  86. iRet = write(smd_fd, atCmd, should_Add);

  87. printf("iLen = %d", should_Add);

  88. }

  89. else

  90. {

  91. memset(strAT, 0x0, sizeof(strAT));

  92. iLen = sizeof(atCmd);

  93. strncpy(strAT, atCmd, iLen);iLen = strlen(atCmd);

  94. if ((atCmd[iLen-1] != '\r') && (atCmd[iLen-1] != '\n'))

  95. {

  96. iLen = sprintf(strAT, "%s\r\n", atCmd);

  97. strAT[iLen] = 0;

  98. }

  99. iRet = write(smd_fd, strAT, iLen);

  100. }

  101. //printf(">>Send AT: \"%s\", iRet=%d\n", atCmd, iRet);

  102.  
  103. // Wait for the response

  104. while (1)

  105. {

  106. FD_ZERO(&fds);

  107. FD_SET(smd_fd, &fds);

  108.  
  109. //printf("timeout.tv_sec=%d, timeout.tv_usec: %d \n", (int)timeout.tv_sec, (int)timeout.tv_usec);

  110. switch (select(smd_fd + 1, &fds, NULL, NULL, &timeout))

  111. //switch (select(smd_fd + 1, &fds, NULL, NULL, NULL)) // block mode

  112. {

  113. case -1:

  114. printf("< select error >\n");

  115. return -1;

  116.  
  117. case 0:

  118. printf("< time out >\n");

  119. return 1;

  120.  
  121. default:

  122. if (FD_ISSET(smd_fd, &fds))

  123. {

  124. do {

  125. memset(strResponse, 0x0, sizeof(strResponse));

  126. rdLen = read(smd_fd, strResponse, lenToRead);

  127. //printf(">>Read response/urc, len=%d, content:\n%s\n", rdLen, strResponse);

  128. //printf("rcv:%s", strResponse);

  129. //printf("final rsp:%s", strFinalRsp);

  130. if ((rdLen > 0) && strstr(strResponse, strFinalRsp))

  131. {

  132. if (strstr(strResponse, strFinalRsp) // final OK response

  133. || strstr(strResponse, "+CME ERROR:") // +CME ERROR

  134. || strstr(strResponse, "+CMS ERROR:") // +CMS ERROR

  135. || strstr(strResponse, "ERROR")) // Unknown ERROR

  136. {

  137. //printf("\n< match >\n");

  138. bRcvFinalRsp = TRUE;

  139. }else{

  140. printf("\n< not final rsp >\n");

  141. }

  142. }

  143. } while ((rdLen > 0) && (lenToRead == rdLen));

  144. }else{

  145. printf("FD is missed\n");

  146. }

  147. break;

  148. }

  149.  
  150. // Found the final response , return back

  151. if (bRcvFinalRsp)

  152. {

  153. break;

  154. }

  155. }

  156. return 0;

  157. }

    然后make编译   注意字符串格式获取长度少用strlen,因为0x00是字符串的结束符。如果发送二进制遇到0x13,0x10这些出问题可以修改串口的属性。

    五.进入开发板的linux系统

         

   六.上传文件

        使用Zmoden上传文件。注意移远给的系统只有usrdata是可写的。然后修改权限为可执行。

chmod 777 example_at

   七.运行程序

    

./example_at

 

  下面是socket程序,运行方法和上方一样

   先要拨号,不然无法socket运行起来,下面是拨号程序

 
  1. #include

  2. #include

  3. #include

  4. #include

  5. #include

  6. #include

  7. #include "ql_wwan_v2.h"

  8.  
  9. static void data_call_state_callback(ql_data_call_state_s *state)

  10. {

  11. printf("profile id %d ", state->profile_idx);

  12. printf("IP family %s ", QL_DATA_CALL_TYPE_IPV4 == state->ip_family ? "v4" : "v6");

  13. if(QL_DATA_CALL_CONNECTED == state->state) {

  14. printf("is Connected\n");

  15. printf("Interface Name: %s\n", state->name);

  16. if(QL_DATA_CALL_TYPE_IPV4 == state->ip_family) {

  17. printf("IP address: %s\n", inet_ntoa(state->v4.ip));

  18. printf("Gateway address: %s\n", inet_ntoa(state->v4.gateway));

  19. printf("Primary DNS address: %s\n", inet_ntoa(state->v4.pri_dns));

  20. printf("Second DNS address: %s\n", inet_ntoa(state->v4.sec_dns));

  21. } else {

  22. char ipv6_buffer[INET6_ADDRSTRLEN];

  23. inet_ntop(AF_INET6, (void *)&state->v6.ip, ipv6_buffer, INET6_ADDRSTRLEN);

  24. printf("IP address: %s\n", ipv6_buffer);

  25. inet_ntop(AF_INET6, (void *)&state->v6.gateway, ipv6_buffer, INET6_ADDRSTRLEN);

  26. printf("Gateway address: %s\n", ipv6_buffer);

  27. inet_ntop(AF_INET6, (void *)&state->v6.pri_dns, ipv6_buffer, INET6_ADDRSTRLEN);

  28. printf("Primary DNS address: %s\n", ipv6_buffer);

  29. inet_ntop(AF_INET6, (void *)&state->v6.sec_dns, ipv6_buffer, INET6_ADDRSTRLEN);

  30. printf("Second DNS address: %s\n", ipv6_buffer);

  31. }

  32. printf("\n");

  33. } else {

  34. printf("is disconnected, and reason code 0x%x\n", state->err);

  35. }

  36. }

  37.  
  38. int main(int argc, char **argv)

  39. {

  40. int retry = 10;

  41. int loop;

  42. ql_data_call_s data_call[3];

  43. ql_data_call_info_s data_call_info;

  44. ql_data_call_error_e err = QL_DATA_CALL_ERROR_NONE;

  45.  
  46. memset(&data_call, 0, sizeof(data_call));

  47.  
  48. /*

  49. * The dialup API relies on the Quectel Manager service. If the program is not initialized successfully,

  50. * debugging these API interfaces will fail, so here is judged whether the service is started normally.

  51. */

  52. while(0 != QL_Data_Call_Init_Precondition() && 0 != retry) {

  53. printf("The Quectel manager service is not initialized, about 500ms try again.\n");

  54. usleep(500*1000);

  55. retry--;

  56. }

  57.  
  58. if(0 == retry) {

  59. printf("Data call failure\n");

  60. exit(0);

  61. }

  62.  
  63. if(QL_Data_Call_Init(data_call_state_callback)) {

  64. printf("Initialization data call failure\n");

  65. exit(0);

  66. }

  67.  
  68. for(loop = 0; loop < sizeof(data_call)/sizeof(data_call[0]); loop++) {

  69. memset(&data_call_info, 0, sizeof(data_call_info));

  70. err = QL_DATA_CALL_ERROR_NONE;

  71. data_call[loop].profile_idx = loop+1;

  72. /*

  73. * If your data call program is coredump, the data call status will not disappear automatically.

  74. * When your program is start again, you need to call the QL_Data_Call_Info_Get interface to get

  75. * the data call status. Because it is already in the data call state, you call QL_Data_Call_Start

  76. * again without callback function

  77. */

  78. if(QL_Data_Call_Info_Get(data_call[loop].profile_idx, QL_DATA_CALL_TYPE_IPV4, &data_call_info, &err)) {

  79. printf("get profile index %d information failure: errno 0x%x\n", data_call[loop].profile_idx, err);

  80. continue;

  81. }

  82. if(QL_DATA_CALL_CONNECTED == data_call_info.v4.state) {

  83. printf("the profile index %d is already connected, don't up\n", data_call[loop].profile_idx);

  84. continue;

  85. }

  86. data_call[loop].ip_family = QL_DATA_CALL_TYPE_IPV4;

  87. data_call[loop].reconnect = true;

  88. err = QL_DATA_CALL_ERROR_NONE;

  89. if(QL_Data_Call_Start(&data_call[loop], &err)) {

  90. printf("the profile index %d start data call failure: 0x%x\n", data_call[loop].profile_idx, err);

  91.  
  92. }

  93. printf("the profile index %d start data call success\n", data_call[loop].profile_idx);

  94. usleep(500*1000);

  95. }

  96. sleep(3600);

  97. return 0;

  98. }

   然后soket传输图像

 
  1. #include

  2. #include

  3. #include

  4. #include

  5. #include

  6. #include

  7. #include

  8. #include

  9. #include

  10. #include

  11. #include

  12. #include

  13. #include

  14.  
  15. #define SERVER_PORT 3333

  16. #define MAXLINE 1024

  17.  
  18. int main(int argc,char **argv)

  19. {

  20. //new add

  21. /*int retry = 10;

  22. int loop;

  23. ql_data_call_s data_call[3];

  24. ql_data_call_info_s data_call_info;

  25. ql_data_call_error_e err = QL_DATA_CALL_ERROR_NONE;

  26.  
  27. memset(&data_call, 0, sizeof(data_call));*/

  28.  
  29. int sockfd;

  30. int read_len;

  31. FILE *from_file; //need send to server

  32. char buf[MAXLINE];

  33. struct sockaddr_in cliaddr;

  34.  
  35. bzero(&cliaddr, sizeof(cliaddr));

  36. cliaddr.sin_family = AF_INET;

  37. cliaddr.sin_port = htons(3333);

  38. cliaddr.sin_addr.s_addr = inet_addr("148.70.42.237");

  39.  
  40. sockfd=socket(AF_INET,SOCK_DGRAM,0);

  41. if(sockfd<0)

  42. {

  43. fprintf(stderr,"Socket Error:%s\n",strerror(errno));

  44. exit(1);

  45. }

  46.  
  47. if((from_file=open("timg.jpg",O_RDWR))==NULL)

  48. {

  49. printf("Can't open the file \n");

  50. exit(1);

  51. }

  52.  
  53. while ( (read_len = read(from_file, buf, MAXLINE)) > 0 )

  54. {

  55. sendto(sockfd, buf ,read_len, 0 , (struct sockaddr*)&cliaddr, sizeof(cliaddr));

  56. bzero(buf, MAXLINE);

  57. }

  58.  
  59. close(from_file);

  60. close(sockfd);

  61. }

 程序也是先运行拨号的再运行socket

你可能感兴趣的:(移远EC20二次开发之4G图像传输)