mirror of
				https://github.com/KevinMidboe/TinyGSM.git
				synced 2025-10-29 18:00:18 +00:00 
			
		
		
		
	Doing a better job of detecting XBee socket state
This commit is contained in:
		@@ -120,6 +120,8 @@ public:
 | 
			
		||||
 | 
			
		||||
  virtual void stop(uint32_t maxWaitMs) {
 | 
			
		||||
    at->streamClear();  // Empty anything in the buffer
 | 
			
		||||
    // empty the saved currently-in-use destination address
 | 
			
		||||
    at->savedOperatingIP = IPAddress(0, 0, 0, 0);
 | 
			
		||||
    at->commandMode();
 | 
			
		||||
    // For WiFi models, there's no direct way to close the socket.  This is a
 | 
			
		||||
    // hack to shut the socket by setting the timeout to zero.
 | 
			
		||||
@@ -216,6 +218,10 @@ public:
 | 
			
		||||
      return true;
 | 
			
		||||
    }
 | 
			
		||||
    return sock_connected;
 | 
			
		||||
    // NOTE:  We dont't check or return
 | 
			
		||||
    // modemGetConnected() because we don't
 | 
			
		||||
    // want to go into command mode.
 | 
			
		||||
    // return at->modemGetConnected();
 | 
			
		||||
  }
 | 
			
		||||
  virtual operator bool() { return connected(); }
 | 
			
		||||
 | 
			
		||||
@@ -832,7 +838,31 @@ public:
 | 
			
		||||
   * Client related functions
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
 protected:
 | 
			
		||||
 | 
			
		||||
  int16_t getConnectionIndicator() {
 | 
			
		||||
    XBEE_COMMAND_START_DECORATOR(5, false)
 | 
			
		||||
    sendAT(GF("CI"));
 | 
			
		||||
    int16_t intRes = readResponseInt();
 | 
			
		||||
    XBEE_COMMAND_END_DECORATOR
 | 
			
		||||
    return intRes;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  IPAddress getOperatingIP() {
 | 
			
		||||
    String strIP;
 | 
			
		||||
    strIP.reserve(16);
 | 
			
		||||
 | 
			
		||||
    XBEE_COMMAND_START_DECORATOR(5, IPAddress(0, 0, 0, 0))
 | 
			
		||||
    sendAT(GF("OD"));
 | 
			
		||||
    strIP = stream.readStringUntil('\r');  // read result
 | 
			
		||||
    strIP.trim();
 | 
			
		||||
    XBEE_COMMAND_END_DECORATOR
 | 
			
		||||
 | 
			
		||||
    if (strIP != "" && strIP != GF("ERROR")) {
 | 
			
		||||
      return TinyGsmIpFromString(strIP);
 | 
			
		||||
    } else
 | 
			
		||||
      return IPAddress(0, 0, 0, 0);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  IPAddress lookupHostIP(const char* host, int timeout_s = 45) {
 | 
			
		||||
    String strIP;
 | 
			
		||||
@@ -867,8 +897,6 @@ protected:
 | 
			
		||||
  bool modemConnect(const char* host, uint16_t port, uint8_t mux = 0,
 | 
			
		||||
                    bool ssl = false, int timeout_s = 75)
 | 
			
		||||
  {
 | 
			
		||||
    unsigned long startMillis = millis();
 | 
			
		||||
    uint32_t timeout_ms = ((uint32_t)timeout_s)*1000;
 | 
			
		||||
    bool retVal = false;
 | 
			
		||||
     XBEE_COMMAND_START_DECORATOR(5, false)
 | 
			
		||||
 | 
			
		||||
@@ -885,7 +913,7 @@ protected:
 | 
			
		||||
 | 
			
		||||
    // If we now have a valid IP address, use it to connect
 | 
			
		||||
    if (savedHostIP != IPAddress(0,0,0,0)) {  // Only re-set connection information if we have an IP address
 | 
			
		||||
      retVal = modemConnect(savedHostIP, port, mux, ssl, timeout_ms - (millis() - startMillis));
 | 
			
		||||
      retVal = modemConnect(savedHostIP, port, mux, ssl);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    XBEE_COMMAND_END_DECORATOR
 | 
			
		||||
@@ -893,13 +921,19 @@ protected:
 | 
			
		||||
    return retVal;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  bool modemConnect(IPAddress ip, uint16_t port, uint8_t mux = 0, bool ssl = false, int timeout_s = 75) {
 | 
			
		||||
 | 
			
		||||
  bool modemConnect(IPAddress ip, uint16_t port, uint8_t mux = 0,
 | 
			
		||||
                    bool ssl = false, int timeout_s = 75) {
 | 
			
		||||
    bool success = true;
 | 
			
		||||
    uint32_t timeout_ms = ((uint32_t)timeout_s)*1000;
 | 
			
		||||
 | 
			
		||||
    if (timeout_s != 75) DBG("Timeout doesn't apply here.");
 | 
			
		||||
 | 
			
		||||
    // empty the saved currelty-in-use destination address
 | 
			
		||||
    savedOperatingIP = IPAddress(0, 0, 0, 0);
 | 
			
		||||
 | 
			
		||||
    XBEE_COMMAND_START_DECORATOR(5, false)
 | 
			
		||||
 | 
			
		||||
    if (ip != savedIP) {  // Can skip almost everything if there's no change in the IP address
 | 
			
		||||
    if (ip != savedIP) {  // Can skip almost everything if there's no
 | 
			
		||||
                          // change in the IP address
 | 
			
		||||
      savedIP = ip;  // Set the newly requested IP address
 | 
			
		||||
      String host; host.reserve(16);
 | 
			
		||||
      host += ip[0];
 | 
			
		||||
@@ -926,11 +960,12 @@ protected:
 | 
			
		||||
      success &= writeChanges();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (unsigned long start = millis(); millis() - start < timeout_ms; ) {
 | 
			
		||||
      if (modemGetConnected()) {
 | 
			
		||||
        sockets[mux]->sock_connected = true;
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
    // we'll accept either unknown or connected
 | 
			
		||||
    uint16_t ci = getConnectionIndicator();
 | 
			
		||||
    success &= (ci == 0x00 || ci == 0xFF || ci == 0x28);
 | 
			
		||||
 | 
			
		||||
    if (success) {
 | 
			
		||||
      sockets[mux]->sock_connected = true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    XBEE_COMMAND_END_DECORATOR
 | 
			
		||||
@@ -942,6 +977,17 @@ protected:
 | 
			
		||||
    if (mux != 0) DBG("XBee only supports 1 IP channel in transparent mode!");
 | 
			
		||||
    stream.write((uint8_t*)buff, len);
 | 
			
		||||
    stream.flush();
 | 
			
		||||
 | 
			
		||||
    // After a send, verify the outgoing ip if it isn't set
 | 
			
		||||
    if (savedOperatingIP == IPAddress(0, 0, 0, 0)) {
 | 
			
		||||
      modemGetConnected();
 | 
			
		||||
    }
 | 
			
		||||
    // After sending several characters, also re-check
 | 
			
		||||
    // NOTE:  I'm intentionally not checking after every single character!
 | 
			
		||||
    else if (len > 5) {
 | 
			
		||||
      modemGetConnected();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return len;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -955,17 +1001,11 @@ protected:
 | 
			
		||||
 | 
			
		||||
     XBEE_COMMAND_START_DECORATOR(5, false)
 | 
			
		||||
 | 
			
		||||
    // Verify that we're connected to the *right* IP address
 | 
			
		||||
    // We might be connected - but to the wrong thing
 | 
			
		||||
    // NOTE:  In transparent mode, there is only one connection possible - no multiplex
 | 
			
		||||
    // String strIP; strIP.reserve(16);
 | 
			
		||||
    // sendAT(GF("DL"));
 | 
			
		||||
    // strIP = stream.readStringUntil('\r');  // read result
 | 
			
		||||
    // if (TinyGsmIpFromString(strIP) != savedIP) return exitAndFail();
 | 
			
		||||
 | 
			
		||||
    if (beeType == XBEE_UNKNOWN) getSeries();  // Need to know the bee type to interpret response
 | 
			
		||||
 | 
			
		||||
    switch (beeType){  // The wifi be can only say if it's connected to the netowrk
 | 
			
		||||
    switch (beeType){
 | 
			
		||||
 | 
			
		||||
      // The wifi be can only say if it's connected to the netowrk
 | 
			
		||||
      case XBEE_S6B_WIFI: {
 | 
			
		||||
        RegStatus s = getRegistrationStatus();
 | 
			
		||||
        XBEE_COMMAND_END_DECORATOR
 | 
			
		||||
@@ -974,22 +1014,111 @@ protected:
 | 
			
		||||
        }
 | 
			
		||||
        return (s == REG_OK);  // if it's connected, we hope the sockets are too
 | 
			
		||||
      }
 | 
			
		||||
      default: {  // Cellular XBee's
 | 
			
		||||
        sendAT(GF("CI"));
 | 
			
		||||
        int16_t intRes = readResponseInt();
 | 
			
		||||
 | 
			
		||||
      // Cellular XBee's
 | 
			
		||||
      default: {
 | 
			
		||||
        int16_t ci = getConnectionIndicator();
 | 
			
		||||
        // Get the operating destination address
 | 
			
		||||
        IPAddress od = getOperatingIP();
 | 
			
		||||
        XBEE_COMMAND_END_DECORATOR
 | 
			
		||||
        switch(intRes) {
 | 
			
		||||
          case 0x00:  // 0x00 = The socket is definitely open
 | 
			
		||||
          case 0x28:  // 0x28 = "Unknown."
 | 
			
		||||
          case 0xFF:  // 0xFF = No known status - this is always returned prior to sending data
 | 
			
		||||
 | 
			
		||||
        switch(ci) {
 | 
			
		||||
 | 
			
		||||
          // 0x00 = The socket is definitely open
 | 
			
		||||
          case 0x00: {
 | 
			
		||||
            savedOperatingIP = od;
 | 
			
		||||
            // but it's possible the socket is set to the wrong place
 | 
			
		||||
            if (od != IPAddress(0, 0, 0, 0) && od != savedIP) {
 | 
			
		||||
              sockets[0]->stop();
 | 
			
		||||
              return false;
 | 
			
		||||
            }
 | 
			
		||||
            return true;
 | 
			
		||||
          case 0x02:  // 0x02 = Invalid parameters (bad IP/host)
 | 
			
		||||
          case 0x12:  // 0x12 = DNS query lookup failure
 | 
			
		||||
          case 0x25:  // 0x25 = Unknown server - DNS lookup failed (0x22 for UDP socket!)
 | 
			
		||||
            savedIP = IPAddress(0,0,0,0);  // force a lookup next time!
 | 
			
		||||
          default:  // If it's anything else (inc 0x02, 0x12, and 0x25)...
 | 
			
		||||
            sockets[0]->sock_connected = false;  // ...it's definitely NOT connected
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          // 0x28 = "Unknown."
 | 
			
		||||
          // 0xFF = No known status - always returned prior to sending data
 | 
			
		||||
          case 0x28:
 | 
			
		||||
          case 0xFF: {
 | 
			
		||||
            // If we previously had an operating destination and we no longer do,
 | 
			
		||||
            // the socket must have closed
 | 
			
		||||
            if (od == IPAddress(0, 0, 0, 0) && savedOperatingIP != IPAddress(0, 0, 0, 0)) {
 | 
			
		||||
              savedOperatingIP = od;
 | 
			
		||||
              sockets[0]->sock_connected = false;
 | 
			
		||||
              return false;
 | 
			
		||||
            }
 | 
			
		||||
            // else if the operating destination exists, but is wrong
 | 
			
		||||
            // we need to close and re-open
 | 
			
		||||
            else if (od != IPAddress(0, 0, 0, 0) && od != savedIP) {
 | 
			
		||||
              sockets[0]->stop();
 | 
			
		||||
              return false;
 | 
			
		||||
            }
 | 
			
		||||
            // else if the operating destination exists and matches, we're
 | 
			
		||||
            // good to go
 | 
			
		||||
            else if (od != IPAddress(0, 0, 0, 0) && od == savedIP) {
 | 
			
		||||
              savedOperatingIP = od;
 | 
			
		||||
              return true;
 | 
			
		||||
            }
 | 
			
		||||
            // If we never had an operating destination, then sock may be open
 | 
			
		||||
            // but data never sent - this is the dreaded "we don't know"
 | 
			
		||||
            else {
 | 
			
		||||
              savedOperatingIP = od;
 | 
			
		||||
              return true;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // // Ask for information about any open sockets
 | 
			
		||||
            // sendAT(GF("SI"));
 | 
			
		||||
            // String open_socks = stream.readStringUntil('\r');
 | 
			
		||||
            // open_socks.replace(GSM_NL, "");
 | 
			
		||||
            // open_socks.trim();
 | 
			
		||||
            // if (open_socks != "") {
 | 
			
		||||
            //   // In transparent mode, only socket 0 should be possible
 | 
			
		||||
            //   sendAT(GF("SI0"));
 | 
			
		||||
            //   // read socket it
 | 
			
		||||
            //   String sock_id = stream.readStringUntil('\r');
 | 
			
		||||
            //   // read socket state
 | 
			
		||||
            //   String sock_state = stream.readStringUntil('\r');
 | 
			
		||||
            //   // read socket protocol (TCP/UDP)
 | 
			
		||||
            //   String sock_protocol = stream.readStringUntil('\r');
 | 
			
		||||
            //   // read local port number
 | 
			
		||||
            //   String local_port = stream.readStringUntil('\r');
 | 
			
		||||
            //   // read remote port number
 | 
			
		||||
            //   String remote_port = stream.readStringUntil('\r');
 | 
			
		||||
            //   // read remote ip address
 | 
			
		||||
            //   String remoted_address =
 | 
			
		||||
            //       stream.readStringUntil('\r');  // read result
 | 
			
		||||
            //   stream.readStringUntil('\r');      // final carriage return
 | 
			
		||||
            // }
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          // 0x21 = User closed
 | 
			
		||||
          // 0x27 = Connection lost
 | 
			
		||||
          // If the connection is lost or timed out on our side,
 | 
			
		||||
          // we force close so it can reopen
 | 
			
		||||
          case 0x21 :
 | 
			
		||||
          case 0x27 : {
 | 
			
		||||
            Serial.println("Here!");
 | 
			
		||||
            sendAT(GF("TM"));  // Get socket timeout
 | 
			
		||||
            String timeoutUsed = readResponseString(5000L);
 | 
			
		||||
            sendAT(GF("TM"), timeoutUsed);  // Re-set socket timeout
 | 
			
		||||
            waitResponse(5000L);  // This response can be slow
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          // 0x02 = Invalid parameters (bad IP/host)
 | 
			
		||||
          // 0x12 = DNS query lookup failure
 | 
			
		||||
          // 0x25 = Unknown server - DNS lookup failed (0x22 for UDP socket!)
 | 
			
		||||
          case 0x02:
 | 
			
		||||
          case 0x12:
 | 
			
		||||
          case 0x25: {
 | 
			
		||||
            savedIP = IPAddress(0, 0, 0, 0);  // force a lookup next time!
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          // If it's anything else (inc 0x02, 0x12, and 0x25)...
 | 
			
		||||
          // it's definitely NOT connected
 | 
			
		||||
          default: {
 | 
			
		||||
            sockets[0]->sock_connected = false;
 | 
			
		||||
            savedOperatingIP = od;
 | 
			
		||||
            return false;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
@@ -1193,6 +1322,7 @@ protected:
 | 
			
		||||
  IPAddress     savedIP;
 | 
			
		||||
  String        savedHost;
 | 
			
		||||
  IPAddress     savedHostIP;
 | 
			
		||||
  IPAddress     savedOperatingIP;
 | 
			
		||||
  bool          inCommandMode;
 | 
			
		||||
  uint32_t      lastCommandModeMillis;
 | 
			
		||||
  GsmClient*    sockets[TINY_GSM_MUX_COUNT];
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user