使用AT指令请求JSON接口返回200,Arduino端获取响应不完整
Arduino UNO + SIM800L 获取完整JSON响应解决方案
问题背景
使用Arduino UNO搭配SIM800L模块向HTTPS接口发起GET请求,接口返回状态码200,但Arduino终端仅能获取部分JSON响应,Postman测试可完整返回响应。
原代码
#include <SoftwareSerial.h> #define RX_PIN 2 #define TX_PIN 3 SoftwareSerial gsmSerial(RX_PIN, TX_PIN); void setup() { Serial.begin(9600); gsmSerial.begin(9600); configureAPN(); Serial.println("Start Actual Communication:---->"); // Additional setup code for your SIM800L module, if required // Ensure that the SIM800L module is configured and connected to the network } void loop() { // Make HTTP GET request to the specified API endpoint another_function("https://just_normal_server.com/user/heartbeat"); // Adjust the delay based on your application requirements delay(2000); } void another_function(String url) { // Buffer to store the HTTP response data char buffer[512]; int index = 0; // Helper function to read and append data to the buffer auto readAndAppendToBuffer = [&buffer, &index](int timeout) { long startTime = millis(); while (millis() - startTime < timeout && gsmSerial.available()) { char c = gsmSerial.read(); buffer[index++] = c; // Add additional conditions for handling specific characters or patterns if needed } }; gsmSerial.println("AT+HTTPINIT"); delay(1000); Serial.println("HTTP INITIALIZATION: " + get_data()); gsmSerial.println("AT+HTTPPARA=\"CID\",1"); delay(1000); Serial.println("CID PARA: " + get_data()); gsmSerial.println("AT+HTTPPARA=\"URL\",\"" + url + "\""); delay(2000); Serial.println("URL Called: " + get_data()); gsmSerial.println("\"CONTENT\",\"application/json\""); delay(2000); Serial.println("JSON PARA: " + get_data()); gsmSerial.println("AT+HTTPPARA=\"REDIR\",1"); delay(1000); Serial.println("REDIR PARA: " + get_data()); gsmSerial.println("AT+HTTPSSL=1"); delay(10000); Serial.println("SSL PARA: " + get_data()); gsmSerial.println("AT+HTTPACTION=0"); delay(10000); Serial.println("HTTP ACTION: " + get_data()); gsmSerial.println("AT+HTTPREAD"); delay(10000); Serial.println("HTTP Read DATA: " + get_data()); /* readAndAppendToBuffer(30000); // Adjust the timeout based on your server's response time // Null-terminate the buffer buffer[index] = '\0'; // Print the entire response data Serial.println(buffer); */ gsmSerial.println("AT+HTTPTERM"); delay(1000); Serial.println("HTTP Termination: " + get_data()); } String get_data() { String response = ""; // Initialize an empty string while (gsmSerial.available() > 0) { char character = gsmSerial.read(); response += character; // Append the character to the string } return response; } void configureAPN() { gsmSerial.println("AT+SAPBR=3,1,\"CONTYPE\",\"GPRS\"\r"); delay(1000); Serial.println("APN-1: " + get_data()); gsmSerial.println("AT+SAPBR=3,1,\"APN\",\"airtelgprs.com\"\r"); delay(1000); Serial.println("APN-2: " + get_data()); gsmSerial.println("AT+SAPBR=1,1\r"); delay(1000); Serial.println("APN-3: " + get_data()); }
实际获取的响应
HTTP ACTION: AT+HTTPACTION=0 OK +HTTPACTION: 0,200,57 HTTP Read DATA: AT+HTTPREAD +HTTPREAD: 57 {"status":"alive","timestamp":"202 HTTP Termination: AT+HTTPTERM OK
解决方案
1. 修复get_data()的读取逻辑
当前get_data()仅读取调用瞬间串口缓冲区的可用数据,SIM800L的响应是分批次发送的,需要添加超时等待,确保读取完所有响应内容。修改后的函数如下:
String get_data() { String response = ""; long timeout = millis() + 1000; // 1秒超时,可根据网络情况调整 while (millis() < timeout) { while (gsmSerial.available() > 0) { char character = gsmSerial.read(); response += character; timeout = millis() + 1000; // 每次收到数据就重置超时 } } return response; }
2. 修正无效的AT指令
原代码中gsmSerial.println("\"CONTENT\",\"application/json\"");是错误的,缺少AT+HTTPPARA前缀,属于无效指令,会导致模块无法正确识别请求格式。应修改为:
gsmSerial.println("AT+HTTPPARA=\"CONTENT\",\"application/json\"");
3. 优化AT+HTTPREAD后的读取流程
去掉固定的delay(10000),依赖修改后的get_data()超时读取,确保完整获取响应。也可以取消注释原代码中readAndAppendToBuffer相关逻辑,直接用缓冲区存储响应,但需注意避免缓冲区溢出。
4. 调整超时参数
根据网络状况调整AT+HTTPSSL=1、AT+HTTPACTION=0后的延迟时间,确保模块完成SSL握手和请求发送。如果网络较慢,可适当延长延迟,比如将delay(10000)调整为delay(15000)。
验证修改效果
修改后重新上传代码,终端应能完整输出JSON响应,示例如下:
HTTP Read DATA: AT+HTTPREAD +HTTPREAD: 57 {"status":"alive","timestamp":"2024-05-20T12:34:56Z"} OK
内容的提问来源于stack exchange,提问作者Dheeraj SmartIam
相关产品推荐
相关产品推荐

