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