vshymanskyy / TinyGSM

A small Arduino library for GSM modules, that just works
GNU Lesser General Public License v3.0
1.95k stars 723 forks source link

Problem with the HttpClient example. #435

Open jatincc opened 4 years ago

jatincc commented 4 years ago

[ x] I have read the Troubleshooting section of the ReadMe

What type of issues is this?

[ ] Request to support a new module

[ ] Bug or problem compiling the library [ ] Bug or issue with library functionality (ie, sending data over TCP/IP) [x ] Question or request for help

What are you working with?

Modem: SEQUANS Communications GM01Q UE5.2.0.1 Main processor board: Nucleo L476RG TinyGSM version: 0.10.8 Code:

 *
 * This sketch connects to a website and downloads a page.
 * It can be used to perform HTTP/RESTful API calls.
 *
 * For this example, you need to install ArduinoHttpClient library:
 *   https://github.com/arduino-libraries/ArduinoHttpClient
 *   or from http://librarymanager/all#ArduinoHttpClient
 *
 * TinyGSM Getting Started guide:
 *   https://tiny.cc/tinygsm-readme
 *
 * For more HTTP API examples, see ArduinoHttpClient library
 *
 * NOTE: This example may NOT work with the XBee because the
 * HttpClient library does not empty to serial buffer fast enough
 * and the buffer overflow causes the HttpClient library to stall.
 * Boards with faster processors may work, 8MHz boards will not.
 **************************************************************/

// Select your modem:
//#define TINY_GSM_MODEM_SIM800
// #define TINY_GSM_MODEM_SIM808
// #define TINY_GSM_MODEM_SIM868
// #define TINY_GSM_MODEM_SIM900
// #define TINY_GSM_MODEM_SIM7000
// #define TINY_GSM_MODEM_SIM5360
// #define TINY_GSM_MODEM_SIM7600
// #define TINY_GSM_MODEM_UBLOX
// #define TINY_GSM_MODEM_SARAR4
// #define TINY_GSM_MODEM_M95
// #define TINY_GSM_MODEM_BG96
// #define TINY_GSM_MODEM_A6
// #define TINY_GSM_MODEM_A7
// #define TINY_GSM_MODEM_M590
// #define TINY_GSM_MODEM_MC60
// #define TINY_GSM_MODEM_MC60E
// #define TINY_GSM_MODEM_ESP8266
// #define TINY_GSM_MODEM_XBEE
 #define TINY_GSM_MODEM_SEQUANS_MONARCH

// Set serial for debug console (to the Serial Monitor, default speed 115200)
#define SerialMon Serial

#ifdef ARDUINO_ARCH_STM32
HardwareSerial Serial1(PA10, PA9);  // RX, TX
#endif

// Set serial for AT commands (to the module)
// Use Hardware Serial on Mega, Leonardo, Micro
#define SerialAT Serial1

// or Software Serial on Uno, Nano
//#include <SoftwareSerial.h>
//SoftwareSerial SerialAT(2, 3); // RX, TX

// Increase RX buffer to capture the entire response
// Chips without internal buffering (A6/A7, ESP8266, M590)
// need enough space in the buffer for the entire response
// else data will be lost (and the http library will fail).
#if !defined(TINY_GSM_RX_BUFFER)
#define TINY_GSM_RX_BUFFER 650
#endif

// See all AT commands, if wanted
 #define DUMP_AT_COMMANDS

// Define the serial console for debug prints, if needed
#define TINY_GSM_DEBUG SerialMon
// #define LOGGING  // <- Logging is for the HTTP library

// Range to attempt to autobaud
#define GSM_AUTOBAUD_MIN 9600
#define GSM_AUTOBAUD_MAX 115200

// Add a reception delay - may be needed for a fast processor at a slow baud rate
// #define TINY_GSM_YIELD() { delay(2); }

// Define how you're planning to connect to the internet
#define TINY_GSM_USE_GPRS true
#define TINY_GSM_USE_WIFI false

// set GSM PIN, if any
#define GSM_PIN ""

// Your GPRS credentials, if any
const char apn[]  = "";
const char gprsUser[] = "";
const char gprsPass[] = "";

// Your WiFi connection credentials, if applicable
const char wifiSSID[]  = "YourSSID";
const char wifiPass[] = "YourWiFiPass";

// Server details
const char server[] = "vsh.pp.ua";
const char resource[] = "/TinyGSM/logo.txt";
const int  port = 80;

#include <TinyGsmClient.h>
#include <ArduinoHttpClient.h>

// Just in case someone defined the wrong thing..
#if TINY_GSM_USE_GPRS && not defined TINY_GSM_MODEM_HAS_GPRS
#undef TINY_GSM_USE_GPRS
#undef TINY_GSM_USE_WIFI
#define TINY_GSM_USE_GPRS false
#define TINY_GSM_USE_WIFI true
#endif
#if TINY_GSM_USE_WIFI && not defined TINY_GSM_MODEM_HAS_WIFI
#undef TINY_GSM_USE_GPRS
#undef TINY_GSM_USE_WIFI
#define TINY_GSM_USE_GPRS true
#define TINY_GSM_USE_WIFI false
#endif

#ifdef DUMP_AT_COMMANDS
  #include <StreamDebugger.h>
  StreamDebugger debugger(SerialAT, SerialMon);
  TinyGsm modem(debugger);
#else
  TinyGsm modem(SerialAT);
#endif

TinyGsmClient client(modem);
HttpClient http(client, server, port);

#define SIM1 PA8
#define SIM2 PB5
#define RTS PA1
#define RESET PC7

void setup() {
  // Set console baud rate
  SerialMon.begin(115200);
  delay(10);

  // !!!!!!!!!!!
  // Set your reset, enable, power pins here
  // !!!!!!!!!!!

  pinMode(SIM1, OUTPUT);
  digitalWrite(SIM1, LOW);

  pinMode(SIM2, OUTPUT);
  digitalWrite(SIM2, LOW);

  pinMode(RTS, OUTPUT);
  digitalWrite(RTS, LOW);

  pinMode(RESET, OUTPUT);
  digitalWrite(RESET, HIGH);
  delay(500);
  digitalWrite(RESET, LOW);

  SerialMon.println("Wait...");

  // Set GSM module baud rate
  TinyGsmAutoBaud(SerialAT, GSM_AUTOBAUD_MIN, GSM_AUTOBAUD_MAX);
  // SerialAT.begin(9600);
  delay(6000);

  // Restart takes quite some time
  // To skip it, call init() instead of restart()
  SerialMon.println("Initializing modem...");
  modem.restart();
  // modem.init();

  String modemInfo = modem.getModemInfo();
  SerialMon.print("Modem Info: ");
  SerialMon.println(modemInfo);

#if TINY_GSM_USE_GPRS
  // Unlock your SIM card with a PIN if needed
  if ( GSM_PIN && modem.getSimStatus() != 3 ) {
    modem.simUnlock(GSM_PIN);
  }
#endif
}

void loop() {

#if TINY_GSM_USE_WIFI
  // Wifi connection parameters must be set before waiting for the network
  SerialMon.print(F("Setting SSID/password..."));
  if (!modem.networkConnect(wifiSSID, wifiPass)) {
    SerialMon.println(" fail");
    delay(10000);
    return;
  }
  SerialMon.println(" success");
#endif

#if TINY_GSM_USE_GPRS && defined TINY_GSM_MODEM_XBEE
  // The XBee must run the gprsConnect function BEFORE waiting for network!
  modem.gprsConnect(apn, gprsUser, gprsPass);
#endif

  SerialMon.print("Waiting for network...");
  if (!modem.waitForNetwork()) {
    SerialMon.println(" fail");
    delay(10000);
    return;
  }
  SerialMon.println(" success");

  if (modem.isNetworkConnected()) {
    SerialMon.println("Network connected");
  }

#if TINY_GSM_USE_GPRS
  // GPRS connection parameters are usually set after network registration
    SerialMon.print(F("Connecting to "));
    SerialMon.print(apn);
    if (!modem.gprsConnect(apn, gprsUser, gprsPass)) {
      SerialMon.println(" fail");
      delay(10000);
      return;
    }
    SerialMon.println(" success");

    if (modem.isGprsConnected()) {
      SerialMon.println("GPRS connected");
    }
#endif

  SerialMon.print(F("Performing HTTP GET request... "));
  int err = http.get(resource);
  if (err != 0) {
    SerialMon.println(F("failed to connect"));
    delay(10000);
    return;
  }

  int status = http.responseStatusCode();
  SerialMon.print(F("Response status code: "));
  SerialMon.println(status);
  if (!status) {
    delay(10000);
    return;
  }

  SerialMon.println(F("Response Headers:"));
  while (http.headerAvailable()) {
    String headerName = http.readHeaderName();
    String headerValue = http.readHeaderValue();
    SerialMon.println("    " + headerName + " : " + headerValue);
  }

  int length = http.contentLength();
  if (length >= 0) {
    SerialMon.print(F("Content length is: "));
    SerialMon.println(length);
  }
  if (http.isResponseChunked()) {
    SerialMon.println(F("The response is chunked"));
  }

  String body = http.responseBody();
  SerialMon.println(F("Response:"));
  SerialMon.println(body);

  SerialMon.print(F("Body length is: "));
  SerialMon.println(body.length());

  // Shutdown

  http.stop();
  SerialMon.println(F("Server disconnected"));

#if TINY_GSM_USE_WIFI
    modem.networkDisconnect();
    SerialMon.println(F("WiFi disconnected"));
#endif
#if TINY_GSM_USE_GPRS
    modem.gprsDisconnect();
    SerialMon.println(F("GPRS disconnected"));
#endif

  // Do nothing forevermore
  while (true) {
    delay(1000);
  }
}

Scenario, steps to reproduce

I am trying to get the HttpClient working with STM32 Nucleo L476RG board. Using the X-NUCLEO-STMOD1 expansion board connected with the SEQUANS GM10Q Monarch.

Expected result

I should expect to see the TinyGSM ascii logo.

Actual result


GPRS connected
Performing HTTP GET request... AT+SQNSCFG=1,3,300,90,600,50

OK
AT+SQNSCFGEXT=1,1,0,0,0,0

OK
AT+SQNSD=1,0,80,"vsh.pp.ua",0,0,1

OK
AT+SQNSS

+SQNSS: 1,2,"<VALID IP>",49153,"212.237.59.104",80
+SQNSS: 2,0
+SQNSS: 3,0
+SQNSS: 4,0
+SQNSS: 5,0
+SQNSS: 6,0

OK
AT+SQNSSENDEXT=1,3

> GET
OK
AT+SQNSSENDEXT=1,1

+CME ERROR: operation not supported
 [54412] ### no OK after send
AT+SQNSSENDEXT=1,17

+CME ERROR: operation not supported
/TinyGSM/logo.txt[55420] ### no OK after send
AT+SQNSSENDEXT=1,9

+CME ERROR: operation not supported
 HTTP/1.1[56427] ### no OK after send
AT+SQNSSENDEXT=1,2

+CME ERROR: operation not supported

[57433] ### no OK after send
AT+SQNSSENDEXT=1,6

> Host: 
OK
AT+SQNSSENDEXT=1,9

+CME ERROR: operation not supported
vsh.pp.ua[58448] ### no OK after send
AT+SQNSSENDEXT=1,2

+CME ERROR: operation not supported

+SQNSRING: 1,343
[58456] ### URC Data Received: 343 on 1

+SQNSH: 1
[58457] ### URC Sock Closed:  1
[59454] ### no OK after send
AT+SQNSI=1

+SQNSI: 1,9,343,343,0

OK
AT+SQNSS

+SQNSS: 1,0
+SQNSS: 2,0
+SQNSS: 3,0
+SQNSS: 4,0
+SQNSS: 5,0
+SQNSS: 6,0

OK
[59471] ### Sock closed, cannot send data!
[59471] ### Sock closed, cannot send data!
[59474] ### Sock closed, cannot send data!
[59478] ### Sock closed, cannot send data!
[59482] ### Sock closed, cannot send data!
[59485] ### Sock closed, cannot send data!
[59489] ### Sock closed, cannot send data!
[59493] ### Sock closed, cannot send data!
[59497] ### Sock closed, cannot send data!
AT+SQNSI=1

+SQNSI: 1,9,343,343,0

OK
AT+SQNSS

+SQNSS: 1,0
+SQNSS: 2,0
+SQNSS: 3,0
+SQNSS: 4,0
+SQNSS: 5,0
+SQNSS: 6,0

OK
AT+SQNSRECV=1,343

+SQNSRECV: 1,343
HTTP/1.1 400 Bad Request
Server: nginx/1.10.3 (Ubuntu)
Date: Wed, 02 Sep 2020 06:28:05 GMT
Content-Type: text/html
Content-Length: 182
Connection: close

<html>
<head><title>400 Bad Request</title></head>
<body bgcolor="white">
<center><h1>400 Bad Request</h1></center>
<hr><center>nginx/1.10.3 (Ubuntu)</center>
</body>
</html>

OK
AT+SQNSI=1

+SQNSI: 1,9,343,0,0

OK
Response status code: 400
Response Headers:
    Server : nginx/1.10.3 (Ubuntu)
    Date : Wed, 02 Sep 2020 06:28:05 GMT
    Content-Type : text/html
    Content-Length : 182
    Connection : close
Content length is: 182
Response:
<html>
<head><title>400 Bad Request</title></head>
<body bgcolor="white">
<center><h1>400 Bad Request</h1></center>
<hr><center>nginx/1.10.3 (Ubuntu)</center>
</body>
</html>

Body length is: 182
AT+SQNSH=1

OK
Server disconnected
AT+CGATT=0

OK
AT+CGACT=0

+CEREG: 0

OK
GPRS disconnected

Debug and AT command log

I have tried factory resetting the modem but i get this error.

+SYSSTART
AT

OK
ATE0

OK
AT+CMEE=0

OK
AT+CFUN=1

OK
AT+CTZR=0

OK
AT+CTZU=1

OK
AT+CPIN?

OK

ERROR
AT+CPIN?
AT+CPIN?

+CPIN: READY

OK
AT&F0

+CPIN: READY

OK
ATZ
AT+IPR=0
***********************************************************
 Return settings to Factory Defaults: FAIL
***********************************************************
SRGDamia1 commented 4 years ago

I'm sorry; I'm finally checking through a month of issues. Did you get this working? I fried the one Monarch chip I had (DOH!) so I can't do much troubleshooting myself.

UCIS commented 3 years ago

I noticed a similar problem, and think it might have been fixed by https://github.com/vshymanskyy/TinyGSM/commit/38a712500ed862128c5f88e8761a88f4066771dc#diff-54854492bf719b8c61334c1cf1017e0ad996eda65cf986c179b53485358e2e6eL723

Specifically, according to the documentation, it appears that the modem only expects a CR character as a line terminator rather than a CRLF (or even just LF). The old situation caused the redundant LF character to be prepended to the data sequence sent to the remote end, and the last data character being prepended to the next command, corrupting it and causing the subsequent "operation not supported" error.

Anyway, in my case just changing const char* gsmNL = CRLF; to const char* gsmNL = "\r"; appears to fix the issue, even using when using used "plain text" mode instead of hex mode.