adafruit / Adafruit_FONA

Arduino library for the Adafruit FONA
https://www.adafruit.com/products/1946
211 stars 237 forks source link

SIM7070 fails when adding body to HTTP POST #131

Closed KnightOfNih closed 3 years ago

KnightOfNih commented 3 years ago

Version: 1.55.0 Commit: c185983a683d14c396952dd432459097bc7f757f Date: 2021-03-30T16:01:05.981Z (1 wk ago) Electron: 11.3.0 Chrome: 87.0.4280.141 Node.js: 12.18.3 V8: 8.7.220.31-electron.0 OS: Darwin x64 18.7.0

Hello Gents,

First off, I'd like to give a very greatful thank you to the library writers for doing this. There's no way I would have gotten as far as I would have without this very helpful repo. Thank you.

Using the example sketches provided with the library to do an HTTP POST. A POST operation works (needed to add some delay commands for SIM7070) but when I add a body to the POST, the POST fails.

In particular, here are the commands to add the body post.

void addBodyToPost()
{
  // Sending plan text and wait one second, b/c I've seen that in other tutorials
  fona.HTTP_addHeader("Content-Type", "text/plain", 10);
  delay(1000);

  fona.HTTP_addHeader("Host", "b225f0b114f9.ngrok.io", 21);
  delay(1000);

  fona.HTTP_addHeader("User-Agent", "IOE Client", 10);
  delay(1000);

  // Add the SHBOD.  It will return a ">" when it is ready for data
  char cmdBuff[150];
  char body[] = {"foo"};
  int bodySize = sizeof(body) / sizeof(body[0]);

  // Format your command and wait up to 2 seconds for SIM7070 to respond
  sprintf(cmdBuff, "AT+SHBOD=%i,10000", bodySize);
  fona.getReply(cmdBuff, 2000);

  // If you get a reply, hope it's a prompt
  if (strstr(fona.replybuffer, ">") == NULL)
    Serial.println("No > in reply buffer");

  // Send the data to the module and wait for OK
  if (!fona.sendCheckReply(body, "OK", 2000))
    Serial.println("No OK in reply buffer.");

  // Data added!  Ha.  That's what they WANT you to think.
}

Here is the entire sketch below. This was modified slightly from the ESP32 example. Again, everything works perfectly when I comment out the "addBodyToPost" function.

#include <Arduino.h>
#include "Adafruit_FONA.h" // https://github.com/botletics/SIM7000-LTE-Shield/tree/master/Code

#define SIMCOM_7070 // I'm using one of these

#define FONA_PWRKEY 18
#define FONA_RST 5
#define FONA_TX 16 // ESP32 hardware serial RX2 (GPIO16)
#define FONA_RX 17 // ESP32 hardware serial TX2 (GPIO17)

// For ESP32 hardware serial
#include <HardwareSerial.h>
HardwareSerial fonaSS(1);

// The fona library.  Excellent!
Adafruit_FONA_LTE fona = Adafruit_FONA_LTE();

void addBodyToPost()
{
  // Sending plan text and wait one second, b/c I've seen that in other tutorials
  fona.HTTP_addHeader("Content-Type", "text/plain", 10);
  delay(1000);

  fona.HTTP_addHeader("Host", "b225f0b114f9.ngrok.io", 21);
  delay(1000);

  fona.HTTP_addHeader("User-Agent", "IOE Client", 10);
  delay(1000);

  // Add the SHBOD.  It will return a ">" when it is ready for data
  char cmdBuff[150];
  char body[] = {"foo"};
  int bodySize = sizeof(body) / sizeof(body[0]);

  // Format your command and wait up to 2 seconds for SIM7070 go respond
  sprintf(cmdBuff, "AT+SHBOD=%i,10000", bodySize);
  fona.getReply(cmdBuff, 2000);

  // If you get a reply, hope it's a prompt
  if (strstr(fona.replybuffer, ">") == NULL)
    Serial.println("No > in reply buffer");

  // Send the data to the module and wait for OK
  if (!fona.sendCheckReply(body, "OK", 2000))
    Serial.println("No OK in reply buffer.");

  // Data added!  Ha.  That's what they WANT you to think.
}

void postRequest()
{

  addBodyToPost();

  // Send your reply and wait up to five seconds for the module to confirm
  fona.sendCheckReply("AT+SHREQ=\"http://b225f0b114f9.ngrok.io\",3", "OK", 5 * 1000);

  // Read responses for up to 10 seconds
  // Note: What's odd is that when adding a body, this fails immediately
  // Parse response status and size
  // Example reply --> "+SHREQ: "POST",200,452"
  uint16_t status, datalen;
  fona.readline(10 * 1000);

  // What did it return?
  DEBUG_PRINT("\t<--- ");
  DEBUG_PRINTLN(fona.replybuffer);

  // Did we get a status reply of 200?
  if (!fona.parseReply(F("+SHREQ: \"POST\""), &status, ',', 1))
  {
    Serial.println("Unable to get status");
    return;
  }

  // The moment of truth
  if (status != 200)
  {
    // D'oh ... what went wrong?
    Serial.println("No soup for you!  Failure ....");
  }
  else
  {
    // Yus!! We got a reply from the server.  Let's see what it says!
    Serial.println("Huzzah!  We have a response ...");

    if (!fona.parseReply(F("+SHREQ: \"POST\""), &datalen, ',', 2))
    {
      Serial.println("Unable to get data");
    }

    DEBUG_PRINT("HTTP status: ");
    DEBUG_PRINTLN(status);
    DEBUG_PRINT("Data length: ");
    DEBUG_PRINTLN(datalen);

    // Read server response
    fona.getReply(F("AT+SHREAD=0,"), datalen, 10000);
    fona.readline();
    DEBUG_PRINT("\t<--- ");
    DEBUG_PRINTLN(fona.replybuffer); // +SHREAD: <datalen>
    fona.readline(10000);
    DEBUG_PRINT("\t<--- ");
    DEBUG_PRINTLN(fona.replybuffer); // Print out server reply
  }
}

void setup()
{

  pinMode(FONA_RST, OUTPUT);
  digitalWrite(FONA_RST, HIGH); // Default state

  fona.powerOn(FONA_PWRKEY); // Power on the module

  Serial.begin(9600);
  Serial.println(F("ESP32 SIMCom Basic Test"));
  Serial.println(F("Initializing....(May take several seconds)"));

  fonaSS.begin(115200, SERIAL_8N1, FONA_TX, FONA_RX); // baud rate, protocol, ESP32 RX pin, ESP32 TX pin

  Serial.println(F("Configuring to 9600 baud"));
  fonaSS.println("AT+IPR=9600");                    // Set baud rate
  delay(100);                                       // Short pause to let the command run
  fonaSS.begin(9600, SERIAL_8N1, FONA_TX, FONA_RX); // Switch to 9600
  if (!fona.begin(fonaSS))
  {
    Serial.println(F("Couldn't find FONA"));
    while (1)
      ; // Don't proceed if it couldn't find the device
  }

  uint8_t type = fona.type();
  Serial.println(F("FONA is OK"));
  Serial.print(F("Found "));
  switch (type)
  {
  case SIM7070:
    Serial.println(F("SIM7070"));
    break;
  }

  // Print module IMEI number.
  char imei[16] = {0};
  uint8_t imeiLen = fona.getIMEI(imei);
  if (imeiLen > 0)
  {
    Serial.print("Module IMEI: ");
    Serial.println(imei);
  }

  // Set modem to full functionality
  fona.setFunctionality(1);               // AT+CFUN=1
  fona.setNetworkSettings(F("hologram")); // For Hologram SIM card
  fona.setPreferredMode(38);              // Use LTE only, not 2G
  fona.setPreferredLTEMode(1);            // Use LTE CAT-M only, not NB-IoT

  int attemptCount = 0;
  while (!fona.getNetworkInfo())
  {
    delay(1000);
    attemptCount++;
    if (attemptCount == 10)
    {
      ESP.restart();
    }
  }

  // Attempt to turn on data
  attemptCount = 0;
  while (!fona.enableGPRS(true))
  {
    delay(1000);
    attemptCount++;
    if (attemptCount == 10)
    {
      ESP.restart();
    }
  }

  char url[] = {"http://b225f0b114f9.ngrok.io"};
  fona.HTTP_connect(url);

  postRequest();

  fona.getReply("AT+SHDISC", 10000); // Disconnect HTTP

  delay(10 * 1000);
  ESP.restart();
}

void loop(){};

This code gives me the output below:

ESP32 SIMCom Basic Test Initializing....(May take several seconds) Configuring to 9600 baud Attempting to open comm with ATs ---> AT <--- AT ---> AT <--- AT ---> ATE0 <--- ATE0 ---> ATE0 <--- OK ---> AT+GMR <--- Revision:1951B03SIM7070

OK

    ---> AT+CPMS="SM","SM","SM"
    <--- +CPMS: 0,10,0,10,0,10

FONA is OK Found SIM7070 ---> AT+GSN <--- 869777041783823 Module IMEI: 869777041783823 ---> AT+CFUN=1 <--- OK ---> AT+CGDCONT=1,"IP","hologram" <--- OK ---> AT+CNMP=38 <--- OK ---> AT+CMNB=1 <--- OK ---> AT+CPSI? <--- +CPSI: LTE CAT-M1,Online,310-410,0x3A85,46161679,402,EUTRAN-BAND12,5110,3,3,-17,-80,-50,11 OK replyOK ---> AT+CNACT=0,1 <--- OK <--- +APP PDP: 0,ACTIVE ---> AT+CNACT? <--- +CNACT: 0,1,"10.155.118.146" ---> AT+SHCONF="URL","http://b225f0b114f9.ngrok.io" <--- OK ---> AT+SHCONF="BODYLEN",1024 <--- OK ---> AT+SHCONF="HEADERLEN",350 <--- OK ---> AT+SHCONN <--- OK ---> AT+SHSTATE? <--- +SHSTATE: 1 ---> AT+SHCHEAD <--- OK ---> AT+SHAHEAD="Content-Type","text/plain" <--- OK ---> AT+SHAHEAD="Host","b225f0b114f9.ngrok.io" <--- OK ---> AT+SHAHEAD="User-Agent","IOE Client" <--- OK ---> AT+SHBOD=4,10000 <--- > ---> foo <--- OK ---> AT+SHREQ="http://b225f0b114f9.ngrok.io",3 <--- OK Unable to get status ---> AT+SHDISC <--- AT+SHDISC

Any ideas on what's going wrong?

I've tried with and without headers. I've tried with varying SHBOD lengths (i.e. AT+SHBOD=3,... instead of AT_SHBOD=4). No luck.

ladyada commented 3 years ago

hi please ask waveshare for help & support - we dont own that module! :)

KnightOfNih commented 3 years ago

Well shucks. Does your team have an example of using HTTP POST with a body attached? In theory, it should all work the same since you both use a SIM7070 (I would assume).

ladyada commented 3 years ago

nope, we have never used a SIM7070, don't even own one!

KnightOfNih commented 3 years ago

Ok, thank you for the prompt responses. Sorry, was using a library built on top of yours! https://github.com/botletics/SIM7000-LTE-Shield