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

移远EC20二次开发之4G图像传输我们公司和移远有合作所以得到了他们 EC20 的二次开发的开发板 下面是我开发 4G 图像传输的总结 工作方式有两种 一种 AT 一种 socket 下面先是 AT 命令一 在 linux 下解压文件解压如下文件二 安装 SDK 每次开新的终端进行编译都要进行环境变量的设置

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

     下面先是AT命令

      一.在linux下解压文件

              解压如下文件

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

      二.安装SDK

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

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

      三.进入历程

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

      四.修改历程

           

#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系统

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

   六.上传文件

        使用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

(0)
上一篇 2026年3月17日 下午6:41
下一篇 2026年3月17日 下午6:41


相关推荐

  • 3706 teradata 语句报错_Teradata SQL

    3706 teradata 语句报错_Teradata SQL刚用 SQL 语句查询的时候发现了一个问题 CREATESETTAB AUTO ETL Received File NOFALLBACK NOBEFOREJOUR NOAFTERJOURN CHECKSUM DEFAULT ETL SystemCHAR 3 CHARACTERSET ETLSys

    2026年3月18日
    3
  • CouchBase_couchbase数据库

    CouchBase_couchbase数据库1.CouchBase是什么简单来说CouchBase是一款开源的,分布式的nosql数据库,主要用于分布式缓存和数据存储领域。能够通过managecache提供快速的亚毫米级别的k-v存储操作,

    2022年8月2日
    10
  • Anaconda 和 Pycharm

    Anaconda 和 Pycharm一句话总结 Anaconda 管理和维护 Python 标准库和第三方库中的各种包及它们的依赖环境的软件 Pycharm 可以调用 Anaconda 当做解释器 Pycharm 是由 JetBrains 打造的一款 PythonIDE 即集成开发环境 在 Anaconda 中安装 jieba wordcloud 等第三方库 可以尝试用 condainstall cconda forgejieba 命令 这个命令的语法是 condainstall cchannel namepackage name 其

    2026年3月17日
    2
  • 如何用AI算法识别骗保行为?蚂蚁保险智能风控模型首次公开![通俗易懂]

    如何用AI算法识别骗保行为?蚂蚁保险智能风控模型首次公开![通俗易懂]阿里妹导读:人生充满意外和不确定性,保险的使命,就是给人以安全感。风控是保险业务正常发展的重要环节,成长于互联网环境下的保险风控更为重要。今天,阿里工程师正在利用跨平台体系下的海量数据资源和智能风控模型,优化保险风控,提升保险业务整体风控能力,让保险更好帮助人们对抗风险,减少后顾之忧。保险风控的背景以及挑战商业保险是一种用于保障未来的商业行为。除了我们常见的车险、财产险、健康险等传统保险以外,运费

    2022年5月11日
    50
  • javaint转化为string_java jsonobject转string

    javaint转化为string_java jsonobject转string1、String转化为JsonObject格式的数据。主要代码如下:JsonReaderjsonReader=Json.createReader(newStringReader(str));JsonObjectz =jsonReader.readObject();  //或者 this.jobj=jsonReader.readObject();  例如:有一

    2022年8月23日
    8
  • iscsiadm命令详解_adm激活成功教程版

    iscsiadm命令详解_adm激活成功教程版iscsiadm是open-iscsi包中的一个工具,用来发现和登陆iSCSItar

    2022年8月23日
    9

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号