You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ESP32+SIM800L调用OpenWeatherMap API遇HTTP 603错误求助

ESP32+SIM800L调用OpenWeatherMap API出现HTTP 603错误的解决方法

问题背景

已拥有可用的OpenWeatherMap API密钥,在Python环境中可正常获取城市温度数据,但使用ESP32搭配SIM800L模块发起GET请求时,出现HTTP 603错误,无法获取数据,目标是实现HTTP 200响应并解析温度数据。

错误原因分析

HTTP 603在SIM800L模块中通常表示HTTP请求参数格式错误或GPRS连接未正确建立,结合代码来看主要存在以下问题:

  • 重复传递API密钥:OpenWeatherMap API仅需通过URL的appid参数传递密钥,代码中额外通过USERDATA添加Authorization: Bearer头属于冗余操作,会导致请求格式异常。
  • GPRS连接验证缺失:setup中仅执行AT+SAPBR=1,1后延迟1秒,未确认连接是否成功获取IP地址。
  • AT命令响应处理不严谨:sendATCommand函数未检查命令执行结果(如是否返回OK),可能导致后续命令在前置命令失败的情况下继续执行。
  • HTTP请求等待逻辑不合理:固定延迟15秒无法适配网络波动,且可能错过响应时机。
  • HTTP连接未正确关闭:AT+HTTPTERM放在return语句之后,永远不会执行,导致模块HTTP资源占用。

修复步骤

  1. 移除冗余的Bearer认证:删除通过AT+HTTPPARA="USERDATA"传递API密钥的代码。
  2. 验证GPRS连接状态:在setup中添加AT+SAPBR=2,1命令,确认模块已获取IP地址,确保GPRS连接正常。
  3. 优化AT命令执行逻辑:修改sendATCommand函数,等待并检查响应是否包含OK,确保命令执行成功后再继续。
  4. 替换固定延迟为响应等待:执行AT+HTTPACTION=0后,等待模块返回+HTTPACTION:响应,确认请求完成。
  5. 调整HTTPTERM位置:将AT+HTTPTERM移至函数末尾,确保每次请求后都关闭HTTP连接。
  6. 确认APN正确性:根据SIM卡运营商替换APN,如移动用cmnet、联通用3gnet、电信用ctnet,避免因APN错误导致网络不通。

修正后的完整代码

#include <Arduino.h>
#include <SoftwareSerial.h>
#define SIM800L_IP5306_VERSION_20200811
#include "utilities.h"
#include <ArduinoJson.h>

SoftwareSerial sim800lSerial(26, 27);  // RX, TX

const char* apiKey = "bbb1506b80137280e7cbdc2c3c72e628";
const char* city = "adana";
const char* apn = "internet"; // 根据运营商修改,如cmnet/3gnet/ctnet

void setupModem()
{
#ifdef MODEM_RST
    pinMode(MODEM_RST, OUTPUT);
    digitalWrite(MODEM_RST, HIGH);
#endif

    pinMode(MODEM_PWRKEY, OUTPUT);
    pinMode(MODEM_POWER_ON, OUTPUT);

    digitalWrite(MODEM_POWER_ON, HIGH);
    digitalWrite(MODEM_PWRKEY, HIGH);
    delay(100);
    digitalWrite(MODEM_PWRKEY, LOW);
    delay(1000);
    digitalWrite(MODEM_PWRKEY, HIGH);

    pinMode(LED_GPIO, OUTPUT);
    digitalWrite(LED_GPIO, LED_OFF);
}

// 发送AT命令并等待OK响应
bool sendATCommand(String command, int timeout = 2000) {
  sim800lSerial.println(command);
  unsigned long start = millis();
  String response = "";
  while (millis() - start < timeout) {
    while (sim800lSerial.available()) {
      char c = sim800lSerial.read();
      response += c;
      Serial.write(c);
    }
    if (response.indexOf("OK") != -1) {
      return true;
    }
    if (response.indexOf("ERROR") != -1) {
      return false;
    }
  }
  return false;
}

String readResponse(int timeout = 5000) {
  String response = "";
  unsigned long start = millis();
  while (millis() - start < timeout) {
    while (sim800lSerial.available()) {
      char c = sim800lSerial.read();
      response += c;
    }
  }
  return response;
}

void setup() {
  Serial.begin(115200);
  sim800lSerial.begin(115200);
  setupModem();
  delay(10000);

  // 初始化SIM800L并验证连接
  if (!sendATCommand("AT")) {
    Serial.println("模块未响应");
    while(1);
  }

  sendATCommand("AT+SAPBR=3,1,\"Contype\",\"GPRS\"");
  sendATCommand("AT+SAPBR=3,1,\"APN\",\"" + String(apn) + "\"");
  if (!sendATCommand("AT+SAPBR=1,1", 5000)) {
    Serial.println("GPRS连接失败");
    while(1);
  }

  // 检查是否获取到IP
  sendATCommand("AT+SAPBR=2,1");
}

float getTemperature(const char* city) {
  // 初始化HTTP
  if (!sendATCommand("AT+HTTPINIT")) {
    Serial.println("HTTP初始化失败");
    return -999;
  }

  sendATCommand("AT+HTTPPARA=\"CID\",1");
  
  String url = "http://api.openweathermap.org/data/2.5/weather?q=";
  url += city;
  url += "&appid=";
  url += apiKey;

  if (!sendATCommand("AT+HTTPPARA=\"URL\",\"" + url + "\"")) {
    sendATCommand("AT+HTTPTERM");
    return -999;
  }

  // 发起GET请求
  sim800lSerial.println("AT+HTTPACTION=0");
  unsigned long start = millis();
  String actionResp = "";
  bool requestDone = false;
  int httpCode = -1;

  // 等待+HTTPACTION响应
  while (millis() - start < 15000) {
    while (sim800lSerial.available()) {
      char c = sim800lSerial.read();
      actionResp += c;
      Serial.write(c);
      
      if (actionResp.indexOf("+HTTPACTION:") != -1) {
        // 解析HTTP状态码
        int codePos = actionResp.indexOf(",") + 1;
        httpCode = actionResp.substring(codePos, codePos+3).toInt();
        requestDone = true;
        break;
      }
    }
    if (requestDone) break;
  }

  if (httpCode != 200) {
    Serial.print("HTTP请求失败,状态码:");
    Serial.println(httpCode);
    sendATCommand("AT+HTTPTERM");
    return -999;
  }

  // 读取响应内容
  sendATCommand("AT+HTTPREAD");
  String response = readResponse();

  if (response == "") {
    Serial.println("未读取到响应内容");
    sendATCommand("AT+HTTPTERM");
    return -999;
  }

  // 解析JSON
  DynamicJsonDocument doc(2048);
  DeserializationError error = deserializeJson(doc, response);

  if (!error) {
    float temperature = doc["main"]["temp"];
    temperature -= 273.15;
    sendATCommand("AT+HTTPTERM");
    return temperature;
  } else {
    Serial.println("JSON解析失败");
    sendATCommand("AT+HTTPTERM");
    return -999;
  }
}

void loop() {
  float temperature = getTemperature(city);

  if (temperature != -999) {
    Serial.print(city);
    Serial.print(" 当前温度:");
    Serial.print(temperature);
    Serial.println(" °C");
  } else {
    Serial.println("获取温度失败");
  }

  delay(600000); // 10分钟
}

额外注意事项

  • 确保SIM卡已开通GPRS服务,且信号正常(可通过AT+CSQ命令查看信号强度,返回值>=10表示信号良好)。
  • 如果仍有问题,可通过AT+HTTPDEBUG=1开启HTTP调试模式,查看详细的请求和响应内容,进一步定位问题。

内容的提问来源于stack exchange,提问作者enis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 21:14:53