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

简介: STM32+果云GA6-GPRS/GSM模块+MQTT+HTTP协议连接中移OneNet上传GPS数据定位

一、环境介绍

MCU:  STM32F103C8T6


GSM模块: GA6--果云


开发软件: Keil5


完整源码下载:  https://download.csdn.net/download/xiaolong1126626497/18245590


其他参考文章: STM32+ESP8266使用MQTT协议连接阿里云物联网服务器


其他参考文章:STM32+ESP8266使用标准MQTT协议(MQTTS)连接中国移动OneNet物联网服务器


二、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短信、数据传输及语音服务。

image.png

image.png

image.png

image.png

image.png

物联网卡:

image.png

image.png

2.2 GA6模块调试

模块默认波特率:  115200

电压:  5V

TX---URX(GA6模块)

RX---UTX(GA6模块)

image.png

image.png

image.png

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

image.png

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

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

image.png

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

 

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

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

1. 检测模块是否正常

image.png

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

image.png

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

image.png

4. 关闭指令回显

image.png

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

1. 查询网络连接状态

image.png

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

image.png

3. 激活GPRS网络

image.png

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

image.png

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

 

5. 发送数据

image.png

发送数据示例:

image.png

image.png

image.png

三、STM32代码调试GA6模块

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

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

image.png

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

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

image.png

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

image.png

image.png

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

image.png

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

image.png

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模块配置成功以下选项:

image.png

主要修改的地方:

  1. GPS模块默认波特率为9600,配置成115200
  2. 输出的语句,只是输出RMC(推荐定位信息),因为现在只需要经纬度信息即可。
  3. 系统设置热启动状态,提高定位速度

image.png

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);
  }
}
  1. 网页上显示的效果:

image.png

image.png

image.png

相关实践学习
消息队列RocketMQ版:基础消息收发功能体验
本实验场景介绍消息队列RocketMQ版的基础消息收发功能,涵盖实例创建、Topic、Group资源创建以及消息收发体验等基础功能模块。
消息队列 MNS 入门课程
1、消息队列MNS简介 本节课介绍消息队列的MNS的基础概念 2、消息队列MNS特性 本节课介绍消息队列的MNS的主要特性 3、MNS的最佳实践及场景应用 本节课介绍消息队列的MNS的最佳实践及场景应用案例 4、手把手系列:消息队列MNS实操讲 本节课介绍消息队列的MNS的实际操作演示 5、动手实验:基于MNS,0基础轻松构建 Web Client 本节课带您一起基于MNS,0基础轻松构建 Web Client
目录
相关文章
|
3月前
|
监控 安全 搜索推荐
设置 HTTPS 协议以确保数据传输的安全性
设置 HTTPS 协议以确保数据传输的安全性
|
2月前
|
传感器 数据采集 移动开发
基于STM32的智能手环wifi连接手机APP(下)
基于STM32的智能手环wifi连接手机APP(下)
111 0
|
3月前
|
数据采集
Haskell爬虫:连接管理与HTTP请求性能
Haskell爬虫:连接管理与HTTP请求性能
|
26天前
|
安全 搜索推荐 网络安全
HTTPS协议是**一种通过计算机网络进行安全通信的传输协议
HTTPS协议是**一种通过计算机网络进行安全通信的传输协议
53 11
|
26天前
|
缓存 安全 网络协议
HTTPS协议的历史发展
HTTPS协议的历史发展
36 8
|
27天前
|
安全 应用服务中间件 Linux
判断一个网站是否使用HTTPS协议
判断一个网站是否使用HTTPS协议
41 4
|
1月前
|
消息中间件 测试技术
通过轻量消息队列(原MNS)主题HTTP订阅+ARMS实现自定义数据多渠道告警
轻量消息队列(原MNS)以其简单队列模型、轻量化协议及按量后付费模式,成为阿里云产品间消息传输首选。本文通过创建主题、订阅、配置告警集成等步骤,展示了该产品在实际应用中的部分功能,确保消息的可靠传输。
44 2
|
2月前
|
安全 网络协议 算法
HTTPS网络通信协议揭秘:WEB网站安全的关键技术
HTTPS网络通信协议揭秘:WEB网站安全的关键技术
229 4
HTTPS网络通信协议揭秘:WEB网站安全的关键技术
|
2月前
|
网络协议 物联网 网络性能优化
物联网协议比较 MQTT CoAP RESTful/HTTP XMPP
【10月更文挑战第18天】本文介绍了物联网领域中四种主要的通信协议:MQTT、CoAP、RESTful/HTTP和XMPP,分别从其特点、应用场景及优缺点进行了详细对比,并提供了简单的示例代码。适合开发者根据具体需求选择合适的协议。
67 5
|
2月前
|
存储 网络安全 对象存储
缺乏中间证书导致通过HTTPS协议访问OSS异常
【10月更文挑战第4天】缺乏中间证书导致通过HTTPS协议访问OSS异常
134 4