写点什么

STM32+ 果云 GA6-GPRSGSM 模块 +MQTT+HTTP 协议连接中移 OneNet 上传 GPS 数据定位

作者:DS小龙哥
  • 2022 年 8 月 06 日
  • 本文字数:9298 字

    阅读完需:约 31 分钟

OneNET 是由中国移动打造的 PaaS 物联网开放平台,平台能够帮助开发者轻松实现设备接入与设备连接,快速完成产品开发部署,为智能硬件、智能家居产品提供完善的物联网解决方案。


GA6 模块是 M2M 应用的理想解决方案,提供完善的 GSM/GPRS 短信,数据传输及语音服务,适用于车载、工业及 PDA、个人跟踪、电力环境检测、无线 POS、智能计量以及其它 M2M 的应用。


这篇文章介绍 OneNET 物联网平台的基本使用办法,演示产品、设备、应用的创建流程,最后通过 GA6 连接 OneNET 物联网平台,完成 GPS 数据上传。

一、环境介绍

MCU: STM32F103C8T6


GSM 模块: GA6--果云


开发软件: Keil5

二、GA6-GSM 模块介绍与调试

说明: GA6-B 模块供电必须 5V,采用电脑 USB 供电可能不稳定(没有 5V,只有 4.8V 左右),导致模块使用不稳定,发送 AT 指令没有反应,调试阶段,可将开发板的 USB 线连接充电宝或者手机充电插头取电。




2.1 GA6-B 模块概述

GA6-B 模组:


\1. GA6 尺寸 22.8mm x 16.8mm x 2.2 mm; \2. 正常工作温度:-30°C ~ +80°C, \3. 受限工作温度:-40°C ~ -30°C 及+80°C ~+85°C* \4. 工作电压 3.5V-4.2V; \5. 开机电压>3.5V; \6. SLEEP 模式下的耗流为 0.9mA; \7. 四频:GSM850, EGSM 900 和 DCS 1800,PCS1900 可以自动的搜寻 四个频段。 l 符合 GSM Phase 2 / 2+ l GPRS Class 10; \8. 灵敏度<-107; \9. 支持语音通话; \10. 支持 SMS 短信; \11. 支持移动和联通2G,以及全球的GSM网络 \12. GPRS 数据特性,最大数据速率,下载 85.6Kbps,上传 42.8Kbps; \13. 支持符合 GSM 07.10 协议的串口复用功能 \14. 支持 2 个串口,一个下载串口,一个 AT 命令口; \15. AT 命令支持标准 AT 和 TCP/IP 命令接口; \16. 支持数字音频和模拟音频,支持 HR,FR,EFR,AMR 语音编码; \17. 支持FCC,CE认证;\18. SMT 42PIN 封装;
复制代码


GA6 模块的优势 广域覆盖:GPRS 在全国 34 个省均有良好覆盖,更是全球通行的 2G 通讯标准。基本上在手机可以打电话的地方都可以通过 GPRS 无线上网; 永远在线:只要激活 GPRS 应用后,将一直保持在线,类似于无线专线网络服务。 按量计费:GPRS 服务虽然保持一直在线,但您不必担心费用问题;因为只有产生通信流量时才计费。 高速传输:目前 GPRS 可支持 85.6Kbps 的峰值传输速率,理论峰值传输可达 100 余 Kbps。 价格便宜 :相对于 SIM 系列的模块 价格只有其的一半。大大降低了物联网设备的入门门槛凭借超小的尺寸,超低功耗和宽工作温度范围,GA6 是 M2M 应用的理想解决方案,适用于车载、工业及 PDA、个人跟踪、电力环境检测、无线 POS、智能计量以及其它 M2M 的应用,为其提供完善的 GSM/GPRS 短信、数据传输及语音服务。










物联网卡:



2.2 GA6 模块调试

模块默认波特率: 115200 电压: 5V TX---URX(GA6 模块) RX---UTX(GA6 模块)






模块上电串口助手收到的消息:



注意: 电压必须 5V* 否则,给模块发送 AT***指令没有用**。


正常情况下,模块插上 SIM 电话卡,供电达到 5V 时,模块上电会返回以下提示信息。



当模块出现 “SMS Ready”字符串提示时,说明模块已经可以正常的接收“AT”指令了。

2.3 基础常用的指令介绍使用

(指令结尾发送都需要加\r\n)


\1. 检测模块是否正常


给模块发送指令: AT 模块正常返回,这个指令可以检测模块是否正常: OK


\2. 查询 SIM 卡是否在卡槽内


给模块发送指令: AT+CPIN? 如果卡在卡槽内,模块正常返回值: +CPIN:READY OK


\3. 查询模块是否注册到网络


给模块发送指令: AT+CREG? 如果模块已经正常注册到网络的返回值: AT+CREG? +CREG: 1,1 OK


\4. 关闭指令回显


给模块发送指令: ATE0 指令执行成功返回值: (关闭 AT 指令回显,方便调试,提高程序效率) OK

2.4 GPRS 网络通信相关指令介绍

\1. 查询网络连接状态


给模块发送指令: AT+CIPSTATUS 指令执行成功返回值如下(多种): "IP INITIAL" 初始化 "IP START" 启动任务 "IP CONFIG" 配置场景 "IP IND" 激活 GPRS/CSD 场景中 "IP GPRSACT" 接收场景配置 "IP STATUS" 获得本地 IP 地址(参考 AT+CIFSR 命令) "TCP CONNECTING" TCP 连接中 "UDP CONNECTING" UDP 连接中 "IP CLOSE" TCP/UDP 连接关闭 "CONNECT OK" TCP/UDP 连接成功 ,连接成功之后才可进行网络数据通信


\2. 附着 GPRS 网络 (进行网络通信前,需要先附着 GPRS 网络才可进行正常通信)


给模块发送指令: AT+CGATT=1 模块正常附着了 GPRS 网络,返回值: (注意该指令第一次附着网络需要点时间,需等待一段时间) OK


\3. 激活 GPRS 网络


给模块发送指令: AT+CGACT=1,1 模块正常激活了 GPRS 网络返回值: OK


\4. 建立 TCP 连接: 连接 TCP 服务器


模块发送指令: AT+CIPSTART="TCP","183.230.40.33",80 如果服务器正常连接成功的返回值: OK CONNECT OK


说明: 上面的指令是采用 TCP 协议连接,183.230.40.33 服务器,端口号是 80。


\5. 发送数据


给模块发送指令: AT+CIPSEND 如果收到指令后会返回 > 符号。,接下来就可以发送 实际要发送的数据,在发送实际数据时,不需要加回车符(\r\n)。 实际数据发送之后,紧接着发送一个 0x1A,即可启动数据发送。


注意: 0x1A 是十六进制格式数据,不是字符串。 如果数据发送成功,会返回 “SEND OK” 字符串。


发送数据示例:


POST /devices/517704007/datapoints HTTP/1.1 api-key:vvQAUiBG=HwKzqGicH=RxBvFCDw= Host:api.heclouds.com Connection:close Content-Length:65 {"datastreams":[{"id":"ds18b20","datapoints":[{"value":66.66}]}]}



三、STM32 代码调试 GA6 模块

3.1 通过 STM32 串口代码测试 GA6 模块

直接接在 STM32F103C8T6 最小系统板上面:



注意 : 如果是使用 USB 给开发板供电,为了防止电压不够,USB 线不要接分线器,直接接电脑的 USB 口。


因为 GA6 模块的电压必须 5V 才可驱动,4.8V 都不行。



STM32F103C8T6 最小系统板使用串口 3 与 GA6-B 模块连接:


5V-----5V GND---G PB10—URX PB11---UTX



出现以上提示之后,发送 AT 能返回 OK 就说明模块已经正常工作了。



模块上电会返回以下信息: (注意: 电压一定要保证是 5V)


AT Ready AST_POWERON +NITZ:19/03/20,01:57:46,32 Call Ready +CREG: 1 SMS Ready

3.2 通过 STM32 封装标准函数(使用 HTTP 协议连接 OneNet 服务器)

GA6_GPRS.c 文件代码:

 #include "ga6_gprs.h" #define GS6_GSM_CHECK_CNT 10 /* 函数功能:向GA6_GPRS发送指令 函数参数:         char *cmd     :发送的指令         char *check   :检查返回的字符串         u32 wait_time :等待的时间(100ms)为单位          说明:该函数只是适用于成功后返回OK的指令 返回值: 0表示成功 1表示失败 */ u8 GA6_GSM_SendCmd(char *cmd,char *check,u32 wait_time) {    u32 i,j;    for(i=0;i<GS6_GSM_CHECK_CNT;i++) //测试的总次数    {       USART3_RX_FLAG=0;       USART3_RX_CNT=0;       memset(USART3_RX_BUFF,0,sizeof(USART3_RX_BUFF));       USART_X_SendString(USART3,cmd);       for(j=0;j<wait_time;j++) //等待的时间(ms单位)       {           delay_ms(100); //一次的时间           if(USART3_RX_FLAG)           {               USART3_RX_BUFF[USART3_RX_CNT]='\0';               if(strstr((char*)USART3_RX_BUFF,check))               {                   return 0;               }               else break;           }       }    }    return 1; } /* 函数功能: 检查GA6的状态 返 回 值: 0表示成功,其他值表示失败 */ u8 GA6_GSM_StateCheck(void) {     /*1. 检查模块是否正常*/     if(GA6_GSM_SendCmd("AT\r\n","OK",50))     {         return 1; //模块不正常     }          /*2. 关闭回显功能*/     if(GA6_GSM_SendCmd("ATE0\r\n","OK",50))     {         return 2; //回显没有关闭成功     }          /*3. 查询卡是否插上*/     if(GA6_GSM_SendCmd("AT+CPIN?\r\n","READY",50))     {         return 3; //卡没有查上     }          /*4. 查询卡是否注册到网络*/     if(GA6_GSM_SendCmd("AT+CREG?\r\n","+CREG: 1,1",50))     {         return 4; //卡没有注册到网络     }     return 0; } /* 函数功能: 连接TCP服务器 函数参数:                      char *server_ip : 服务器地址                     u32 port :服务器端口 返 回 值: 0表示成功连接服务器,其他值表示服务器连接失败 */ u8 GA6_GSM_ConnectServer(char *server_ip,u32 port) {         char cmd_buffer[50];      /*1. 检查服务器连接状态*/      if(GA6_GSM_SendCmd("AT+CIPSTATUS\r\n","CONNECT",50))    {           /*2 附着GPRS网络*/             if(GA6_GSM_SendCmd("AT+CGATT=1\r\n","OK",50))return 1;                 /*3 激活GPRS网络*/             if(GA6_GSM_SendCmd("AT+CGACT=1,1\r\n","OK",50))return 2;                 /*4 连接指定的服务器*/           //组合命令             snprintf(cmd_buffer,sizeof(cmd_buffer),"AT+CIPSTART="TCP","%s",%d\r\n",server_ip,port);           //连接服务器      //服务器连接成功的情况下该指令会返回两种状态:  ALREAY CONNECT  ,CONNECT OK             if(GA6_GSM_SendCmd(cmd_buffer,"CONNECT",50))return 3;    }      return 0; } /* 函数功能: 向服务器发送数据 函数参数:                 u8 *data:发送的数据首地址                 u32 len :数据长度 */ u8 GA6_GSM_SendDataToServer(u8 *data,u32 len) {         char end_char[2];         end_char[0] = 0x1A;//结束字符         end_char[1] = '\0';         /*2.1 启动数据发送*/         if(GA6_GSM_SendCmd("AT+CIPSEND\r\n",">",50))return 1;         /*2.2 发送实际要发送的数据*/         USART_X_SendData(USART3,data,len);         /*2.3 结束数据发送*/       if(GA6_GSM_SendCmd(end_char,"SEND OK",100))return 2;                return 0; }
复制代码

GA6_GPRS.h 文件代码:

 #ifndef GA6_GPRS #define GA6_GPRS #include "stm32f10x.h" #include "usart.h" #include "delay.h" u8 GA6_GSM_StateCheck(void); u8 GA6_GSM_SendDataToServer(u8 *data,u32 len); u8 GA6_GSM_ConnectServer(char *server_ip,u32 port); u8 GA6_GSM_SendCmd(char *cmd,char *check,u32 wait_time); #endif
复制代码

Main.c 代码

 #include "stm32f10x.h" #include <string.h> #include <stdio.h> #include "ga6_gprs.h" #include "usart.h" #include "timer.h" #include "led.h" #include "key.h" //u8 onenet_http_cmd[]= //{ //  "POST /devices/517704007/datapoints HTTP/1.1\r\n"\ //  "api-key:vvQAUiBG=HwKzqGicH=RxBvFCDw=\r\n"\ //  "Host:api.heclouds.com\r\n"\ //  "Connection:close\r\n"\ //  "Content-Length:65\r\n"\ //  "\r\n"\ //  "{"datastreams":[{"id":"ds18b20","datapoints":[{"value":88.88}]}]}" //}; u8 onenet_http_cmd[]= {     "POST /devices/517620924/datapoints HTTP/1.1\r\n"\     "api-key:OCZ6ghYPdky3=FJQCOEVZbByHRM=\r\n"\     "Host:api.heclouds.com\r\n"\     "Connection:close\r\n"\     "Content-Length:62\r\n"\     "\r\n"\     "{"datastreams":[{"id":"temp","datapoints":[{"value":88.88}]}]}" }; //应用发布地址: https://open.iot.10086.cn/iotbox/appsquare/appview?openid=905ef1b56ba526fdeee0c69a0787f176 /* 以下程序正确运行返回的数据: +NITZ:19/03/20,14:45:27,32 Call Ready +CREG: 1 SMS Ready 发送一次数据! GA6_GSM_StateCheck=0 GA6_GSM_ConnectServer=0 GA6_GSM_SendDataToServer=0 SEND OK HTTP/1.1 200 OK Date: Wed, 20 Mar 2019 14:45:40 GMT Content-Type: application/json Content-Length: 26 Connection: close Server: Apache-Coyote/1.1 Pragma: no-cache {"errno":0,"error":"succ"} CLOSED */ int main() {      u8 key,state;   LED_Init();   KEY_Init();   BEEP_Init();   TIM1_Init(72,20000); //辅助串口1接收,超时时间为20ms   USART_X_Init(USART1,72,115200);   TIM2_Init(72,20000);//辅助串口2接收,超时时间为20ms   USART_X_Init(USART2,36,9600);   TIM3_Init(72,20000);//辅助串口3接收,超时时间为20ms   USART_X_Init(USART3,36,115200);   printf("UART1 OK.....\n");      while(1)   {           if(USART3_RX_FLAG)      {          USART3_RX_BUFF[USART3_RX_CNT]='\0';          //printf("buff=%s,cnt=%d\n\n",USART3_RX_BUFF,USART3_RX_CNT);          printf("%s",USART3_RX_BUFF);          USART3_RX_CNT=0;          USART3_RX_FLAG=0;          memset(USART3_RX_BUFF,0,sizeof(USART3_RX_BUFF));      }            key=KEY_Scanf();      if(key)      {           LED0=!LED0;           LED1=!LED1;           printf("发送一次数据!\n");           /*1. 检查GSM工作状态*/           state=GA6_GSM_StateCheck();           printf("GA6_GSM_StateCheck=%d\n",state);           if(!state)           {             /*2. 连接服务器*/             state=GA6_GSM_ConnectServer("183.230.40.33",80);             printf("GA6_GSM_ConnectServer=%d\n",state);             if(!state)             {                 /*3. 向服务器发送数据*/                 state=GA6_GSM_SendDataToServer(onenet_http_cmd,strlen((char*)onenet_http_cmd));                 printf("GA6_GSM_SendDataToServer=%d\n",state);             }             else             {                 //手动断开服务器连接                 printf("断开服务器连接:%d\r\n",GA6_GSM_SendCmd("AT+CIPCLOSE\r\n","OK",5000));             }          }      }   } }
复制代码

3.3 GA6-B 模块使用 HTTP 协议连接 OneNet 服务器上传 GPS 经纬度

为了提高效率,通过 GPS 配置软件,可以将 GPS 模块配置成功以下选项:



主要修改的地方:


  1. GPS 模块默认波特率为 9600,配置成 115200

  2. 输出的语句,只是输出 RMC(推荐定位信息),因为现在只需要经纬度信息即可。

  3. 系统设置热启动状态,提高定位速度


经纬度格式分为三种: 度: ( ddd.ddddd °) 十进制小数部分(5 位) 度 .分:(ddd °mm.mmm’)十进制小数部分(3 位)度 . 分 . 秒 :(ddd°mm’ss’’) 关系: 一度(°)等于 60 分钟(’)等于 3600 秒(“): 整度(d)等于十进制的度的整数部分(dd): 分钟(m)等于十进制的度的整数部分(dd)减去整数度(d)的 60 倍: 秒(s)等于十进制的度(dd)减去整数度(d)减分(M)除以 60 乘以 3600:

GPS.c 文件代码示例:

 #include "gps.h" /* 函数功能:从buf里面得到第cnt个逗号所在的位置 返 回 值:0~254,代表逗号所在位置的偏移. 255,代表不存在第cnt个逗号 */ u8 GPS_GetCommaOffset(char *buf,u8 cnt) {     char *p=buf;     while(cnt)     {         if(*buf=='*'||*buf<' '||*buf>'z')return 255;//遇到'*'或者非法字符,则不存在第cx个逗号         if(*buf==',')cnt--;         buf++;     }     return buf-p; //计算偏移量 } /* 函数功能: 获取GPS经纬度数据值 函数参数:         double *Longitude  :经度         double *latitude   :纬度 返回值: 0表示定位成功,1表示定位失败 说明: 解析$GNRMC命令,得到经纬度 $GNRMC,023705.000,A,2842.4164,N,11549.5713,E,1.73,91.65,150319,,,A*41 转换公式示例: 经度: dddmm.mmmm 东经 11408.4790 114+(08.4790/60)=114.141317 纬度: ddmm.mmmm 北纬 2236.9453 22+(36.9453/60)= 22.615755 */ u8 GPS_GNRMC_Decoding(char *gps_buffer,double *Longitude,double *latitude) {     u8 Offset;     u32 int_data;     double s_Longitude,s_latitude;     char *p;     /*1. 确定下定位是否成功*/     p=strstr(gps_buffer,"$GNRMC");     if(!p)return 1;          Offset=GPS_GetCommaOffset(p,2);     if(Offset==255)return 2;     if(*(p+Offset)!='A')return 3; //定位不准确          /*2. 得到纬度*/     Offset=GPS_GetCommaOffset(p,3);     if(Offset==255)return 4;     sscanf(p+Offset,"%lf",&s_latitude);    // printf("转换前的纬度:%lf\r\n",s_latitude);        s_latitude=s_latitude/100;     int_data=s_latitude;//得到纬度整数部分     s_latitude=s_latitude-int_data;//得到纬度小数部分     s_latitude=(s_latitude)*100;     *latitude=int_data+(s_latitude/60.0); //得到转换后的值    // printf("转换后的纬度: %lf\r\n",*latitude);       /*3. 得到经度*/     Offset=GPS_GetCommaOffset(p,5);     if(Offset==255)return 5;     sscanf(p+Offset,"%lf",&s_Longitude);    // printf("转换前的经度:%lf\r\n",s_Longitude);          s_Longitude=s_Longitude/100;     int_data=s_Longitude;//得到经度整数部分     s_Longitude=s_Longitude-int_data; //得到经度小数部分     s_Longitude=s_Longitude*100;     *Longitude=int_data+(s_Longitude/60.0);    // printf("转换后的经度:%lf\r\n",*Longitude);          return 0; }
复制代码

GPS.h 代码示例

 #ifndef GPS_H #define GPS_H #include "stm32f10x.h" #include <string.h> #include "usart.h" u8 GPS_GNRMC_Decoding(char *gps_buffer,double *Longitude,double *latitude); #endif
复制代码

Main.c 代码示例

 #include "stm32f10x.h" #include <string.h> #include <stdio.h> #include "ga6_gprs.h" #include "usart.h" #include "timer.h" #include "led.h" #include "key.h" #include "gps.h" char onenet_http_cmd[1024]; //应用发布地址: https://open.iot.10086.cn/iotbox/appsquare/appview?openid=fd1307a02210acbef4b34de89d6cfe21 /* GPS 接线方式: 将 GPS 模块的 TX 脚与 PA3 相连接。 (串口 2 的接收脚) GPS 模块波特率默认为 9600  (为了提高速度,可以将GPS的波特率设置成115200---可直接通过上位机软件设置) GPS 模块型号: ATGM336H-5N 电 源: 3V */ /* GA6-GSM 接线方式: 将 GA6-GSM  模块的 UTX 脚与 PB11 相连接,URX 脚与 PB10 相连接。 (串口 3 的接收脚) GA6-GSM  模块波特率默认为 115200 GA6-GSM  模块型号: 果云GA6-B 电 源: 5V */ int main() {      double Longitude,latitude;   u8 state;   u32 time_cnt=0;   u16 data_tx_len=0;   char temp_buff[50];      LED_Init();   KEY_Init();   BEEP_Init();   TIM1_Init(72,20000); //辅助串口1接收,超时时间为20ms     USART_X_Init(USART1,72,115200);   TIM2_Init(72,20000);//辅助串口2接收,超时时间为20ms   USART_X_Init(USART2,36,115200);   //接GPS模块   TIM3_Init(72,20000);//辅助串口3接收,超时时间为20ms   USART_X_Init(USART3,36,115200); //接GSM模块   printf("UART1 OK.....\n");      while(1)   {            //接收GPRS模块的返回值      if(USART3_RX_FLAG)      {          USART3_RX_BUFF[USART3_RX_CNT]='\0';          //printf("buff=%s,cnt=%d\n\n",USART3_RX_BUFF,USART3_RX_CNT);          printf("%s",USART3_RX_BUFF);          USART3_RX_CNT=0;          USART3_RX_FLAG=0;          memset(USART3_RX_BUFF,0,sizeof(USART3_RX_BUFF));      }            //接收GPS模块的返回值      if(USART2_RX_FLAG)      {          USART2_RX_BUFF[USART2_RX_CNT]='\0';          //printf("USART2_RX_BUFF=%s",USART2_RX_BUFF);                  //解析GPS数据,得到经纬度          if(GPS_GNRMC_Decoding((char*)USART2_RX_BUFF,&Longitude,&latitude))          {             printf("GPS定位失败! 请到空旷地方定位\r\n");          }          else //定位成功          {              if(time_cnt>=8000) //8秒一次              {                 data_tx_len=71;                 sprintf(temp_buff,"%lf",Longitude);                 data_tx_len+=strlen(temp_buff);                                 sprintf(temp_buff,"%lf",latitude);                 data_tx_len+=strlen(temp_buff); //得到发送的数据长度                                 snprintf(onenet_http_cmd,sizeof(onenet_http_cmd),                   "POST /devices/517704007/datapoints HTTP/1.1\r\n"\                   "api-key:vvQAUiBG=HwKzqGicH=RxBvFCDw=\r\n"\                   "Host:api.heclouds.com\r\n"\                   "Connection:close\r\n"\                   "Content-Length:%d\r\n"\                   "\r\n"\                   "{"datastreams":[{"id":"gps","datapoints":[{"value":{"lon":%lf,"lat":%lf}}]}]}",                    data_tx_len,Longitude,latitude                   );                 printf("data_tx_len=%d\r\n",data_tx_len);                 printf("经度:%lf,纬度:%lf\r\n",Longitude,latitude);                   time_cnt=0;                 LED0=!LED0;                 LED1=!LED1;                 /*1. 检查GSM工作状态*/                 state=GA6_GSM_StateCheck();                 printf("GA6_GSM_StateCheck=%d\n",state);                 if(!state)                 {                     /*2. 连接服务器*/                     state=GA6_GSM_ConnectServer("183.230.40.33",80);                               printf("GA6_GSM_ConnectServer=%d\n",state);                     if(!state)                     {                       /*3. 向服务器发送数据*/                     state=GA6_GSM_SendDataToServer((u8*)onenet_http_cmd,strlen((char*)onenet_http_cmd));                       printf("GA6_GSM_SendDataToServer=%d\n",state);                     }                     else                     {                         //手动断开服务器连接                      printf("断开服务器连接:%d\r\n",GA6_GSM_SendCmd("AT+CIPCLOSE\r\n","OK",5000));                     }                 }              }          }          USART2_RX_CNT=0;          USART2_RX_FLAG=0;          memset(USART2_RX_BUFF,0,sizeof(USART2_RX_BUFF));      }           time_cnt++;     delay_ms(1);   } }
复制代码


网页上显示的效果:




发布于: 2022 年 08 月 06 日阅读数: 2
用户头像

DS小龙哥

关注

之所以觉得累,是因为说的比做的多。 2022.01.06 加入

熟悉C/C++、51单片机、STM32、Linux应用开发、Linux驱动开发、音视频开发、QT开发. 目前已经完成的项目涉及音视频、物联网、智能家居、工业控制领域

评论

发布
暂无评论
STM32+果云GA6-GPRSGSM模块+MQTT+HTTP协议连接中移OneNet上传GPS数据定位_8月月更_DS小龙哥_InfoQ写作社区