Restructured to bring similar functions together
This commit is contained in:
		@@ -238,9 +238,8 @@ public:
 | 
				
			|||||||
    if (waitResponse(GF(GSM_NL "+ICCID:")) != 1) {
 | 
					    if (waitResponse(GF(GSM_NL "+ICCID:")) != 1) {
 | 
				
			||||||
      return "";
 | 
					      return "";
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    String res = stream.readStringUntil('\n');
 | 
					    String res = streamReadUntil('\n');
 | 
				
			||||||
    waitResponse();
 | 
					    waitResponse();
 | 
				
			||||||
    res.trim();
 | 
					 | 
				
			||||||
    return res;
 | 
					    return res;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -249,9 +248,8 @@ public:
 | 
				
			|||||||
    if (waitResponse(GF(GSM_NL)) != 1) {
 | 
					    if (waitResponse(GF(GSM_NL)) != 1) {
 | 
				
			||||||
      return "";
 | 
					      return "";
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    String res = stream.readStringUntil('\n');
 | 
					    String res = streamReadUntil('\n');
 | 
				
			||||||
    waitResponse();
 | 
					    waitResponse();
 | 
				
			||||||
    res.trim();
 | 
					 | 
				
			||||||
    return res;
 | 
					    return res;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -260,38 +258,11 @@ public:
 | 
				
			|||||||
    if (waitResponse(GF(GSM_NL "+CSQ:")) != 1) {
 | 
					    if (waitResponse(GF(GSM_NL "+CSQ:")) != 1) {
 | 
				
			||||||
      return 99;
 | 
					      return 99;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    int res = stream.readStringUntil(',').toInt();
 | 
					    int res = streamReadUntil(',').toInt();
 | 
				
			||||||
    waitResponse();
 | 
					    waitResponse();
 | 
				
			||||||
    return res;
 | 
					    return res;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  bool callAnswer() {
 | 
					 | 
				
			||||||
    sendAT(GF("A"));
 | 
					 | 
				
			||||||
    return waitResponse() == 1;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  bool callNumber(const String& number) {
 | 
					 | 
				
			||||||
    sendAT(GF("D"), number);
 | 
					 | 
				
			||||||
    return waitResponse() == 1;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  bool callHangup(const String& number) {
 | 
					 | 
				
			||||||
    sendAT(GF("H"), number);
 | 
					 | 
				
			||||||
    return waitResponse() == 1;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  bool sendSMS(const String& number, const String& text) {
 | 
					 | 
				
			||||||
    sendAT(GF("+CMGF=1"));
 | 
					 | 
				
			||||||
    waitResponse();
 | 
					 | 
				
			||||||
    sendAT(GF("+CMGS=\""), number, GF("\""));
 | 
					 | 
				
			||||||
    if (waitResponse(GF(">")) != 1) {
 | 
					 | 
				
			||||||
      return false;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    stream.print(text);
 | 
					 | 
				
			||||||
    stream.write((char)0x1A);
 | 
					 | 
				
			||||||
    return waitResponse(60000L) == 1;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  SimStatus getSimStatus(unsigned long timeout = 10000L) {
 | 
					  SimStatus getSimStatus(unsigned long timeout = 10000L) {
 | 
				
			||||||
    for (unsigned long start = millis(); millis() - start < timeout; ) {
 | 
					    for (unsigned long start = millis(); millis() - start < timeout; ) {
 | 
				
			||||||
      sendAT(GF("+CPIN?"));
 | 
					      sendAT(GF("+CPIN?"));
 | 
				
			||||||
@@ -317,7 +288,7 @@ public:
 | 
				
			|||||||
      return REG_UNKNOWN;
 | 
					      return REG_UNKNOWN;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    streamSkipUntil(','); // Skip format (0)
 | 
					    streamSkipUntil(','); // Skip format (0)
 | 
				
			||||||
    int status = stream.readStringUntil('\n').toInt();
 | 
					    int status = streamReadUntil('\n').toInt();
 | 
				
			||||||
    waitResponse();
 | 
					    waitResponse();
 | 
				
			||||||
    return (RegStatus)status;
 | 
					    return (RegStatus)status;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -328,7 +299,7 @@ public:
 | 
				
			|||||||
      return "";
 | 
					      return "";
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    streamSkipUntil('"'); // Skip mode and format
 | 
					    streamSkipUntil('"'); // Skip mode and format
 | 
				
			||||||
    String res = stream.readStringUntil('"');
 | 
					    String res = streamReadUntil('"');
 | 
				
			||||||
    waitResponse();
 | 
					    waitResponse();
 | 
				
			||||||
    return res;
 | 
					    return res;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -338,8 +309,6 @@ public:
 | 
				
			|||||||
      RegStatus s = getRegistrationStatus();
 | 
					      RegStatus s = getRegistrationStatus();
 | 
				
			||||||
      if (s == REG_OK_HOME || s == REG_OK_ROAMING) {
 | 
					      if (s == REG_OK_HOME || s == REG_OK_ROAMING) {
 | 
				
			||||||
        return true;
 | 
					        return true;
 | 
				
			||||||
      } else if (s == REG_UNREGISTERED) {
 | 
					 | 
				
			||||||
        return false;
 | 
					 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      delay(1000);
 | 
					      delay(1000);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -393,6 +362,21 @@ public:
 | 
				
			|||||||
   * Phone Call functions
 | 
					   * Phone Call functions
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bool callAnswer() {
 | 
				
			||||||
 | 
					    sendAT(GF("A"));
 | 
				
			||||||
 | 
					    return waitResponse() == 1;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bool callNumber(const String& number) {
 | 
				
			||||||
 | 
					    sendAT(GF("D"), number);
 | 
				
			||||||
 | 
					    return waitResponse() == 1;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bool callHangup(const String& number) {
 | 
				
			||||||
 | 
					    sendAT(GF("H"), number);
 | 
				
			||||||
 | 
					    return waitResponse() == 1;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /*
 | 
					  /*
 | 
				
			||||||
   * Messaging functions
 | 
					   * Messaging functions
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
@@ -403,6 +387,18 @@ public:
 | 
				
			|||||||
  void sendSMS() {
 | 
					  void sendSMS() {
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bool sendSMS(const String& number, const String& text) {
 | 
				
			||||||
 | 
					    sendAT(GF("+CMGF=1"));
 | 
				
			||||||
 | 
					    waitResponse();
 | 
				
			||||||
 | 
					    sendAT(GF("+CMGS=\""), number, GF("\""));
 | 
				
			||||||
 | 
					    if (waitResponse(GF(">")) != 1) {
 | 
				
			||||||
 | 
					      return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    stream.print(text);
 | 
				
			||||||
 | 
					    stream.write((char)0x1A);
 | 
				
			||||||
 | 
					    return waitResponse(60000L) == 1;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /*
 | 
					  /*
 | 
				
			||||||
   * Location functions
 | 
					   * Location functions
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
@@ -413,76 +409,13 @@ public:
 | 
				
			|||||||
   * Battery functions
 | 
					   * Battery functions
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					  /* Public Utilities */
 | 
				
			||||||
  int modemConnect(const char* host, uint16_t port, uint8_t* mux) {
 | 
					 | 
				
			||||||
    sendAT(GF("+CIPSTART="),  GF("\"TCP"), GF("\",\""), host, GF("\","), port);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (waitResponse(75000L, GF(GSM_NL "+CIPNUM:")) != 1) {
 | 
					 | 
				
			||||||
      return -1;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    int newMux = stream.readStringUntil('\n').toInt();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    int rsp = waitResponse(75000L,
 | 
					 | 
				
			||||||
                           GF("CONNECT OK" GSM_NL),
 | 
					 | 
				
			||||||
                           GF("CONNECT FAIL" GSM_NL),
 | 
					 | 
				
			||||||
                           GF("ALREADY CONNECT" GSM_NL));
 | 
					 | 
				
			||||||
    if (waitResponse() != 1) {
 | 
					 | 
				
			||||||
      return -1;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    *mux = newMux;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return (1 == rsp);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  int modemSend(const void* buff, size_t len, uint8_t mux) {
 | 
					 | 
				
			||||||
    sendAT(GF("+CIPSEND="), mux, ',', len);
 | 
					 | 
				
			||||||
    if (waitResponse(10000L, GF(GSM_NL ">")) != 1) {
 | 
					 | 
				
			||||||
      return -1;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    stream.write((uint8_t*)buff, len);
 | 
					 | 
				
			||||||
    stream.flush();
 | 
					 | 
				
			||||||
    if (waitResponse(10000L, GFP(GSM_OK), GF(GSM_NL "FAIL")) != 1) {
 | 
					 | 
				
			||||||
      return -1;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return len;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  bool modemGetConnected(uint8_t mux) { //TODO mux?
 | 
					 | 
				
			||||||
    sendAT(GF("+CIPSTATUS"));
 | 
					 | 
				
			||||||
    int res = waitResponse(GF(",\"CONNECTED\""), GF(",\"CLOSED\""), GF(",\"CLOSING\""), GF(",\"INITIAL\""));
 | 
					 | 
				
			||||||
    waitResponse();
 | 
					 | 
				
			||||||
    return 1 == res;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /* Utilities */
 | 
					 | 
				
			||||||
  template<typename T>
 | 
					 | 
				
			||||||
  void streamWrite(T last) {
 | 
					 | 
				
			||||||
    stream.print(last);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  template<typename T, typename... Args>
 | 
					 | 
				
			||||||
  void streamWrite(T head, Args... tail) {
 | 
					 | 
				
			||||||
    stream.print(head);
 | 
					 | 
				
			||||||
    streamWrite(tail...);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  int streamRead() { return stream.read(); }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  bool streamSkipUntil(char c) { //TODO: timeout
 | 
					 | 
				
			||||||
    while (true) {
 | 
					 | 
				
			||||||
      while (!stream.available()) {}
 | 
					 | 
				
			||||||
      if (stream.read() == c)
 | 
					 | 
				
			||||||
        return true;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return false;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  template<typename... Args>
 | 
					  template<typename... Args>
 | 
				
			||||||
  void sendAT(Args... cmd) {
 | 
					  void sendAT(Args... cmd) {
 | 
				
			||||||
    streamWrite("AT", cmd..., GSM_NL);
 | 
					    streamWrite("AT", cmd..., GSM_NL);
 | 
				
			||||||
    stream.flush();
 | 
					    stream.flush();
 | 
				
			||||||
    TINY_GSM_YIELD();
 | 
					    TINY_GSM_YIELD();
 | 
				
			||||||
    //DBG("### AT:", cmd...);
 | 
					    DBG(GSM_NL, ">>> AT:", cmd...);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // TODO: Optimize this!
 | 
					  // TODO: Optimize this!
 | 
				
			||||||
@@ -521,8 +454,8 @@ private:
 | 
				
			|||||||
          index = 5;
 | 
					          index = 5;
 | 
				
			||||||
          goto finish;
 | 
					          goto finish;
 | 
				
			||||||
        } else if (data.endsWith(GF("+CIPRCV:"))) {
 | 
					        } else if (data.endsWith(GF("+CIPRCV:"))) {
 | 
				
			||||||
          int mux = stream.readStringUntil(',').toInt();
 | 
					          int mux = streamReadUntil(',').toInt();
 | 
				
			||||||
          int len = stream.readStringUntil(',').toInt();
 | 
					          int len = streamReadUntil(',').toInt();
 | 
				
			||||||
          if (len > sockets[mux]->rx.free()) {
 | 
					          if (len > sockets[mux]->rx.free()) {
 | 
				
			||||||
            DBG("### Buffer overflow: ", len, "->", sockets[mux]->rx.free());
 | 
					            DBG("### Buffer overflow: ", len, "->", sockets[mux]->rx.free());
 | 
				
			||||||
          } else {
 | 
					          } else {
 | 
				
			||||||
@@ -535,14 +468,14 @@ private:
 | 
				
			|||||||
          data = "";
 | 
					          data = "";
 | 
				
			||||||
          return index;
 | 
					          return index;
 | 
				
			||||||
        } else if (data.endsWith(GF("+TCPCLOSED:"))) {
 | 
					        } else if (data.endsWith(GF("+TCPCLOSED:"))) {
 | 
				
			||||||
          int mux = stream.readStringUntil(',').toInt();
 | 
					          int mux = streamReadUntil(',').toInt();
 | 
				
			||||||
          stream.readStringUntil('\n');
 | 
					         streamReadUntil('\n');
 | 
				
			||||||
          sockets[mux]->sock_connected = false;
 | 
					         sockets[mux]->sock_connected = false;
 | 
				
			||||||
          data = "";
 | 
					         data = "";
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    } while (millis() - startMillis < timeout);
 | 
					    } while (millis() - startMillis < timeout);
 | 
				
			||||||
finish:
 | 
					  finish:
 | 
				
			||||||
    if (!index) {
 | 
					    if (!index) {
 | 
				
			||||||
      data.trim();
 | 
					      data.trim();
 | 
				
			||||||
      if (data.length()) {
 | 
					      if (data.length()) {
 | 
				
			||||||
@@ -550,6 +483,15 @@ finish:
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
      data = "";
 | 
					      data = "";
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    else {
 | 
				
			||||||
 | 
					      data.trim();
 | 
				
			||||||
 | 
					      data.replace(GSM_NL GSM_NL, GSM_NL);
 | 
				
			||||||
 | 
					      data.replace(GSM_NL, GSM_NL "    ");
 | 
				
			||||||
 | 
					      if (data.length()) {
 | 
				
			||||||
 | 
					        DBG(GSM_NL, "<<< ", data);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      data = "";
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    return index;
 | 
					    return index;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -567,6 +509,81 @@ finish:
 | 
				
			|||||||
    return waitResponse(1000, r1, r2, r3, r4, r5);
 | 
					    return waitResponse(1000, r1, r2, r3, r4, r5);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					  int modemConnect(const char* host, uint16_t port, uint8_t* mux) {
 | 
				
			||||||
 | 
					    sendAT(GF("+CIPSTART="),  GF("\"TCP"), GF("\",\""), host, GF("\","), port);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (waitResponse(75000L, GF(GSM_NL "+CIPNUM:")) != 1) {
 | 
				
			||||||
 | 
					      return -1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    int newMux = streamReadUntil('\n').toInt();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    int rsp = waitResponse(75000L,
 | 
				
			||||||
 | 
					                           GF("CONNECT OK" GSM_NL),
 | 
				
			||||||
 | 
					                           GF("CONNECT FAIL" GSM_NL),
 | 
				
			||||||
 | 
					                           GF("ALREADY CONNECT" GSM_NL));
 | 
				
			||||||
 | 
					    if (waitResponse() != 1) {
 | 
				
			||||||
 | 
					      return -1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    *mux = newMux;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return (1 == rsp);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  int modemSend(const void* buff, size_t len, uint8_t mux) {
 | 
				
			||||||
 | 
					    sendAT(GF("+CIPSEND="), mux, ',', len);
 | 
				
			||||||
 | 
					    if (waitResponse(10000L, GF(GSM_NL ">")) != 1) {
 | 
				
			||||||
 | 
					      return -1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    stream.write((uint8_t*)buff, len);
 | 
				
			||||||
 | 
					    stream.flush();
 | 
				
			||||||
 | 
					    if (waitResponse(10000L, GFP(GSM_OK), GF(GSM_NL "FAIL")) != 1) {
 | 
				
			||||||
 | 
					      return -1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return len;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bool modemGetConnected(uint8_t mux) { //TODO mux?
 | 
				
			||||||
 | 
					    sendAT(GF("+CIPSTATUS"));
 | 
				
			||||||
 | 
					    int res = waitResponse(GF(",\"CONNECTED\""), GF(",\"CLOSED\""), GF(",\"CLOSING\""), GF(",\"INITIAL\""));
 | 
				
			||||||
 | 
					    waitResponse();
 | 
				
			||||||
 | 
					    return 1 == res;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* Private Utilities */
 | 
				
			||||||
 | 
					  template<typename T>
 | 
				
			||||||
 | 
					  void streamWrite(T last) {
 | 
				
			||||||
 | 
					    stream.print(last);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  template<typename T, typename... Args>
 | 
				
			||||||
 | 
					  void streamWrite(T head, Args... tail) {
 | 
				
			||||||
 | 
					    stream.print(head);
 | 
				
			||||||
 | 
					    streamWrite(tail...);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  int streamRead() { return stream.read(); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  String streamReadUntil(char c) {
 | 
				
			||||||
 | 
					    String return_string = stream.readStringUntil(c);
 | 
				
			||||||
 | 
					    return_string.trim();
 | 
				
			||||||
 | 
					    if (String(c) == GSM_NL || String(c) == "\n"){
 | 
				
			||||||
 | 
					      DBG(return_string, c, "    ");
 | 
				
			||||||
 | 
					    } else DBG(return_string, c);
 | 
				
			||||||
 | 
					    return return_string;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bool streamSkipUntil(char c) { //TODO: timeout
 | 
				
			||||||
 | 
					    String skipped = stream.readStringUntil(c);
 | 
				
			||||||
 | 
					    skipped.trim();
 | 
				
			||||||
 | 
					    if (skipped.length()) {
 | 
				
			||||||
 | 
					      if (String(c) == GSM_NL || String(c) == "\n"){
 | 
				
			||||||
 | 
					        DBG(skipped, c, "    ");
 | 
				
			||||||
 | 
					      } else DBG(skipped, c);
 | 
				
			||||||
 | 
					      return true;
 | 
				
			||||||
 | 
					    } else return false;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
  Stream&       stream;
 | 
					  Stream&       stream;
 | 
				
			||||||
  GsmClient*    sockets[8];
 | 
					  GsmClient*    sockets[8];
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -233,55 +233,13 @@ public:
 | 
				
			|||||||
    return waitResponse(10000L) == 1;
 | 
					    return waitResponse(10000L) == 1;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					  /* Public Utilities */
 | 
				
			||||||
  int modemConnect(const char* host, uint16_t port, uint8_t mux) {
 | 
					 | 
				
			||||||
    sendAT(GF("+CIPSTART="), mux, ',', GF("\"TCP"), GF("\",\""), host, GF("\","), port, GF(",120"));
 | 
					 | 
				
			||||||
    int rsp = waitResponse(75000L,
 | 
					 | 
				
			||||||
                           GFP(GSM_OK),
 | 
					 | 
				
			||||||
                           GFP(GSM_ERROR),
 | 
					 | 
				
			||||||
                           GF(GSM_NL "ALREADY CONNECT" GSM_NL));
 | 
					 | 
				
			||||||
    return (1 == rsp);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  int modemSend(const void* buff, size_t len, uint8_t mux) {
 | 
					 | 
				
			||||||
    sendAT(GF("+CIPSEND="), mux, ',', len);
 | 
					 | 
				
			||||||
    if (waitResponse(GF(">")) != 1) {
 | 
					 | 
				
			||||||
      return -1;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    stream.write((uint8_t*)buff, len);
 | 
					 | 
				
			||||||
    if (waitResponse(GF(GSM_NL "SEND OK" GSM_NL)) != 1) {
 | 
					 | 
				
			||||||
      return -1;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return len;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  bool modemGetConnected(uint8_t mux) {
 | 
					 | 
				
			||||||
    sendAT(GF("+CIPSTATUS="), mux);
 | 
					 | 
				
			||||||
    int res = waitResponse(GF(",\"CONNECTED\""), GF(",\"CLOSED\""), GF(",\"CLOSING\""), GF(",\"INITIAL\""));
 | 
					 | 
				
			||||||
    waitResponse();
 | 
					 | 
				
			||||||
    return 1 == res;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /* Utilities */
 | 
					 | 
				
			||||||
  template<typename T>
 | 
					 | 
				
			||||||
  void streamWrite(T last) {
 | 
					 | 
				
			||||||
    stream.print(last);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  template<typename T, typename... Args>
 | 
					 | 
				
			||||||
  void streamWrite(T head, Args... tail) {
 | 
					 | 
				
			||||||
    stream.print(head);
 | 
					 | 
				
			||||||
    streamWrite(tail...);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  int streamRead() { return stream.read(); }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  template<typename... Args>
 | 
					  template<typename... Args>
 | 
				
			||||||
  void sendAT(Args... cmd) {
 | 
					  void sendAT(Args... cmd) {
 | 
				
			||||||
    streamWrite("AT", cmd..., GSM_NL);
 | 
					    streamWrite("AT", cmd..., GSM_NL);
 | 
				
			||||||
    stream.flush();
 | 
					    stream.flush();
 | 
				
			||||||
    TINY_GSM_YIELD();
 | 
					    TINY_GSM_YIELD();
 | 
				
			||||||
    //DBG("### AT:", cmd...);
 | 
					    DBG(GSM_NL, ">>> AT:", cmd...);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // TODO: Optimize this!
 | 
					  // TODO: Optimize this!
 | 
				
			||||||
@@ -339,7 +297,7 @@ private:
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    } while (millis() - startMillis < timeout);
 | 
					    } while (millis() - startMillis < timeout);
 | 
				
			||||||
finish:
 | 
					  finish:
 | 
				
			||||||
    if (!index) {
 | 
					    if (!index) {
 | 
				
			||||||
      data.trim();
 | 
					      data.trim();
 | 
				
			||||||
      if (data.length()) {
 | 
					      if (data.length()) {
 | 
				
			||||||
@@ -364,6 +322,49 @@ finish:
 | 
				
			|||||||
    return waitResponse(1000, r1, r2, r3, r4, r5);
 | 
					    return waitResponse(1000, r1, r2, r3, r4, r5);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					  int modemConnect(const char* host, uint16_t port, uint8_t mux) {
 | 
				
			||||||
 | 
					    sendAT(GF("+CIPSTART="), mux, ',', GF("\"TCP"), GF("\",\""), host, GF("\","), port, GF(",120"));
 | 
				
			||||||
 | 
					    int rsp = waitResponse(75000L,
 | 
				
			||||||
 | 
					                           GFP(GSM_OK),
 | 
				
			||||||
 | 
					                           GFP(GSM_ERROR),
 | 
				
			||||||
 | 
					                           GF(GSM_NL "ALREADY CONNECT" GSM_NL));
 | 
				
			||||||
 | 
					    return (1 == rsp);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  int modemSend(const void* buff, size_t len, uint8_t mux) {
 | 
				
			||||||
 | 
					    sendAT(GF("+CIPSEND="), mux, ',', len);
 | 
				
			||||||
 | 
					    if (waitResponse(GF(">")) != 1) {
 | 
				
			||||||
 | 
					      return -1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    stream.write((uint8_t*)buff, len);
 | 
				
			||||||
 | 
					    if (waitResponse(GF(GSM_NL "SEND OK" GSM_NL)) != 1) {
 | 
				
			||||||
 | 
					      return -1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return len;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bool modemGetConnected(uint8_t mux) {
 | 
				
			||||||
 | 
					    sendAT(GF("+CIPSTATUS="), mux);
 | 
				
			||||||
 | 
					    int res = waitResponse(GF(",\"CONNECTED\""), GF(",\"CLOSED\""), GF(",\"CLOSING\""), GF(",\"INITIAL\""));
 | 
				
			||||||
 | 
					    waitResponse();
 | 
				
			||||||
 | 
					    return 1 == res;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* Private Utilities */
 | 
				
			||||||
 | 
					  template<typename T>
 | 
				
			||||||
 | 
					  void streamWrite(T last) {
 | 
				
			||||||
 | 
					    stream.print(last);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  template<typename T, typename... Args>
 | 
				
			||||||
 | 
					  void streamWrite(T head, Args... tail) {
 | 
				
			||||||
 | 
					    stream.print(head);
 | 
				
			||||||
 | 
					    streamWrite(tail...);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  int streamRead() { return stream.read(); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
  Stream&       stream;
 | 
					  Stream&       stream;
 | 
				
			||||||
  GsmClient*    sockets[5];
 | 
					  GsmClient*    sockets[5];
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -247,9 +247,8 @@ public:
 | 
				
			|||||||
    if (waitResponse(GF(GSM_NL "+CCID:")) != 1) {
 | 
					    if (waitResponse(GF(GSM_NL "+CCID:")) != 1) {
 | 
				
			||||||
      return "";
 | 
					      return "";
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    String res = stream.readStringUntil('\n');
 | 
					    String res = streamReadUntil('\n');
 | 
				
			||||||
    waitResponse();
 | 
					    waitResponse();
 | 
				
			||||||
    res.trim();
 | 
					 | 
				
			||||||
    return res;
 | 
					    return res;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -258,9 +257,8 @@ public:
 | 
				
			|||||||
    if (waitResponse(GF(GSM_NL)) != 1) {
 | 
					    if (waitResponse(GF(GSM_NL)) != 1) {
 | 
				
			||||||
      return "";
 | 
					      return "";
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    String res = stream.readStringUntil('\n');
 | 
					    String res = streamReadUntil('\n');
 | 
				
			||||||
    waitResponse();
 | 
					    waitResponse();
 | 
				
			||||||
    res.trim();
 | 
					 | 
				
			||||||
    return res;
 | 
					    return res;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -269,38 +267,11 @@ public:
 | 
				
			|||||||
    if (waitResponse(GF(GSM_NL "+CSQ:")) != 1) {
 | 
					    if (waitResponse(GF(GSM_NL "+CSQ:")) != 1) {
 | 
				
			||||||
      return 99;
 | 
					      return 99;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    int res = stream.readStringUntil(',').toInt();
 | 
					    int res = streamReadUntil(',').toInt();
 | 
				
			||||||
    waitResponse();
 | 
					    waitResponse();
 | 
				
			||||||
    return res;
 | 
					    return res;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  bool callAnswer() {
 | 
					 | 
				
			||||||
    sendAT(GF("A"));
 | 
					 | 
				
			||||||
    return waitResponse() == 1;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  bool callNumber(const String& number) {
 | 
					 | 
				
			||||||
    sendAT(GF("D"), number);
 | 
					 | 
				
			||||||
    return waitResponse() == 1;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  bool callHangup(const String& number) {
 | 
					 | 
				
			||||||
    sendAT(GF("H"), number);
 | 
					 | 
				
			||||||
    return waitResponse() == 1;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  bool sendSMS(const String& number, const String& text) {
 | 
					 | 
				
			||||||
    sendAT(GF("+CMGF=1"));
 | 
					 | 
				
			||||||
    waitResponse();
 | 
					 | 
				
			||||||
    sendAT(GF("+CMGS=\""), number, GF("\""));
 | 
					 | 
				
			||||||
    if (waitResponse(GF(">")) != 1) {
 | 
					 | 
				
			||||||
      return false;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    stream.print(text);
 | 
					 | 
				
			||||||
    stream.write((char)0x1A);
 | 
					 | 
				
			||||||
    return waitResponse(60000L) == 1;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  SimStatus getSimStatus(unsigned long timeout = 10000L) {
 | 
					  SimStatus getSimStatus(unsigned long timeout = 10000L) {
 | 
				
			||||||
    for (unsigned long start = millis(); millis() - start < timeout; ) {
 | 
					    for (unsigned long start = millis(); millis() - start < timeout; ) {
 | 
				
			||||||
      sendAT(GF("+CPIN?"));
 | 
					      sendAT(GF("+CPIN?"));
 | 
				
			||||||
@@ -326,7 +297,7 @@ public:
 | 
				
			|||||||
      return REG_UNKNOWN;
 | 
					      return REG_UNKNOWN;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    streamSkipUntil(','); // Skip format (0)
 | 
					    streamSkipUntil(','); // Skip format (0)
 | 
				
			||||||
    int status = stream.readStringUntil('\n').toInt();
 | 
					    int status = streamReadUntil('\n').toInt();
 | 
				
			||||||
    waitResponse();
 | 
					    waitResponse();
 | 
				
			||||||
    return (RegStatus)status;
 | 
					    return (RegStatus)status;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -337,7 +308,7 @@ public:
 | 
				
			|||||||
      return "";
 | 
					      return "";
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    streamSkipUntil('"'); // Skip mode and format
 | 
					    streamSkipUntil('"'); // Skip mode and format
 | 
				
			||||||
    String res = stream.readStringUntil('"');
 | 
					    String res = streamReadUntil('"');
 | 
				
			||||||
    waitResponse();
 | 
					    waitResponse();
 | 
				
			||||||
    return res;
 | 
					    return res;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -347,8 +318,6 @@ public:
 | 
				
			|||||||
      RegStatus s = getRegistrationStatus();
 | 
					      RegStatus s = getRegistrationStatus();
 | 
				
			||||||
      if (s == REG_OK_HOME || s == REG_OK_ROAMING) {
 | 
					      if (s == REG_OK_HOME || s == REG_OK_ROAMING) {
 | 
				
			||||||
        return true;
 | 
					        return true;
 | 
				
			||||||
      } else if (s == REG_UNREGISTERED) {
 | 
					 | 
				
			||||||
        return false;
 | 
					 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      delay(1000);
 | 
					      delay(1000);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -400,6 +369,21 @@ public:
 | 
				
			|||||||
   * Phone Call functions
 | 
					   * Phone Call functions
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bool callAnswer() {
 | 
				
			||||||
 | 
					    sendAT(GF("A"));
 | 
				
			||||||
 | 
					    return waitResponse() == 1;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bool callNumber(const String& number) {
 | 
				
			||||||
 | 
					    sendAT(GF("D"), number);
 | 
				
			||||||
 | 
					    return waitResponse() == 1;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bool callHangup(const String& number) {
 | 
				
			||||||
 | 
					    sendAT(GF("H"), number);
 | 
				
			||||||
 | 
					    return waitResponse() == 1;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /*
 | 
					  /*
 | 
				
			||||||
   * Messaging functions
 | 
					   * Messaging functions
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
@@ -410,6 +394,18 @@ public:
 | 
				
			|||||||
  void sendSMS() {
 | 
					  void sendSMS() {
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bool sendSMS(const String& number, const String& text) {
 | 
				
			||||||
 | 
					    sendAT(GF("+CMGF=1"));
 | 
				
			||||||
 | 
					    waitResponse();
 | 
				
			||||||
 | 
					    sendAT(GF("+CMGS=\""), number, GF("\""));
 | 
				
			||||||
 | 
					    if (waitResponse(GF(">")) != 1) {
 | 
				
			||||||
 | 
					      return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    stream.print(text);
 | 
				
			||||||
 | 
					    stream.write((char)0x1A);
 | 
				
			||||||
 | 
					    return waitResponse(60000L) == 1;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /*
 | 
					  /*
 | 
				
			||||||
   * Location functions
 | 
					   * Location functions
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
@@ -420,90 +416,13 @@ public:
 | 
				
			|||||||
   * Battery functions
 | 
					   * Battery functions
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					  /* Public Utilities */
 | 
				
			||||||
  String dnsIpQuery(const char* host) {
 | 
					 | 
				
			||||||
    sendAT(GF("+DNS=\""), host, GF("\""));
 | 
					 | 
				
			||||||
    if (waitResponse(10000L, GF(GSM_NL "+DNS:")) != 1) {
 | 
					 | 
				
			||||||
      return "";
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    String res = stream.readStringUntil('\n');
 | 
					 | 
				
			||||||
    waitResponse(GF("+DNS:OK" GSM_NL));
 | 
					 | 
				
			||||||
    res.trim();
 | 
					 | 
				
			||||||
    return res;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  int modemConnect(const char* host, uint16_t port, uint8_t mux) {
 | 
					 | 
				
			||||||
    int rsp = 0;
 | 
					 | 
				
			||||||
    for (int i=0; i<3; i++) {
 | 
					 | 
				
			||||||
      String ip = dnsIpQuery(host);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      sendAT(GF("+TCPSETUP="), mux, GF(","), ip, GF(","), port);
 | 
					 | 
				
			||||||
      int rsp = waitResponse(75000L,
 | 
					 | 
				
			||||||
                            GF(",OK" GSM_NL),
 | 
					 | 
				
			||||||
                            GF(",FAIL" GSM_NL),
 | 
					 | 
				
			||||||
                            GF("+TCPSETUP:Error" GSM_NL));
 | 
					 | 
				
			||||||
      if (1 == rsp) {
 | 
					 | 
				
			||||||
        return true;
 | 
					 | 
				
			||||||
      } else if (3 == rsp) {
 | 
					 | 
				
			||||||
        sendAT(GF("+TCPCLOSE="), mux);
 | 
					 | 
				
			||||||
        waitResponse();
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      delay(1000);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return false;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  int modemSend(const void* buff, size_t len, uint8_t mux) {
 | 
					 | 
				
			||||||
    sendAT(GF("+TCPSEND="), mux, ',', len);
 | 
					 | 
				
			||||||
    if (waitResponse(GF(">")) != 1) {
 | 
					 | 
				
			||||||
      return 0;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    stream.write((uint8_t*)buff, len);
 | 
					 | 
				
			||||||
    stream.write((char)0x0D);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (waitResponse(30000L, GF(GSM_NL "+TCPSEND:")) != 1) {
 | 
					 | 
				
			||||||
      return 0;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    stream.readStringUntil('\n');
 | 
					 | 
				
			||||||
    return len;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  bool modemGetConnected(uint8_t mux) {
 | 
					 | 
				
			||||||
    sendAT(GF("+CIPSTATUS="), mux);
 | 
					 | 
				
			||||||
    int res = waitResponse(GF(",\"CONNECTED\""), GF(",\"CLOSED\""), GF(",\"CLOSING\""), GF(",\"INITIAL\""));
 | 
					 | 
				
			||||||
    waitResponse();
 | 
					 | 
				
			||||||
    return 1 == res;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /* Utilities */
 | 
					 | 
				
			||||||
  template<typename T>
 | 
					 | 
				
			||||||
  void streamWrite(T last) {
 | 
					 | 
				
			||||||
    stream.print(last);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  template<typename T, typename... Args>
 | 
					 | 
				
			||||||
  void streamWrite(T head, Args... tail) {
 | 
					 | 
				
			||||||
    stream.print(head);
 | 
					 | 
				
			||||||
    streamWrite(tail...);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  int streamRead() { return stream.read(); }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  bool streamSkipUntil(char c) { //TODO: timeout
 | 
					 | 
				
			||||||
    while (true) {
 | 
					 | 
				
			||||||
      while (!stream.available()) {}
 | 
					 | 
				
			||||||
      if (stream.read() == c)
 | 
					 | 
				
			||||||
        return true;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return false;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  template<typename... Args>
 | 
					  template<typename... Args>
 | 
				
			||||||
  void sendAT(Args... cmd) {
 | 
					  void sendAT(Args... cmd) {
 | 
				
			||||||
    streamWrite("AT", cmd..., GSM_NL);
 | 
					    streamWrite("AT", cmd..., GSM_NL);
 | 
				
			||||||
    stream.flush();
 | 
					    stream.flush();
 | 
				
			||||||
    TINY_GSM_YIELD();
 | 
					    TINY_GSM_YIELD();
 | 
				
			||||||
    //DBG("### AT:", cmd...);
 | 
					    DBG(GSM_NL, ">>> AT:", cmd...);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // TODO: Optimize this!
 | 
					  // TODO: Optimize this!
 | 
				
			||||||
@@ -542,8 +461,8 @@ private:
 | 
				
			|||||||
          index = 5;
 | 
					          index = 5;
 | 
				
			||||||
          goto finish;
 | 
					          goto finish;
 | 
				
			||||||
        } else if (data.endsWith(GF("+TCPRECV:"))) {
 | 
					        } else if (data.endsWith(GF("+TCPRECV:"))) {
 | 
				
			||||||
          int mux = stream.readStringUntil(',').toInt();
 | 
					          int mux = streamReadUntil(',').toInt();
 | 
				
			||||||
          int len = stream.readStringUntil(',').toInt();
 | 
					          int len = streamReadUntil(',').toInt();
 | 
				
			||||||
          if (len > sockets[mux]->rx.free()) {
 | 
					          if (len > sockets[mux]->rx.free()) {
 | 
				
			||||||
            DBG("### Buffer overflow: ", len, "->", sockets[mux]->rx.free());
 | 
					            DBG("### Buffer overflow: ", len, "->", sockets[mux]->rx.free());
 | 
				
			||||||
          } else {
 | 
					          } else {
 | 
				
			||||||
@@ -556,14 +475,14 @@ private:
 | 
				
			|||||||
          data = "";
 | 
					          data = "";
 | 
				
			||||||
          return index;
 | 
					          return index;
 | 
				
			||||||
        } else if (data.endsWith(GF("+TCPCLOSE:"))) {
 | 
					        } else if (data.endsWith(GF("+TCPCLOSE:"))) {
 | 
				
			||||||
          int mux = stream.readStringUntil(',').toInt();
 | 
					          int mux = streamReadUntil(',').toInt();
 | 
				
			||||||
          stream.readStringUntil('\n');
 | 
					          streamReadUntil('\n');
 | 
				
			||||||
          sockets[mux]->sock_connected = false;
 | 
					          sockets[mux]->sock_connected = false;
 | 
				
			||||||
          data = "";
 | 
					          data = "";
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    } while (millis() - startMillis < timeout);
 | 
					    } while (millis() - startMillis < timeout);
 | 
				
			||||||
finish:
 | 
					  finish:
 | 
				
			||||||
    if (!index) {
 | 
					    if (!index) {
 | 
				
			||||||
      data.trim();
 | 
					      data.trim();
 | 
				
			||||||
      if (data.length()) {
 | 
					      if (data.length()) {
 | 
				
			||||||
@@ -571,6 +490,15 @@ finish:
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
      data = "";
 | 
					      data = "";
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    else {
 | 
				
			||||||
 | 
					      data.trim();
 | 
				
			||||||
 | 
					      data.replace(GSM_NL GSM_NL, GSM_NL);
 | 
				
			||||||
 | 
					      data.replace(GSM_NL, GSM_NL "    ");
 | 
				
			||||||
 | 
					      if (data.length()) {
 | 
				
			||||||
 | 
					        DBG(GSM_NL, "<<< ", data);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      data = "";
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    return index;
 | 
					    return index;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -588,6 +516,95 @@ finish:
 | 
				
			|||||||
    return waitResponse(1000, r1, r2, r3, r4, r5);
 | 
					    return waitResponse(1000, r1, r2, r3, r4, r5);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					  String dnsIpQuery(const char* host) {
 | 
				
			||||||
 | 
					   sendAT(GF("+DNS=\""), host, GF("\""));
 | 
				
			||||||
 | 
					   if (waitResponse(10000L, GF(GSM_NL "+DNS:")) != 1) {
 | 
				
			||||||
 | 
					     return "";
 | 
				
			||||||
 | 
					   }
 | 
				
			||||||
 | 
					   String res = streamReadUntil('\n');
 | 
				
			||||||
 | 
					   waitResponse(GF("+DNS:OK" GSM_NL));
 | 
				
			||||||
 | 
					   res.trim();
 | 
				
			||||||
 | 
					   return res;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  int modemConnect(const char* host, uint16_t port, uint8_t mux) {
 | 
				
			||||||
 | 
					    int rsp = 0;
 | 
				
			||||||
 | 
					    for (int i=0; i<3; i++) {
 | 
				
			||||||
 | 
					      String ip = dnsIpQuery(host);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      sendAT(GF("+TCPSETUP="), mux, GF(","), ip, GF(","), port);
 | 
				
			||||||
 | 
					      int rsp = waitResponse(75000L,
 | 
				
			||||||
 | 
					                            GF(",OK" GSM_NL),
 | 
				
			||||||
 | 
					                            GF(",FAIL" GSM_NL),
 | 
				
			||||||
 | 
					                            GF("+TCPSETUP:Error" GSM_NL));
 | 
				
			||||||
 | 
					      if (1 == rsp) {
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					      } else if (3 == rsp) {
 | 
				
			||||||
 | 
					        sendAT(GF("+TCPCLOSE="), mux);
 | 
				
			||||||
 | 
					        waitResponse();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      delay(1000);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return false;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  int modemSend(const void* buff, size_t len, uint8_t mux) {
 | 
				
			||||||
 | 
					    sendAT(GF("+TCPSEND="), mux, ',', len);
 | 
				
			||||||
 | 
					    if (waitResponse(GF(">")) != 1) {
 | 
				
			||||||
 | 
					      return 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    stream.write((uint8_t*)buff, len);
 | 
				
			||||||
 | 
					    stream.write((char)0x0D);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (waitResponse(30000L, GF(GSM_NL "+TCPSEND:")) != 1) {
 | 
				
			||||||
 | 
					      return 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    streamReadUntil('\n');
 | 
				
			||||||
 | 
					    return len;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bool modemGetConnected(uint8_t mux) {
 | 
				
			||||||
 | 
					    sendAT(GF("+CIPSTATUS="), mux);
 | 
				
			||||||
 | 
					    int res = waitResponse(GF(",\"CONNECTED\""), GF(",\"CLOSED\""), GF(",\"CLOSING\""), GF(",\"INITIAL\""));
 | 
				
			||||||
 | 
					    waitResponse();
 | 
				
			||||||
 | 
					    return 1 == res;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* Private Utilities */
 | 
				
			||||||
 | 
					  template<typename T>
 | 
				
			||||||
 | 
					  void streamWrite(T last) {
 | 
				
			||||||
 | 
					    stream.print(last);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  template<typename T, typename... Args>
 | 
				
			||||||
 | 
					  void streamWrite(T head, Args... tail) {
 | 
				
			||||||
 | 
					    stream.print(head);
 | 
				
			||||||
 | 
					    streamWrite(tail...);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  int streamRead() { return stream.read(); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  String streamReadUntil(char c) {
 | 
				
			||||||
 | 
					    String return_string = stream.readStringUntil(c);
 | 
				
			||||||
 | 
					    return_string.trim();
 | 
				
			||||||
 | 
					    if (String(c) == GSM_NL || String(c) == "\n"){
 | 
				
			||||||
 | 
					      DBG(return_string, c, "    ");
 | 
				
			||||||
 | 
					    } else DBG(return_string, c);
 | 
				
			||||||
 | 
					    return return_string;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bool streamSkipUntil(char c) { //TODO: timeout
 | 
				
			||||||
 | 
					    String skipped = stream.readStringUntil(c);
 | 
				
			||||||
 | 
					    skipped.trim();
 | 
				
			||||||
 | 
					    if (skipped.length()) {
 | 
				
			||||||
 | 
					      if (String(c) == GSM_NL || String(c) == "\n"){
 | 
				
			||||||
 | 
					        DBG(skipped, c, "    ");
 | 
				
			||||||
 | 
					      } else DBG(skipped, c);
 | 
				
			||||||
 | 
					      return true;
 | 
				
			||||||
 | 
					    } else return false;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
  Stream&       stream;
 | 
					  Stream&       stream;
 | 
				
			||||||
  GsmClient*    sockets[2];
 | 
					  GsmClient*    sockets[2];
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -187,7 +187,7 @@ public:
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  bool autoBaud(unsigned long timeout = 10000L) {
 | 
					  bool autoBaud(unsigned long timeout = 10000L) {
 | 
				
			||||||
    streamWrite(GF("AAAAAAAAAAAA"));  // some extra A's to help detect the baud rate
 | 
					    streamWrite(GF("AAAAAAAAAAAAA"));  // extra A's to help detect the baud rate
 | 
				
			||||||
    for (unsigned long start = millis(); millis() - start < timeout; ) {
 | 
					    for (unsigned long start = millis(); millis() - start < timeout; ) {
 | 
				
			||||||
      sendAT(GF(""));
 | 
					      sendAT(GF(""));
 | 
				
			||||||
      if (waitResponse(200) == 1) {
 | 
					      if (waitResponse(200) == 1) {
 | 
				
			||||||
@@ -279,79 +279,11 @@ public:
 | 
				
			|||||||
    return res;
 | 
					    return res;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  String getGsmLocation() {
 | 
					 | 
				
			||||||
    sendAT(GF("+CIPGSMLOC=1,1"));
 | 
					 | 
				
			||||||
    if (waitResponse(GF(GSM_NL "+CIPGSMLOC:")) != 1) {
 | 
					 | 
				
			||||||
      return "";
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    String res = streamReadUntil('\n');
 | 
					 | 
				
			||||||
    waitResponse();
 | 
					 | 
				
			||||||
    return res;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  bool setGsmBusy(bool busy = true) {
 | 
					 | 
				
			||||||
    sendAT(GF("+GSMBUSY="), busy ? 1 : 0);
 | 
					 | 
				
			||||||
    return waitResponse() == 1;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  bool callAnswer() {
 | 
					 | 
				
			||||||
    sendAT(GF("A"));
 | 
					 | 
				
			||||||
    return waitResponse() == 1;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  bool callNumber(const String& number) {
 | 
					 | 
				
			||||||
    sendAT(GF("D"), number);
 | 
					 | 
				
			||||||
    return waitResponse() == 1;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  bool callHangup(const String& number) {
 | 
					 | 
				
			||||||
    sendAT(GF("H"), number);
 | 
					 | 
				
			||||||
    return waitResponse() == 1;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  bool sendSMS(const String& number, const String& text) {
 | 
					 | 
				
			||||||
    sendAT(GF("+CMGF=1"));
 | 
					 | 
				
			||||||
    waitResponse();
 | 
					 | 
				
			||||||
    sendAT(GF("+CMGS=\""), number, GF("\""));
 | 
					 | 
				
			||||||
    if (waitResponse(GF(">")) != 1) {
 | 
					 | 
				
			||||||
      return false;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    stream.print(text);
 | 
					 | 
				
			||||||
    stream.write((char)0x1A);
 | 
					 | 
				
			||||||
    return waitResponse(60000L) == 1;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  bool sendSMS_UTF16(const String& number, const void* text, size_t len) {
 | 
					 | 
				
			||||||
    sendAT(GF("+CMGF=1"));
 | 
					 | 
				
			||||||
    waitResponse();
 | 
					 | 
				
			||||||
    sendAT(GF("+CSCS=\"HEX\""));
 | 
					 | 
				
			||||||
    waitResponse();
 | 
					 | 
				
			||||||
    sendAT(GF("+CSMP=17,167,0,8"));
 | 
					 | 
				
			||||||
    waitResponse();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    sendAT(GF("+CMGS=\""), number, GF("\""));
 | 
					 | 
				
			||||||
    if (waitResponse(GF(">")) != 1) {
 | 
					 | 
				
			||||||
      return false;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    uint16_t* t = (uint16_t*)text;
 | 
					 | 
				
			||||||
    for (size_t i=0; i<len; i++) {
 | 
					 | 
				
			||||||
      uint8_t c = t[i] >> 8;
 | 
					 | 
				
			||||||
      if (c < 0x10) { stream.print('0'); }
 | 
					 | 
				
			||||||
      stream.print(c, HEX);
 | 
					 | 
				
			||||||
      c = t[i] & 0xFF;
 | 
					 | 
				
			||||||
      if (c < 0x10) { stream.print('0'); }
 | 
					 | 
				
			||||||
      stream.print(c, HEX);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    stream.write((char)0x1A);
 | 
					 | 
				
			||||||
    return waitResponse(60000L) == 1;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  SimStatus getSimStatus(unsigned long timeout = 10000L) {
 | 
					  SimStatus getSimStatus(unsigned long timeout = 10000L) {
 | 
				
			||||||
    for (unsigned long start = millis(); millis() - start < timeout; ) {
 | 
					    for (unsigned long start = millis(); millis() - start < timeout; ) {
 | 
				
			||||||
      sendAT(GF("+CPIN?"));
 | 
					      sendAT(GF("+CPIN?"));
 | 
				
			||||||
      if (waitResponse(GF(GSM_NL "+CPIN:")) != 1) {
 | 
					      if (waitResponse(GF(GSM_NL "+CPIN:")) != 1) {
 | 
				
			||||||
        delay(250);
 | 
					        delay(1000);
 | 
				
			||||||
        continue;
 | 
					        continue;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      int status = waitResponse(GF("READY"), GF("SIM PIN"), GF("SIM PUK"), GF("NOT INSERTED"));
 | 
					      int status = waitResponse(GF("READY"), GF("SIM PIN"), GF("SIM PUK"), GF("NOT INSERTED"));
 | 
				
			||||||
@@ -389,16 +321,14 @@ public:
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  bool waitForNetwork(unsigned long timeout = 60000L) {
 | 
					  bool waitForNetwork(unsigned long timeout = 60000L) {
 | 
				
			||||||
    unsigned long start = millis();
 | 
					    for (unsigned long start = millis(); millis() - start < timeout; ) {
 | 
				
			||||||
    bool is_registered = false;
 | 
					 | 
				
			||||||
    while (millis() - start < timeout && is_registered == false){
 | 
					 | 
				
			||||||
      RegStatus s = getRegistrationStatus();
 | 
					      RegStatus s = getRegistrationStatus();
 | 
				
			||||||
      if (s == REG_OK_HOME || s == REG_OK_ROAMING) {
 | 
					      if (s == REG_OK_HOME || s == REG_OK_ROAMING) {
 | 
				
			||||||
        is_registered = true;
 | 
					        return true;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      delay(1000);
 | 
					      delay(1000);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return is_registered;
 | 
					    return false;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /*
 | 
					  /*
 | 
				
			||||||
@@ -491,6 +421,26 @@ public:
 | 
				
			|||||||
   * Phone Call functions
 | 
					   * Phone Call functions
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bool setGsmBusy(bool busy = true) {
 | 
				
			||||||
 | 
					    sendAT(GF("+GSMBUSY="), busy ? 1 : 0);
 | 
				
			||||||
 | 
					    return waitResponse() == 1;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bool callAnswer() {
 | 
				
			||||||
 | 
					    sendAT(GF("A"));
 | 
				
			||||||
 | 
					    return waitResponse() == 1;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bool callNumber(const String& number) {
 | 
				
			||||||
 | 
					    sendAT(GF("D"), number);
 | 
				
			||||||
 | 
					    return waitResponse() == 1;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bool callHangup(const String& number) {
 | 
				
			||||||
 | 
					    sendAT(GF("H"), number);
 | 
				
			||||||
 | 
					    return waitResponse() == 1;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /*
 | 
					  /*
 | 
				
			||||||
   * Messaging functions
 | 
					   * Messaging functions
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
@@ -501,12 +451,61 @@ public:
 | 
				
			|||||||
  void sendSMS() {
 | 
					  void sendSMS() {
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bool sendSMS(const String& number, const String& text) {
 | 
				
			||||||
 | 
					    sendAT(GF("+CMGF=1"));
 | 
				
			||||||
 | 
					    waitResponse();
 | 
				
			||||||
 | 
					    sendAT(GF("+CMGS=\""), number, GF("\""));
 | 
				
			||||||
 | 
					    if (waitResponse(GF(">")) != 1) {
 | 
				
			||||||
 | 
					      return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    stream.print(text);
 | 
				
			||||||
 | 
					    stream.write((char)0x1A);
 | 
				
			||||||
 | 
					    return waitResponse(60000L) == 1;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bool sendSMS_UTF16(const String& number, const void* text, size_t len) {
 | 
				
			||||||
 | 
					    sendAT(GF("+CMGF=1"));
 | 
				
			||||||
 | 
					    waitResponse();
 | 
				
			||||||
 | 
					    sendAT(GF("+CSCS=\"HEX\""));
 | 
				
			||||||
 | 
					    waitResponse();
 | 
				
			||||||
 | 
					    sendAT(GF("+CSMP=17,167,0,8"));
 | 
				
			||||||
 | 
					    waitResponse();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    sendAT(GF("+CMGS=\""), number, GF("\""));
 | 
				
			||||||
 | 
					    if (waitResponse(GF(">")) != 1) {
 | 
				
			||||||
 | 
					      return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    uint16_t* t = (uint16_t*)text;
 | 
				
			||||||
 | 
					    for (size_t i=0; i<len; i++) {
 | 
				
			||||||
 | 
					      uint8_t c = t[i] >> 8;
 | 
				
			||||||
 | 
					      if (c < 0x10) { stream.print('0'); }
 | 
				
			||||||
 | 
					      stream.print(c, HEX);
 | 
				
			||||||
 | 
					      c = t[i] & 0xFF;
 | 
				
			||||||
 | 
					      if (c < 0x10) { stream.print('0'); }
 | 
				
			||||||
 | 
					      stream.print(c, HEX);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    stream.write((char)0x1A);
 | 
				
			||||||
 | 
					    return waitResponse(60000L) == 1;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /*
 | 
					  /*
 | 
				
			||||||
   * Location functions
 | 
					   * Location functions
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  void getLocation() {
 | 
					  void getLocation() {
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  String getGsmLocation() {
 | 
				
			||||||
 | 
					    sendAT(GF("+CIPGSMLOC=1,1"));
 | 
				
			||||||
 | 
					    if (waitResponse(GF(GSM_NL "+CIPGSMLOC:")) != 1) {
 | 
				
			||||||
 | 
					      return "";
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    String res = streamReadUntil('\n');
 | 
				
			||||||
 | 
					    waitResponse();
 | 
				
			||||||
 | 
					    return res;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /*
 | 
					  /*
 | 
				
			||||||
   * Battery functions
 | 
					   * Battery functions
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
@@ -524,120 +523,7 @@ public:
 | 
				
			|||||||
    return res;
 | 
					    return res;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					  /* Public Utilities */
 | 
				
			||||||
  int modemConnect(const char* host, uint16_t port, uint8_t mux) {
 | 
					 | 
				
			||||||
    sendAT(GF("+CIPSTART="), mux, ',', GF("\"TCP"), GF("\",\""), host, GF("\","), port);
 | 
					 | 
				
			||||||
    int rsp = waitResponse(75000L,
 | 
					 | 
				
			||||||
                           GF("CONNECT OK" GSM_NL),
 | 
					 | 
				
			||||||
                           GF("CONNECT FAIL" GSM_NL),
 | 
					 | 
				
			||||||
                           GF("ALREADY CONNECT" GSM_NL));
 | 
					 | 
				
			||||||
    return (1 == rsp);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  int modemSend(const void* buff, size_t len, uint8_t mux) {
 | 
					 | 
				
			||||||
    sendAT(GF("+CIPSEND="), mux, ',', len);
 | 
					 | 
				
			||||||
    if (waitResponse(GF(">")) != 1) {
 | 
					 | 
				
			||||||
      return -1;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    stream.write((uint8_t*)buff, len);
 | 
					 | 
				
			||||||
    stream.flush();
 | 
					 | 
				
			||||||
    if (waitResponse(GF(GSM_NL "DATA ACCEPT:")) != 1) {
 | 
					 | 
				
			||||||
      return -1;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    streamSkipUntil(','); // Skip mux
 | 
					 | 
				
			||||||
    return streamReadUntil('\n').toInt();
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  size_t modemRead(size_t size, uint8_t mux) {
 | 
					 | 
				
			||||||
#ifdef TINY_GSM_USE_HEX
 | 
					 | 
				
			||||||
    sendAT(GF("+CIPRXGET=3,"), mux, ',', size);
 | 
					 | 
				
			||||||
    if (waitResponse(GF("+CIPRXGET:")) != 1) {
 | 
					 | 
				
			||||||
      return 0;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
    sendAT(GF("+CIPRXGET=2,"), mux, ',', size);
 | 
					 | 
				
			||||||
    if (waitResponse(GF("+CIPRXGET:")) != 1) {
 | 
					 | 
				
			||||||
      return 0;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
    streamSkipUntil(','); // Skip mode 2/3
 | 
					 | 
				
			||||||
    streamSkipUntil(','); // Skip mux
 | 
					 | 
				
			||||||
    size_t len = streamReadUntil(',').toInt();
 | 
					 | 
				
			||||||
    sockets[mux]->sock_available = streamReadUntil('\n').toInt();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for (size_t i=0; i<len; i++) {
 | 
					 | 
				
			||||||
#ifdef TINY_GSM_USE_HEX
 | 
					 | 
				
			||||||
      while (stream.available() < 2) {}
 | 
					 | 
				
			||||||
      char buf[4] = { 0, };
 | 
					 | 
				
			||||||
      buf[0] = streamRead();
 | 
					 | 
				
			||||||
      buf[1] = streamRead();
 | 
					 | 
				
			||||||
      char c = strtol(buf, NULL, 16);
 | 
					 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
      while (!stream.available()) {}
 | 
					 | 
				
			||||||
      char c = streamRead();  // DBG(c);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
      sockets[mux]->rx.put(c);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    waitResponse();
 | 
					 | 
				
			||||||
    return len;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  size_t modemGetAvailable(uint8_t mux) {
 | 
					 | 
				
			||||||
    sendAT(GF("+CIPRXGET=4,"), mux);
 | 
					 | 
				
			||||||
    size_t result = 0;
 | 
					 | 
				
			||||||
    if (waitResponse(GF("+CIPRXGET:")) == 1) {
 | 
					 | 
				
			||||||
      streamSkipUntil(','); // Skip mode 4
 | 
					 | 
				
			||||||
      streamSkipUntil(','); // Skip mux
 | 
					 | 
				
			||||||
      result = streamReadUntil('\n').toInt();
 | 
					 | 
				
			||||||
      waitResponse();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (!result) {
 | 
					 | 
				
			||||||
      sockets[mux]->sock_connected = modemGetConnected(mux);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return result;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  bool modemGetConnected(uint8_t mux) {
 | 
					 | 
				
			||||||
    sendAT(GF("+CIPSTATUS="), mux);
 | 
					 | 
				
			||||||
    int res = waitResponse(GF(",\"CONNECTED\""), GF(",\"CLOSED\""), GF(",\"CLOSING\""), GF(",\"INITIAL\""));
 | 
					 | 
				
			||||||
    waitResponse();
 | 
					 | 
				
			||||||
    return 1 == res;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /* Utilities */
 | 
					 | 
				
			||||||
  template<typename T>
 | 
					 | 
				
			||||||
  void streamWrite(T last) {
 | 
					 | 
				
			||||||
    stream.print(last);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  template<typename T, typename... Args>
 | 
					 | 
				
			||||||
  void streamWrite(T head, Args... tail) {
 | 
					 | 
				
			||||||
    stream.print(head);
 | 
					 | 
				
			||||||
    streamWrite(tail...);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  int streamRead() { return stream.read(); }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  String streamReadUntil(char c) {
 | 
					 | 
				
			||||||
    String return_string = stream.readStringUntil(c);
 | 
					 | 
				
			||||||
    return_string.trim();
 | 
					 | 
				
			||||||
    if (String(c) == GSM_NL || String(c) == "\n"){
 | 
					 | 
				
			||||||
      DBG(return_string, c, "    ");
 | 
					 | 
				
			||||||
    } else DBG(return_string, c);
 | 
					 | 
				
			||||||
    return return_string;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  bool streamSkipUntil(char c) { //TODO: timeout
 | 
					 | 
				
			||||||
    String skipped = stream.readStringUntil(c);
 | 
					 | 
				
			||||||
    skipped.trim();
 | 
					 | 
				
			||||||
    if (skipped.length()) {
 | 
					 | 
				
			||||||
      if (String(c) == GSM_NL || String(c) == "\n"){
 | 
					 | 
				
			||||||
        DBG(skipped, c, "    ");
 | 
					 | 
				
			||||||
      } else DBG(skipped, c);
 | 
					 | 
				
			||||||
      return true;
 | 
					 | 
				
			||||||
    } else return false;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  template<typename... Args>
 | 
					  template<typename... Args>
 | 
				
			||||||
  void sendAT(Args... cmd) {
 | 
					  void sendAT(Args... cmd) {
 | 
				
			||||||
    streamWrite("AT", cmd..., GSM_NL);
 | 
					    streamWrite("AT", cmd..., GSM_NL);
 | 
				
			||||||
@@ -740,6 +626,120 @@ private:
 | 
				
			|||||||
    return waitResponse(1000, r1, r2, r3, r4, r5);
 | 
					    return waitResponse(1000, r1, r2, r3, r4, r5);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					  int modemConnect(const char* host, uint16_t port, uint8_t mux) {
 | 
				
			||||||
 | 
					    sendAT(GF("+CIPSTART="), mux, ',', GF("\"TCP"), GF("\",\""), host, GF("\","), port);
 | 
				
			||||||
 | 
					    int rsp = waitResponse(75000L,
 | 
				
			||||||
 | 
					                           GF("CONNECT OK" GSM_NL),
 | 
				
			||||||
 | 
					                           GF("CONNECT FAIL" GSM_NL),
 | 
				
			||||||
 | 
					                           GF("ALREADY CONNECT" GSM_NL));
 | 
				
			||||||
 | 
					    return (1 == rsp);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  int modemSend(const void* buff, size_t len, uint8_t mux) {
 | 
				
			||||||
 | 
					    sendAT(GF("+CIPSEND="), mux, ',', len);
 | 
				
			||||||
 | 
					    if (waitResponse(GF(">")) != 1) {
 | 
				
			||||||
 | 
					      return -1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    stream.write((uint8_t*)buff, len);
 | 
				
			||||||
 | 
					    stream.flush();
 | 
				
			||||||
 | 
					    if (waitResponse(GF(GSM_NL "DATA ACCEPT:")) != 1) {
 | 
				
			||||||
 | 
					      return -1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    streamSkipUntil(','); // Skip mux
 | 
				
			||||||
 | 
					    return streamReadUntil('\n').toInt();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  size_t modemRead(size_t size, uint8_t mux) {
 | 
				
			||||||
 | 
					#ifdef TINY_GSM_USE_HEX
 | 
				
			||||||
 | 
					    sendAT(GF("+CIPRXGET=3,"), mux, ',', size);
 | 
				
			||||||
 | 
					    if (waitResponse(GF("+CIPRXGET:")) != 1) {
 | 
				
			||||||
 | 
					      return 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					    sendAT(GF("+CIPRXGET=2,"), mux, ',', size);
 | 
				
			||||||
 | 
					    if (waitResponse(GF("+CIPRXGET:")) != 1) {
 | 
				
			||||||
 | 
					      return 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					    streamSkipUntil(','); // Skip mode 2/3
 | 
				
			||||||
 | 
					    streamSkipUntil(','); // Skip mux
 | 
				
			||||||
 | 
					    size_t len = streamReadUntil(',').toInt();
 | 
				
			||||||
 | 
					    sockets[mux]->sock_available = streamReadUntil('\n').toInt();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (size_t i=0; i<len; i++) {
 | 
				
			||||||
 | 
					#ifdef TINY_GSM_USE_HEX
 | 
				
			||||||
 | 
					      while (stream.available() < 2) {}
 | 
				
			||||||
 | 
					      char buf[4] = { 0, };
 | 
				
			||||||
 | 
					      buf[0] = streamRead();
 | 
				
			||||||
 | 
					      buf[1] = streamRead();
 | 
				
			||||||
 | 
					      char c = strtol(buf, NULL, 16);
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					      while (!stream.available()) {}
 | 
				
			||||||
 | 
					      char c = streamRead();  // DBG(c);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					      sockets[mux]->rx.put(c);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    waitResponse();
 | 
				
			||||||
 | 
					    return len;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  size_t modemGetAvailable(uint8_t mux) {
 | 
				
			||||||
 | 
					    sendAT(GF("+CIPRXGET=4,"), mux);
 | 
				
			||||||
 | 
					    size_t result = 0;
 | 
				
			||||||
 | 
					    if (waitResponse(GF("+CIPRXGET:")) == 1) {
 | 
				
			||||||
 | 
					      streamSkipUntil(','); // Skip mode 4
 | 
				
			||||||
 | 
					      streamSkipUntil(','); // Skip mux
 | 
				
			||||||
 | 
					      result = streamReadUntil('\n').toInt();
 | 
				
			||||||
 | 
					      waitResponse();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (!result) {
 | 
				
			||||||
 | 
					      sockets[mux]->sock_connected = modemGetConnected(mux);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return result;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bool modemGetConnected(uint8_t mux) {
 | 
				
			||||||
 | 
					    sendAT(GF("+CIPSTATUS="), mux);
 | 
				
			||||||
 | 
					    int res = waitResponse(GF(",\"CONNECTED\""), GF(",\"CLOSED\""), GF(",\"CLOSING\""), GF(",\"INITIAL\""));
 | 
				
			||||||
 | 
					    waitResponse();
 | 
				
			||||||
 | 
					    return 1 == res;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* Private Utilities */
 | 
				
			||||||
 | 
					  template<typename T>
 | 
				
			||||||
 | 
					  void streamWrite(T last) {
 | 
				
			||||||
 | 
					    stream.print(last);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  template<typename T, typename... Args>
 | 
				
			||||||
 | 
					  void streamWrite(T head, Args... tail) {
 | 
				
			||||||
 | 
					    stream.print(head);
 | 
				
			||||||
 | 
					    streamWrite(tail...);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  int streamRead() { return stream.read(); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  String streamReadUntil(char c) {
 | 
				
			||||||
 | 
					    String return_string = stream.readStringUntil(c);
 | 
				
			||||||
 | 
					    return_string.trim();
 | 
				
			||||||
 | 
					    if (String(c) == GSM_NL || String(c) == "\n"){
 | 
				
			||||||
 | 
					      DBG(return_string, c, "    ");
 | 
				
			||||||
 | 
					    } else DBG(return_string, c);
 | 
				
			||||||
 | 
					    return return_string;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bool streamSkipUntil(char c) { //TODO: timeout
 | 
				
			||||||
 | 
					    String skipped = stream.readStringUntil(c);
 | 
				
			||||||
 | 
					    skipped.trim();
 | 
				
			||||||
 | 
					    if (skipped.length()) {
 | 
				
			||||||
 | 
					      if (String(c) == GSM_NL || String(c) == "\n"){
 | 
				
			||||||
 | 
					        DBG(skipped, c, "    ");
 | 
				
			||||||
 | 
					      } else DBG(skipped, c);
 | 
				
			||||||
 | 
					      return true;
 | 
				
			||||||
 | 
					    } else return false;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
  Stream&       stream;
 | 
					  Stream&       stream;
 | 
				
			||||||
  GsmClient*    sockets[5];
 | 
					  GsmClient*    sockets[5];
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  "name": "TinyGSM",
 | 
					  "name": "TinyGSM",
 | 
				
			||||||
  "version": "0.1.7",
 | 
					  "version": "0.1.8",
 | 
				
			||||||
  "description": "A small Arduino library for GPRS modules, that just works. Includes examples for Blynk, MQTT, File Download, and Web Client. Supports GSM modules with AT command interface: SIM800, SIM800A, SIM800C, SIM800L, SIM800H, SIM808, SIM868, SIM900, SIM900A, SIM900D, SIM908, SIM968",
 | 
					  "description": "A small Arduino library for GPRS modules, that just works. Includes examples for Blynk, MQTT, File Download, and Web Client. Supports GSM modules with AT command interface: SIM800, SIM800A, SIM800C, SIM800L, SIM800H, SIM808, SIM868, SIM900, SIM900A, SIM900D, SIM908, SIM968",
 | 
				
			||||||
  "keywords": "GSM, AT commands, AT, SIM800, SIM900, A6, A7, M590, ESP8266, SIM800A, SIM800C, SIM800L, SIM800H, SIM808, SIM868, SIM900A, SIM900D, SIM908, SIM968",
 | 
					  "keywords": "GSM, AT commands, AT, SIM800, SIM900, A6, A7, M590, ESP8266, SIM800A, SIM800C, SIM800L, SIM800H, SIM808, SIM868, SIM900A, SIM900D, SIM908, SIM968",
 | 
				
			||||||
  "authors":
 | 
					  "authors":
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,5 @@
 | 
				
			|||||||
name=TinyGSM
 | 
					name=TinyGSM
 | 
				
			||||||
version=0.1.7
 | 
					version=0.1.8
 | 
				
			||||||
author=Volodymyr Shymanskyy
 | 
					author=Volodymyr Shymanskyy
 | 
				
			||||||
maintainer=Volodymyr Shymanskyy
 | 
					maintainer=Volodymyr Shymanskyy
 | 
				
			||||||
sentence=A small Arduino library for GPRS modules, that just works.
 | 
					sentence=A small Arduino library for GPRS modules, that just works.
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user