Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of MTS-Cellular by
Cellular/UIP.cpp@3:04046eebaef5, 2014-05-20 (annotated)
- Committer:
- Mike Fiore
- Date:
- Tue May 20 15:21:06 2014 -0500
- Revision:
- 3:04046eebaef5
- Parent:
- Cellular/SMCIP.cpp@2:10e72dce251d
- Child:
- 4:1f63354b8d1b
rename SMC and SMCIP files to EasyIP and UIP, remove RadioInterface code
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Mike Fiore |
3:04046eebaef5 | 1 | #include "mbed.h" |
Mike Fiore |
3:04046eebaef5 | 2 | #include "UIP.h" |
Mike Fiore |
1:f155d94d6f3a | 3 | #include "MTSText.h" |
Mike Fiore |
2:10e72dce251d | 4 | #include "CellUtils.h" |
Mike Fiore |
1:f155d94d6f3a | 5 | |
Mike Fiore |
1:f155d94d6f3a | 6 | using namespace mts; |
Mike Fiore |
1:f155d94d6f3a | 7 | |
Mike Fiore |
3:04046eebaef5 | 8 | UIP::UIP() |
Mike Fiore |
3:04046eebaef5 | 9 | : dcd(NULL), |
Mike Fiore |
3:04046eebaef5 | 10 | dtr(NULL), |
Mike Fiore |
3:04046eebaef5 | 11 | resetLine(NULL) |
Mike Fiore |
1:f155d94d6f3a | 12 | { |
Mike Fiore |
3:04046eebaef5 | 13 | io = NULL; |
Mike Fiore |
3:04046eebaef5 | 14 | echoMode = true; |
Mike Fiore |
3:04046eebaef5 | 15 | pppConnected = false; |
Mike Fiore |
3:04046eebaef5 | 16 | mode = TCP; |
Mike Fiore |
3:04046eebaef5 | 17 | socketOpened = false; |
Mike Fiore |
3:04046eebaef5 | 18 | socketCloseable = true; |
Mike Fiore |
3:04046eebaef5 | 19 | local_port = 0; |
Mike Fiore |
3:04046eebaef5 | 20 | local_address = ""; |
Mike Fiore |
3:04046eebaef5 | 21 | host_port = 0; |
Mike Fiore |
1:f155d94d6f3a | 22 | } |
Mike Fiore |
1:f155d94d6f3a | 23 | |
Mike Fiore |
3:04046eebaef5 | 24 | UIP::~UIP() |
Mike Fiore |
1:f155d94d6f3a | 25 | { |
Mike Fiore |
1:f155d94d6f3a | 26 | if (dtr != NULL) { |
Mike Fiore |
1:f155d94d6f3a | 27 | dtr->write(1); |
Mike Fiore |
1:f155d94d6f3a | 28 | } |
Mike Fiore |
1:f155d94d6f3a | 29 | |
Mike Fiore |
1:f155d94d6f3a | 30 | delete dcd; |
Mike Fiore |
1:f155d94d6f3a | 31 | delete dtr; |
Mike Fiore |
1:f155d94d6f3a | 32 | delete resetLine; |
Mike Fiore |
1:f155d94d6f3a | 33 | } |
Mike Fiore |
1:f155d94d6f3a | 34 | |
Mike Fiore |
3:04046eebaef5 | 35 | bool UIP::init(MTSBufferedIO* io) |
Mike Fiore |
1:f155d94d6f3a | 36 | { |
Mike Fiore |
1:f155d94d6f3a | 37 | if (io == NULL) { |
Mike Fiore |
1:f155d94d6f3a | 38 | return false; |
Mike Fiore |
1:f155d94d6f3a | 39 | } |
Mike Fiore |
1:f155d94d6f3a | 40 | this->io = io; |
Mike Fiore |
1:f155d94d6f3a | 41 | |
Mike Fiore |
1:f155d94d6f3a | 42 | test(); |
Mike Fiore |
1:f155d94d6f3a | 43 | // Reset radio to make sure it's in a good state and wait for it to come back |
Mike Fiore |
1:f155d94d6f3a | 44 | reset(); |
Mike Fiore |
1:f155d94d6f3a | 45 | test(); |
Mike Fiore |
1:f155d94d6f3a | 46 | |
Mike Fiore |
1:f155d94d6f3a | 47 | return SUCCESS; |
Mike Fiore |
1:f155d94d6f3a | 48 | } |
Mike Fiore |
1:f155d94d6f3a | 49 | |
Mike Fiore |
3:04046eebaef5 | 50 | bool UIP::configureSignals(PinName DCD, PinName DTR, PinName RESET) |
Mike Fiore |
1:f155d94d6f3a | 51 | { |
Mike Fiore |
1:f155d94d6f3a | 52 | //Set DCD - The radio will raise and lower this line |
Mike Fiore |
1:f155d94d6f3a | 53 | if (DCD != NC) { |
Mike Fiore |
1:f155d94d6f3a | 54 | dcd = new DigitalIn(DCD); |
Mike Fiore |
1:f155d94d6f3a | 55 | } |
Mike Fiore |
1:f155d94d6f3a | 56 | /* Set DTR - This line should be lowered when we want to talk to the radio and raised when we're done |
Mike Fiore |
1:f155d94d6f3a | 57 | * for now we will lower it in the constructor and raise it in the destructor. |
Mike Fiore |
1:f155d94d6f3a | 58 | */ |
Mike Fiore |
1:f155d94d6f3a | 59 | if (DTR != NC) { |
Mike Fiore |
1:f155d94d6f3a | 60 | dtr = new DigitalOut(DTR); |
Mike Fiore |
1:f155d94d6f3a | 61 | dtr->write(0); |
Mike Fiore |
1:f155d94d6f3a | 62 | } |
Mike Fiore |
1:f155d94d6f3a | 63 | //Set RESET - Set the hardware reset line to the radio |
Mike Fiore |
1:f155d94d6f3a | 64 | if (RESET != NC) { |
Mike Fiore |
1:f155d94d6f3a | 65 | resetLine = new DigitalOut(RESET); |
Mike Fiore |
1:f155d94d6f3a | 66 | } |
Mike Fiore |
1:f155d94d6f3a | 67 | return true; |
Mike Fiore |
1:f155d94d6f3a | 68 | } |
Mike Fiore |
1:f155d94d6f3a | 69 | |
Mike Fiore |
3:04046eebaef5 | 70 | bool UIP::connect() |
Mike Fiore |
1:f155d94d6f3a | 71 | { |
Mike Fiore |
1:f155d94d6f3a | 72 | //Check if socket is open |
Mike Fiore |
1:f155d94d6f3a | 73 | if(socketOpened) { |
Mike Fiore |
1:f155d94d6f3a | 74 | return true; |
Mike Fiore |
1:f155d94d6f3a | 75 | } |
Mike Fiore |
1:f155d94d6f3a | 76 | |
Mike Fiore |
1:f155d94d6f3a | 77 | //Check if already connected |
Mike Fiore |
1:f155d94d6f3a | 78 | if(isConnected()) { |
Mike Fiore |
1:f155d94d6f3a | 79 | return true; |
Mike Fiore |
1:f155d94d6f3a | 80 | } |
Mike Fiore |
1:f155d94d6f3a | 81 | |
Mike Fiore |
1:f155d94d6f3a | 82 | Timer tmr; |
Mike Fiore |
1:f155d94d6f3a | 83 | |
Mike Fiore |
1:f155d94d6f3a | 84 | //Check Registration: AT+CREG? == 0,1 |
Mike Fiore |
1:f155d94d6f3a | 85 | tmr.start(); |
Mike Fiore |
1:f155d94d6f3a | 86 | do { |
Mike Fiore |
1:f155d94d6f3a | 87 | Registration registration = getRegistration(); |
Mike Fiore |
1:f155d94d6f3a | 88 | if(registration != REGISTERED) { |
Mike Fiore |
1:f155d94d6f3a | 89 | printf("[WARNING] Not Registered [%d] ... waiting\r\n", (int)registration); |
Mike Fiore |
1:f155d94d6f3a | 90 | wait(1); |
Mike Fiore |
1:f155d94d6f3a | 91 | } else { |
Mike Fiore |
1:f155d94d6f3a | 92 | break; |
Mike Fiore |
1:f155d94d6f3a | 93 | } |
Mike Fiore |
1:f155d94d6f3a | 94 | } while(tmr.read() < 30); |
Mike Fiore |
1:f155d94d6f3a | 95 | |
Mike Fiore |
1:f155d94d6f3a | 96 | //Check RSSI: AT+CSQ |
Mike Fiore |
1:f155d94d6f3a | 97 | tmr.reset(); |
Mike Fiore |
1:f155d94d6f3a | 98 | do { |
Mike Fiore |
1:f155d94d6f3a | 99 | int rssi = getSignalStrength(); |
Mike Fiore |
1:f155d94d6f3a | 100 | printf("[DEBUG] Signal strength: %d\r\n", rssi); |
Mike Fiore |
1:f155d94d6f3a | 101 | if(rssi == 99) { |
Mike Fiore |
1:f155d94d6f3a | 102 | printf("[WARNING] No Signal ... waiting\r\n"); |
Mike Fiore |
1:f155d94d6f3a | 103 | wait(1); |
Mike Fiore |
1:f155d94d6f3a | 104 | } else { |
Mike Fiore |
1:f155d94d6f3a | 105 | break; |
Mike Fiore |
1:f155d94d6f3a | 106 | } |
Mike Fiore |
1:f155d94d6f3a | 107 | } while(tmr.read() < 30); |
Mike Fiore |
1:f155d94d6f3a | 108 | |
Mike Fiore |
1:f155d94d6f3a | 109 | //AT#CONNECTIONSTART: Make a PPP connection |
Mike Fiore |
1:f155d94d6f3a | 110 | printf("[DEBUG] Making PPP Connection Attempt. APN[%s]\r\n", apn.c_str()); |
Mike Fiore |
1:f155d94d6f3a | 111 | std::string pppResult = sendCommand("AT#CONNECTIONSTART", 120000); |
Mike Fiore |
1:f155d94d6f3a | 112 | std::vector<std::string> parts = Text::split(pppResult, "\r\n"); |
Mike Fiore |
1:f155d94d6f3a | 113 | |
Mike Fiore |
1:f155d94d6f3a | 114 | if(pppResult.find("Ok_Info_GprsActivation") != std::string::npos) { |
Mike Fiore |
1:f155d94d6f3a | 115 | if(parts.size() >= 2) { |
Mike Fiore |
1:f155d94d6f3a | 116 | local_address = parts[1]; |
Mike Fiore |
1:f155d94d6f3a | 117 | } |
Mike Fiore |
1:f155d94d6f3a | 118 | printf("[INFO] PPP Connection Established: IP[%s]\r\n", local_address.c_str()); |
Mike Fiore |
1:f155d94d6f3a | 119 | pppConnected = true; |
Mike Fiore |
1:f155d94d6f3a | 120 | |
Mike Fiore |
1:f155d94d6f3a | 121 | } else { |
Mike Fiore |
1:f155d94d6f3a | 122 | pppConnected = false; |
Mike Fiore |
1:f155d94d6f3a | 123 | } |
Mike Fiore |
1:f155d94d6f3a | 124 | |
Mike Fiore |
1:f155d94d6f3a | 125 | return pppConnected; |
Mike Fiore |
1:f155d94d6f3a | 126 | } |
Mike Fiore |
1:f155d94d6f3a | 127 | |
Mike Fiore |
3:04046eebaef5 | 128 | void UIP::disconnect() |
Mike Fiore |
1:f155d94d6f3a | 129 | { |
Mike Fiore |
1:f155d94d6f3a | 130 | //AT#CONNECTIONSTOP: Close a PPP connection |
Mike Fiore |
1:f155d94d6f3a | 131 | printf("[DEBUG] Closing PPP Connection\r\n"); |
Mike Fiore |
1:f155d94d6f3a | 132 | |
Mike Fiore |
1:f155d94d6f3a | 133 | if(socketOpened) { |
Mike Fiore |
1:f155d94d6f3a | 134 | close(); |
Mike Fiore |
1:f155d94d6f3a | 135 | } |
Mike Fiore |
1:f155d94d6f3a | 136 | |
Mike Fiore |
1:f155d94d6f3a | 137 | Code code = sendBasicCommand("AT#CONNECTIONSTOP", 10000); |
Mike Fiore |
1:f155d94d6f3a | 138 | if(code == SUCCESS) { |
Mike Fiore |
1:f155d94d6f3a | 139 | printf("[DEBUG] Successfully closed PPP Connection\r\n"); |
Mike Fiore |
1:f155d94d6f3a | 140 | } else { |
Mike Fiore |
1:f155d94d6f3a | 141 | printf("[ERROR] Closing PPP Connection [%d]. Continuing ...\r\n", (int)code); |
Mike Fiore |
1:f155d94d6f3a | 142 | } |
Mike Fiore |
1:f155d94d6f3a | 143 | |
Mike Fiore |
1:f155d94d6f3a | 144 | pppConnected = false; |
Mike Fiore |
1:f155d94d6f3a | 145 | } |
Mike Fiore |
1:f155d94d6f3a | 146 | |
Mike Fiore |
3:04046eebaef5 | 147 | bool UIP::isConnected() |
Mike Fiore |
1:f155d94d6f3a | 148 | { |
Mike Fiore |
1:f155d94d6f3a | 149 | //1) Check if APN was set |
Mike Fiore |
1:f155d94d6f3a | 150 | if(apn.size() == 0) { |
Mike Fiore |
1:f155d94d6f3a | 151 | printf("[DEBUG] APN is not set\r\n"); |
Mike Fiore |
1:f155d94d6f3a | 152 | return false; |
Mike Fiore |
1:f155d94d6f3a | 153 | } |
Mike Fiore |
1:f155d94d6f3a | 154 | |
Mike Fiore |
1:f155d94d6f3a | 155 | //1) Check that we do not have a live connection up |
Mike Fiore |
1:f155d94d6f3a | 156 | if(socketOpened) { |
Mike Fiore |
1:f155d94d6f3a | 157 | printf("[DEBUG] Socket is opened\r\n"); |
Mike Fiore |
1:f155d94d6f3a | 158 | return true; |
Mike Fiore |
1:f155d94d6f3a | 159 | } |
Mike Fiore |
1:f155d94d6f3a | 160 | //2) Query the radio |
Mike Fiore |
1:f155d94d6f3a | 161 | std::string result = sendCommand("AT#VSTATE", 3000); |
Mike Fiore |
1:f155d94d6f3a | 162 | if(result.find("CONNECTED") != std::string::npos) { |
Mike Fiore |
1:f155d94d6f3a | 163 | if(pppConnected == false) { |
Mike Fiore |
1:f155d94d6f3a | 164 | printf("[WARNING] Internal PPP state tracking differs from radio (DISCONNECTED:CONNECTED)\r\n"); |
Mike Fiore |
1:f155d94d6f3a | 165 | } |
Mike Fiore |
1:f155d94d6f3a | 166 | pppConnected = true; |
Mike Fiore |
1:f155d94d6f3a | 167 | } else { |
Mike Fiore |
1:f155d94d6f3a | 168 | if(pppConnected == true) { |
Mike Fiore |
1:f155d94d6f3a | 169 | //Find out what state is |
Mike Fiore |
1:f155d94d6f3a | 170 | size_t pos = result.find("STATE:"); |
Mike Fiore |
1:f155d94d6f3a | 171 | if(pos != std::string::npos) { |
Mike Fiore |
1:f155d94d6f3a | 172 | result = Text::getLine(result, pos + sizeof("STATE:"), pos); |
Mike Fiore |
1:f155d94d6f3a | 173 | printf("[WARNING] Internal PPP state tracking differs from radio (CONNECTED:%s)\r\n", result.c_str()); |
Mike Fiore |
1:f155d94d6f3a | 174 | } else { |
Mike Fiore |
1:f155d94d6f3a | 175 | printf("[ERROR] Unable to parse radio state: [%s]\r\n", result.c_str()); |
Mike Fiore |
1:f155d94d6f3a | 176 | } |
Mike Fiore |
1:f155d94d6f3a | 177 | |
Mike Fiore |
1:f155d94d6f3a | 178 | } |
Mike Fiore |
1:f155d94d6f3a | 179 | pppConnected = false; |
Mike Fiore |
1:f155d94d6f3a | 180 | } |
Mike Fiore |
1:f155d94d6f3a | 181 | |
Mike Fiore |
1:f155d94d6f3a | 182 | return pppConnected; |
Mike Fiore |
1:f155d94d6f3a | 183 | } |
Mike Fiore |
1:f155d94d6f3a | 184 | |
Mike Fiore |
3:04046eebaef5 | 185 | bool UIP::bind(unsigned int port) |
Mike Fiore |
1:f155d94d6f3a | 186 | { |
Mike Fiore |
1:f155d94d6f3a | 187 | if(socketOpened) { |
Mike Fiore |
1:f155d94d6f3a | 188 | printf("[ERROR] socket is open. Can not set local port\r\n"); |
Mike Fiore |
1:f155d94d6f3a | 189 | return false; |
Mike Fiore |
1:f155d94d6f3a | 190 | } |
Mike Fiore |
1:f155d94d6f3a | 191 | if(port > 65535) { |
Mike Fiore |
1:f155d94d6f3a | 192 | printf("[ERROR] port out of range (0-65535)\r\n"); |
Mike Fiore |
1:f155d94d6f3a | 193 | return false; |
Mike Fiore |
1:f155d94d6f3a | 194 | } |
Mike Fiore |
1:f155d94d6f3a | 195 | local_port = port; |
Mike Fiore |
1:f155d94d6f3a | 196 | return true; |
Mike Fiore |
1:f155d94d6f3a | 197 | } |
Mike Fiore |
1:f155d94d6f3a | 198 | |
Mike Fiore |
3:04046eebaef5 | 199 | bool UIP::open(const std::string& address, unsigned int port, Mode mode) |
Mike Fiore |
1:f155d94d6f3a | 200 | { |
Mike Fiore |
1:f155d94d6f3a | 201 | char buffer[256] = {0}; |
Mike Fiore |
1:f155d94d6f3a | 202 | Code portCode, addressCode; |
Mike Fiore |
1:f155d94d6f3a | 203 | |
Mike Fiore |
1:f155d94d6f3a | 204 | //1) Check that we do not have a live connection up |
Mike Fiore |
1:f155d94d6f3a | 205 | if(socketOpened) { |
Mike Fiore |
1:f155d94d6f3a | 206 | //Check that the address, port, and mode match |
Mike Fiore |
1:f155d94d6f3a | 207 | if(host_address != address || host_port != port || this->mode != mode) { |
Mike Fiore |
1:f155d94d6f3a | 208 | if(this->mode == TCP) { |
Mike Fiore |
1:f155d94d6f3a | 209 | printf("[ERROR] TCP socket already opened [%s:%d]\r\n", host_address.c_str(), host_port); |
Mike Fiore |
1:f155d94d6f3a | 210 | } else { |
Mike Fiore |
1:f155d94d6f3a | 211 | printf("[ERROR] UDP socket already opened [%s:%d]\r\n", host_address.c_str(), host_port); |
Mike Fiore |
1:f155d94d6f3a | 212 | } |
Mike Fiore |
1:f155d94d6f3a | 213 | return false; |
Mike Fiore |
1:f155d94d6f3a | 214 | } |
Mike Fiore |
1:f155d94d6f3a | 215 | |
Mike Fiore |
1:f155d94d6f3a | 216 | printf("[DEBUG] Socket already opened\r\n"); |
Mike Fiore |
1:f155d94d6f3a | 217 | return true; |
Mike Fiore |
1:f155d94d6f3a | 218 | } |
Mike Fiore |
1:f155d94d6f3a | 219 | |
Mike Fiore |
1:f155d94d6f3a | 220 | //2) Check Parameters |
Mike Fiore |
1:f155d94d6f3a | 221 | if(port > 65535) { |
Mike Fiore |
1:f155d94d6f3a | 222 | printf("[ERROR] port out of range (0-65535)\r\n"); |
Mike Fiore |
1:f155d94d6f3a | 223 | return false; |
Mike Fiore |
1:f155d94d6f3a | 224 | } |
Mike Fiore |
1:f155d94d6f3a | 225 | |
Mike Fiore |
1:f155d94d6f3a | 226 | //3) Check PPP connection |
Mike Fiore |
1:f155d94d6f3a | 227 | if(!isConnected()) { |
Mike Fiore |
1:f155d94d6f3a | 228 | printf("[ERROR] PPP not established. Attempting to connect\r\n"); |
Mike Fiore |
1:f155d94d6f3a | 229 | if(!connect()) { |
Mike Fiore |
1:f155d94d6f3a | 230 | printf("[ERROR] PPP connection failed\r\n"); |
Mike Fiore |
1:f155d94d6f3a | 231 | return false; |
Mike Fiore |
1:f155d94d6f3a | 232 | } else { |
Mike Fiore |
1:f155d94d6f3a | 233 | printf("[DEBUG] PPP connection established\r\n"); |
Mike Fiore |
1:f155d94d6f3a | 234 | } |
Mike Fiore |
1:f155d94d6f3a | 235 | } |
Mike Fiore |
1:f155d94d6f3a | 236 | |
Mike Fiore |
1:f155d94d6f3a | 237 | //Set Local Port |
Mike Fiore |
1:f155d94d6f3a | 238 | if(local_port != 0) { |
Mike Fiore |
1:f155d94d6f3a | 239 | //Attempt to set local port |
Mike Fiore |
1:f155d94d6f3a | 240 | sprintf(buffer, "AT#OUTPORT=%d", local_port); |
Mike Fiore |
1:f155d94d6f3a | 241 | Code code = sendBasicCommand(buffer, 1000); |
Mike Fiore |
1:f155d94d6f3a | 242 | if(code != SUCCESS) { |
Mike Fiore |
1:f155d94d6f3a | 243 | printf("[WARNING] Unable to set local port (%d) [%d]\r\n", local_port, (int) code); |
Mike Fiore |
1:f155d94d6f3a | 244 | } |
Mike Fiore |
1:f155d94d6f3a | 245 | } |
Mike Fiore |
1:f155d94d6f3a | 246 | |
Mike Fiore |
1:f155d94d6f3a | 247 | //Set TCP/UDP parameters |
Mike Fiore |
1:f155d94d6f3a | 248 | if(mode == TCP) { |
Mike Fiore |
1:f155d94d6f3a | 249 | if(socketCloseable) { |
Mike Fiore |
1:f155d94d6f3a | 250 | Code code = sendBasicCommand("AT#DLEMODE=1,1", 1000); |
Mike Fiore |
1:f155d94d6f3a | 251 | if(code != SUCCESS) { |
Mike Fiore |
1:f155d94d6f3a | 252 | printf("[WARNING] Unable to set socket closeable [%d]\r\n", (int) code); |
Mike Fiore |
1:f155d94d6f3a | 253 | } |
Mike Fiore |
1:f155d94d6f3a | 254 | } |
Mike Fiore |
1:f155d94d6f3a | 255 | sprintf(buffer, "AT#TCPPORT=1,%d", port); |
Mike Fiore |
1:f155d94d6f3a | 256 | portCode = sendBasicCommand(buffer, 1000); |
Mike Fiore |
1:f155d94d6f3a | 257 | addressCode = sendBasicCommand("AT#TCPSERV=1,\"" + address + "\"", 1000); |
Mike Fiore |
1:f155d94d6f3a | 258 | } else { |
Mike Fiore |
1:f155d94d6f3a | 259 | if(socketCloseable) { |
Mike Fiore |
1:f155d94d6f3a | 260 | Code code = sendBasicCommand("AT#UDPDLEMODE=1", 1000); |
Mike Fiore |
1:f155d94d6f3a | 261 | if(code != SUCCESS) { |
Mike Fiore |
1:f155d94d6f3a | 262 | printf("[WARNING] Unable to set socket closeable [%d]\r\n", (int) code); |
Mike Fiore |
1:f155d94d6f3a | 263 | } |
Mike Fiore |
1:f155d94d6f3a | 264 | } |
Mike Fiore |
1:f155d94d6f3a | 265 | sprintf(buffer, "AT#UDPPORT=%d", port); |
Mike Fiore |
1:f155d94d6f3a | 266 | portCode = sendBasicCommand(buffer, 1000); |
Mike Fiore |
1:f155d94d6f3a | 267 | addressCode = sendBasicCommand("AT#UDPSERV=\"" + address + "\"", 1000); |
Mike Fiore |
1:f155d94d6f3a | 268 | } |
Mike Fiore |
1:f155d94d6f3a | 269 | |
Mike Fiore |
1:f155d94d6f3a | 270 | if(portCode == SUCCESS) { |
Mike Fiore |
1:f155d94d6f3a | 271 | host_port = port; |
Mike Fiore |
1:f155d94d6f3a | 272 | } else { |
Mike Fiore |
1:f155d94d6f3a | 273 | printf("[ERROR] Host port could not be set\r\n"); |
Mike Fiore |
1:f155d94d6f3a | 274 | } |
Mike Fiore |
1:f155d94d6f3a | 275 | |
Mike Fiore |
1:f155d94d6f3a | 276 | if(addressCode == SUCCESS) { |
Mike Fiore |
1:f155d94d6f3a | 277 | host_address = address; |
Mike Fiore |
1:f155d94d6f3a | 278 | } else { |
Mike Fiore |
1:f155d94d6f3a | 279 | printf("[ERROR] Host address could not be set\r\n"); |
Mike Fiore |
1:f155d94d6f3a | 280 | } |
Mike Fiore |
1:f155d94d6f3a | 281 | |
Mike Fiore |
1:f155d94d6f3a | 282 | // Try and Connect |
Mike Fiore |
1:f155d94d6f3a | 283 | std::string sMode; |
Mike Fiore |
1:f155d94d6f3a | 284 | std::string sOpenSocketCmd; |
Mike Fiore |
1:f155d94d6f3a | 285 | if(mode == TCP) { |
Mike Fiore |
1:f155d94d6f3a | 286 | sOpenSocketCmd = "AT#OTCP=1"; |
Mike Fiore |
1:f155d94d6f3a | 287 | sMode = "TCP"; |
Mike Fiore |
1:f155d94d6f3a | 288 | } else { |
Mike Fiore |
1:f155d94d6f3a | 289 | sOpenSocketCmd = "AT#OUDP"; |
Mike Fiore |
1:f155d94d6f3a | 290 | sMode = "UDP"; |
Mike Fiore |
1:f155d94d6f3a | 291 | } |
Mike Fiore |
1:f155d94d6f3a | 292 | |
Mike Fiore |
1:f155d94d6f3a | 293 | string response = sendCommand(sOpenSocketCmd, 30000); |
Mike Fiore |
1:f155d94d6f3a | 294 | if (response.find("Ok_Info_WaitingForData") != string::npos) { |
Mike Fiore |
1:f155d94d6f3a | 295 | printf("[INFO] Opened %s Socket [%s:%d]\r\n", sMode.c_str(), address.c_str(), port); |
Mike Fiore |
1:f155d94d6f3a | 296 | socketOpened = true; |
Mike Fiore |
1:f155d94d6f3a | 297 | } else { |
Mike Fiore |
1:f155d94d6f3a | 298 | printf("[WARNING] Unable to open %s Socket [%s:%d]\r\n", sMode.c_str(), address.c_str(), port); |
Mike Fiore |
1:f155d94d6f3a | 299 | socketOpened = false; |
Mike Fiore |
1:f155d94d6f3a | 300 | } |
Mike Fiore |
1:f155d94d6f3a | 301 | |
Mike Fiore |
1:f155d94d6f3a | 302 | return socketOpened; |
Mike Fiore |
1:f155d94d6f3a | 303 | } |
Mike Fiore |
1:f155d94d6f3a | 304 | |
Mike Fiore |
3:04046eebaef5 | 305 | bool UIP::isOpen() |
Mike Fiore |
1:f155d94d6f3a | 306 | { |
Mike Fiore |
1:f155d94d6f3a | 307 | if(io->readable()) { |
Mike Fiore |
1:f155d94d6f3a | 308 | printf("[DEBUG] Assuming open, data available to read.\n\r"); |
Mike Fiore |
1:f155d94d6f3a | 309 | return true; |
Mike Fiore |
1:f155d94d6f3a | 310 | } |
Mike Fiore |
1:f155d94d6f3a | 311 | return socketOpened; |
Mike Fiore |
1:f155d94d6f3a | 312 | } |
Mike Fiore |
1:f155d94d6f3a | 313 | |
Mike Fiore |
3:04046eebaef5 | 314 | bool UIP::close() |
Mike Fiore |
1:f155d94d6f3a | 315 | { |
Mike Fiore |
1:f155d94d6f3a | 316 | if(io == NULL) { |
Mike Fiore |
1:f155d94d6f3a | 317 | printf("[ERROR] MTSBufferedIO not set\r\n"); |
Mike Fiore |
1:f155d94d6f3a | 318 | return false; |
Mike Fiore |
1:f155d94d6f3a | 319 | } |
Mike Fiore |
1:f155d94d6f3a | 320 | |
Mike Fiore |
1:f155d94d6f3a | 321 | if(!socketOpened) { |
Mike Fiore |
1:f155d94d6f3a | 322 | printf("[WARNING] Socket close() called, but socket was not open\r\n"); |
Mike Fiore |
1:f155d94d6f3a | 323 | return true; |
Mike Fiore |
1:f155d94d6f3a | 324 | } |
Mike Fiore |
1:f155d94d6f3a | 325 | |
Mike Fiore |
1:f155d94d6f3a | 326 | if(!socketCloseable) { |
Mike Fiore |
1:f155d94d6f3a | 327 | printf("[ERROR] Socket is not closeable\r\n"); |
Mike Fiore |
1:f155d94d6f3a | 328 | return false; |
Mike Fiore |
1:f155d94d6f3a | 329 | } |
Mike Fiore |
1:f155d94d6f3a | 330 | |
Mike Fiore |
1:f155d94d6f3a | 331 | |
Mike Fiore |
1:f155d94d6f3a | 332 | |
Mike Fiore |
1:f155d94d6f3a | 333 | if(io->write(ETX, 1000) != 1) { |
Mike Fiore |
1:f155d94d6f3a | 334 | printf("[ERROR] Timed out attempting to close socket\r\n"); |
Mike Fiore |
1:f155d94d6f3a | 335 | return false; |
Mike Fiore |
1:f155d94d6f3a | 336 | } |
Mike Fiore |
1:f155d94d6f3a | 337 | |
Mike Fiore |
1:f155d94d6f3a | 338 | Timer tmr; |
Mike Fiore |
1:f155d94d6f3a | 339 | int counter = 0; |
Mike Fiore |
1:f155d94d6f3a | 340 | char tmp[256]; |
Mike Fiore |
1:f155d94d6f3a | 341 | tmr.start(); |
Mike Fiore |
1:f155d94d6f3a | 342 | do { |
Mike Fiore |
1:f155d94d6f3a | 343 | if(socketOpened == false) { |
Mike Fiore |
1:f155d94d6f3a | 344 | break; |
Mike Fiore |
1:f155d94d6f3a | 345 | } |
Mike Fiore |
1:f155d94d6f3a | 346 | read(tmp, 256, 1000); |
Mike Fiore |
1:f155d94d6f3a | 347 | } while(counter++ < 10); |
Mike Fiore |
1:f155d94d6f3a | 348 | |
Mike Fiore |
1:f155d94d6f3a | 349 | io->rxClear(); |
Mike Fiore |
1:f155d94d6f3a | 350 | io->txClear(); |
Mike Fiore |
1:f155d94d6f3a | 351 | |
Mike Fiore |
1:f155d94d6f3a | 352 | socketOpened = false; |
Mike Fiore |
1:f155d94d6f3a | 353 | return true; |
Mike Fiore |
1:f155d94d6f3a | 354 | } |
Mike Fiore |
1:f155d94d6f3a | 355 | |
Mike Fiore |
3:04046eebaef5 | 356 | int UIP::read(char* data, int max, int timeout) |
Mike Fiore |
1:f155d94d6f3a | 357 | { |
Mike Fiore |
1:f155d94d6f3a | 358 | if(io == NULL) { |
Mike Fiore |
1:f155d94d6f3a | 359 | printf("[ERROR] MTSBufferedIO not set\r\n"); |
Mike Fiore |
1:f155d94d6f3a | 360 | return -1; |
Mike Fiore |
1:f155d94d6f3a | 361 | } |
Mike Fiore |
1:f155d94d6f3a | 362 | |
Mike Fiore |
1:f155d94d6f3a | 363 | //Check that nothing is in the rx buffer |
Mike Fiore |
1:f155d94d6f3a | 364 | if(!socketOpened && !io->readable()) { |
Mike Fiore |
1:f155d94d6f3a | 365 | printf("[ERROR] Socket is not open\r\n"); |
Mike Fiore |
1:f155d94d6f3a | 366 | return -1; |
Mike Fiore |
1:f155d94d6f3a | 367 | } |
Mike Fiore |
1:f155d94d6f3a | 368 | |
Mike Fiore |
1:f155d94d6f3a | 369 | int bytesRead = 0; |
Mike Fiore |
1:f155d94d6f3a | 370 | |
Mike Fiore |
1:f155d94d6f3a | 371 | if(timeout >= 0) { |
Mike Fiore |
1:f155d94d6f3a | 372 | bytesRead = io->read(data, max, static_cast<unsigned int>(timeout)); |
Mike Fiore |
1:f155d94d6f3a | 373 | } else { |
Mike Fiore |
1:f155d94d6f3a | 374 | bytesRead = io->read(data, max); |
Mike Fiore |
1:f155d94d6f3a | 375 | } |
Mike Fiore |
1:f155d94d6f3a | 376 | |
Mike Fiore |
1:f155d94d6f3a | 377 | if(bytesRead > 0 && socketCloseable) { |
Mike Fiore |
1:f155d94d6f3a | 378 | //Remove escape characters |
Mike Fiore |
1:f155d94d6f3a | 379 | int index = 0; |
Mike Fiore |
1:f155d94d6f3a | 380 | bool escapeFlag = false; |
Mike Fiore |
1:f155d94d6f3a | 381 | for(int i = 0; i < bytesRead; i++) { |
Mike Fiore |
1:f155d94d6f3a | 382 | if(data[i] == DLE || data[i] == ETX) { |
Mike Fiore |
1:f155d94d6f3a | 383 | if(escapeFlag == true) { |
Mike Fiore |
1:f155d94d6f3a | 384 | //This character has been escaped |
Mike Fiore |
1:f155d94d6f3a | 385 | escapeFlag = false; |
Mike Fiore |
1:f155d94d6f3a | 386 | } else if(data[bytesRead] == DLE) { |
Mike Fiore |
1:f155d94d6f3a | 387 | //Found escape character |
Mike Fiore |
1:f155d94d6f3a | 388 | escapeFlag = true; |
Mike Fiore |
1:f155d94d6f3a | 389 | continue; |
Mike Fiore |
1:f155d94d6f3a | 390 | } else { |
Mike Fiore |
1:f155d94d6f3a | 391 | //ETX sent without escape -> Socket closed |
Mike Fiore |
1:f155d94d6f3a | 392 | printf("[INFO] Read ETX character without DLE escape. Socket closed\r\n"); |
Mike Fiore |
1:f155d94d6f3a | 393 | socketOpened = false; |
Mike Fiore |
1:f155d94d6f3a | 394 | continue; |
Mike Fiore |
1:f155d94d6f3a | 395 | } |
Mike Fiore |
1:f155d94d6f3a | 396 | } |
Mike Fiore |
1:f155d94d6f3a | 397 | |
Mike Fiore |
1:f155d94d6f3a | 398 | if(index != i) { |
Mike Fiore |
1:f155d94d6f3a | 399 | data[index] = data[i]; |
Mike Fiore |
1:f155d94d6f3a | 400 | } |
Mike Fiore |
1:f155d94d6f3a | 401 | index++; |
Mike Fiore |
1:f155d94d6f3a | 402 | } |
Mike Fiore |
1:f155d94d6f3a | 403 | bytesRead = index; |
Mike Fiore |
1:f155d94d6f3a | 404 | } |
Mike Fiore |
1:f155d94d6f3a | 405 | |
Mike Fiore |
1:f155d94d6f3a | 406 | //Scan for socket closed message |
Mike Fiore |
1:f155d94d6f3a | 407 | for(size_t i = 0; i < bytesRead; i++) { |
Mike Fiore |
1:f155d94d6f3a | 408 | if(data[i] == 'O') { |
Mike Fiore |
1:f155d94d6f3a | 409 | if(strstr(&data[i], "Ok_Info_SocketClosed")) { |
Mike Fiore |
1:f155d94d6f3a | 410 | printf("[INFO] Found socket closed message. Socket closed\r\n"); |
Mike Fiore |
1:f155d94d6f3a | 411 | //Close socket and Cut Off End of Message |
Mike Fiore |
1:f155d94d6f3a | 412 | socketOpened = false; |
Mike Fiore |
1:f155d94d6f3a | 413 | data[i] = '\0'; |
Mike Fiore |
1:f155d94d6f3a | 414 | bytesRead = i; |
Mike Fiore |
1:f155d94d6f3a | 415 | break; |
Mike Fiore |
1:f155d94d6f3a | 416 | } |
Mike Fiore |
1:f155d94d6f3a | 417 | } |
Mike Fiore |
1:f155d94d6f3a | 418 | } |
Mike Fiore |
1:f155d94d6f3a | 419 | return bytesRead; |
Mike Fiore |
1:f155d94d6f3a | 420 | } |
Mike Fiore |
1:f155d94d6f3a | 421 | |
Mike Fiore |
3:04046eebaef5 | 422 | int UIP::write(const char* data, int length, int timeout) |
Mike Fiore |
1:f155d94d6f3a | 423 | { |
Mike Fiore |
1:f155d94d6f3a | 424 | if(io == NULL) { |
Mike Fiore |
1:f155d94d6f3a | 425 | printf("[ERROR] MTSBufferedIO not set\r\n"); |
Mike Fiore |
1:f155d94d6f3a | 426 | return -1; |
Mike Fiore |
1:f155d94d6f3a | 427 | } |
Mike Fiore |
1:f155d94d6f3a | 428 | |
Mike Fiore |
1:f155d94d6f3a | 429 | if(!socketOpened) { |
Mike Fiore |
1:f155d94d6f3a | 430 | printf("[ERROR] Socket is not open\r\n"); |
Mike Fiore |
1:f155d94d6f3a | 431 | return -1; |
Mike Fiore |
1:f155d94d6f3a | 432 | } |
Mike Fiore |
1:f155d94d6f3a | 433 | |
Mike Fiore |
1:f155d94d6f3a | 434 | //In order to avoid allocating another buffer, capture indices of |
Mike Fiore |
1:f155d94d6f3a | 435 | //characters to escape during write |
Mike Fiore |
1:f155d94d6f3a | 436 | int specialWritten = 0; |
Mike Fiore |
1:f155d94d6f3a | 437 | std::vector<int> vSpecial; |
Mike Fiore |
1:f155d94d6f3a | 438 | if(socketCloseable) { |
Mike Fiore |
1:f155d94d6f3a | 439 | for(int i = 0; i < length; i++) { |
Mike Fiore |
1:f155d94d6f3a | 440 | if(data[i] == ETX || data[i] == DLE) { |
Mike Fiore |
1:f155d94d6f3a | 441 | //Push back index of special characters |
Mike Fiore |
1:f155d94d6f3a | 442 | vSpecial.push_back(i); |
Mike Fiore |
1:f155d94d6f3a | 443 | } |
Mike Fiore |
1:f155d94d6f3a | 444 | } |
Mike Fiore |
1:f155d94d6f3a | 445 | } |
Mike Fiore |
1:f155d94d6f3a | 446 | |
Mike Fiore |
1:f155d94d6f3a | 447 | int bytesWritten = 0; |
Mike Fiore |
1:f155d94d6f3a | 448 | if(timeout >= 0) { |
Mike Fiore |
1:f155d94d6f3a | 449 | Timer tmr; |
Mike Fiore |
1:f155d94d6f3a | 450 | tmr.start(); |
Mike Fiore |
1:f155d94d6f3a | 451 | do { |
Mike Fiore |
1:f155d94d6f3a | 452 | int available = io->writeable(); |
Mike Fiore |
1:f155d94d6f3a | 453 | if (available > 0) { |
Mike Fiore |
1:f155d94d6f3a | 454 | if(specialWritten < vSpecial.size()) { |
Mike Fiore |
1:f155d94d6f3a | 455 | //Check if current index is at a special character |
Mike Fiore |
1:f155d94d6f3a | 456 | if(bytesWritten == vSpecial[specialWritten]) { |
Mike Fiore |
1:f155d94d6f3a | 457 | if(available < 2) { |
Mike Fiore |
1:f155d94d6f3a | 458 | //Requires at least two bytes of space |
Mike Fiore |
1:f155d94d6f3a | 459 | wait(0.05); |
Mike Fiore |
1:f155d94d6f3a | 460 | continue; |
Mike Fiore |
1:f155d94d6f3a | 461 | } |
Mike Fiore |
1:f155d94d6f3a | 462 | //Ready to write special character |
Mike Fiore |
1:f155d94d6f3a | 463 | if(io->write(DLE)) { |
Mike Fiore |
1:f155d94d6f3a | 464 | specialWritten++; |
Mike Fiore |
1:f155d94d6f3a | 465 | if(io->write(data[bytesWritten])) { |
Mike Fiore |
1:f155d94d6f3a | 466 | bytesWritten++; |
Mike Fiore |
1:f155d94d6f3a | 467 | } |
Mike Fiore |
1:f155d94d6f3a | 468 | } else { |
Mike Fiore |
1:f155d94d6f3a | 469 | //Unable to write escape character, try again next round |
Mike Fiore |
1:f155d94d6f3a | 470 | wait(0.05); |
Mike Fiore |
1:f155d94d6f3a | 471 | } |
Mike Fiore |
1:f155d94d6f3a | 472 | } else { |
Mike Fiore |
1:f155d94d6f3a | 473 | //We want to write all the way up to the next special character |
Mike Fiore |
1:f155d94d6f3a | 474 | int relativeIndex = vSpecial[specialWritten] - bytesWritten; |
Mike Fiore |
1:f155d94d6f3a | 475 | int size = MIN(available, relativeIndex); |
Mike Fiore |
1:f155d94d6f3a | 476 | bytesWritten += io->write(&data[bytesWritten], size); |
Mike Fiore |
1:f155d94d6f3a | 477 | } |
Mike Fiore |
1:f155d94d6f3a | 478 | } else { |
Mike Fiore |
1:f155d94d6f3a | 479 | int size = MIN(available, length - bytesWritten); |
Mike Fiore |
1:f155d94d6f3a | 480 | bytesWritten += io->write(&data[bytesWritten], size); |
Mike Fiore |
1:f155d94d6f3a | 481 | } |
Mike Fiore |
1:f155d94d6f3a | 482 | } else { |
Mike Fiore |
1:f155d94d6f3a | 483 | wait(0.05); |
Mike Fiore |
1:f155d94d6f3a | 484 | } |
Mike Fiore |
1:f155d94d6f3a | 485 | } while (tmr.read_ms() <= timeout && bytesWritten < length); |
Mike Fiore |
1:f155d94d6f3a | 486 | } else { |
Mike Fiore |
1:f155d94d6f3a | 487 | for(int i = 0; i < vSpecial.size(); i++) { |
Mike Fiore |
1:f155d94d6f3a | 488 | //Write up to the special character, then write the special character |
Mike Fiore |
1:f155d94d6f3a | 489 | int size = vSpecial[i] - bytesWritten; |
Mike Fiore |
1:f155d94d6f3a | 490 | int currentWritten = io->write(&data[bytesWritten], size); |
Mike Fiore |
1:f155d94d6f3a | 491 | bytesWritten += currentWritten; |
Mike Fiore |
1:f155d94d6f3a | 492 | if(currentWritten != size) { |
Mike Fiore |
1:f155d94d6f3a | 493 | //Failed to write up to the special character. |
Mike Fiore |
1:f155d94d6f3a | 494 | return bytesWritten; |
Mike Fiore |
1:f155d94d6f3a | 495 | } |
Mike Fiore |
1:f155d94d6f3a | 496 | if(io->write(DLE) && io->write(data[bytesWritten])) { |
Mike Fiore |
1:f155d94d6f3a | 497 | bytesWritten++; |
Mike Fiore |
1:f155d94d6f3a | 498 | } else { |
Mike Fiore |
1:f155d94d6f3a | 499 | //Failed to write the special character. |
Mike Fiore |
1:f155d94d6f3a | 500 | return bytesWritten; |
Mike Fiore |
1:f155d94d6f3a | 501 | } |
Mike Fiore |
1:f155d94d6f3a | 502 | } |
Mike Fiore |
1:f155d94d6f3a | 503 | |
Mike Fiore |
1:f155d94d6f3a | 504 | bytesWritten = io->write(&data[bytesWritten], length - bytesWritten); |
Mike Fiore |
1:f155d94d6f3a | 505 | } |
Mike Fiore |
1:f155d94d6f3a | 506 | |
Mike Fiore |
1:f155d94d6f3a | 507 | return bytesWritten; |
Mike Fiore |
1:f155d94d6f3a | 508 | } |
Mike Fiore |
1:f155d94d6f3a | 509 | |
Mike Fiore |
3:04046eebaef5 | 510 | unsigned int UIP::readable() |
Mike Fiore |
1:f155d94d6f3a | 511 | { |
Mike Fiore |
1:f155d94d6f3a | 512 | if(io == NULL) { |
Mike Fiore |
1:f155d94d6f3a | 513 | printf("[WARNING] MTSBufferedIO not set\r\n"); |
Mike Fiore |
1:f155d94d6f3a | 514 | return 0; |
Mike Fiore |
1:f155d94d6f3a | 515 | } |
Mike Fiore |
1:f155d94d6f3a | 516 | if(!socketOpened && !io->readable()) { |
Mike Fiore |
1:f155d94d6f3a | 517 | printf("[WARNING] Socket is not open\r\n"); |
Mike Fiore |
1:f155d94d6f3a | 518 | return 0; |
Mike Fiore |
1:f155d94d6f3a | 519 | } |
Mike Fiore |
1:f155d94d6f3a | 520 | return io->readable(); |
Mike Fiore |
1:f155d94d6f3a | 521 | } |
Mike Fiore |
1:f155d94d6f3a | 522 | |
Mike Fiore |
3:04046eebaef5 | 523 | unsigned int UIP::writeable() |
Mike Fiore |
1:f155d94d6f3a | 524 | { |
Mike Fiore |
1:f155d94d6f3a | 525 | if(io == NULL) { |
Mike Fiore |
1:f155d94d6f3a | 526 | printf("[WARNING] MTSBufferedIO not set\r\n"); |
Mike Fiore |
1:f155d94d6f3a | 527 | return 0; |
Mike Fiore |
1:f155d94d6f3a | 528 | } |
Mike Fiore |
1:f155d94d6f3a | 529 | if(!socketOpened) { |
Mike Fiore |
1:f155d94d6f3a | 530 | printf("[WARNING] Socket is not open\r\n"); |
Mike Fiore |
1:f155d94d6f3a | 531 | return 0; |
Mike Fiore |
1:f155d94d6f3a | 532 | } |
Mike Fiore |
1:f155d94d6f3a | 533 | |
Mike Fiore |
1:f155d94d6f3a | 534 | return io->writeable(); |
Mike Fiore |
1:f155d94d6f3a | 535 | } |
Mike Fiore |
1:f155d94d6f3a | 536 | |
Mike Fiore |
3:04046eebaef5 | 537 | bool UIP::setDeviceIP(std::string address) |
Mike Fiore |
1:f155d94d6f3a | 538 | { |
Mike Fiore |
1:f155d94d6f3a | 539 | if (address.compare("DHCP") == 0) { |
Mike Fiore |
1:f155d94d6f3a | 540 | return true; |
Mike Fiore |
1:f155d94d6f3a | 541 | } else { |
Mike Fiore |
1:f155d94d6f3a | 542 | printf("[WARNING] Radio does not support static IPs, using DHCP.\n\r"); |
Mike Fiore |
1:f155d94d6f3a | 543 | return false; |
Mike Fiore |
1:f155d94d6f3a | 544 | } |
Mike Fiore |
1:f155d94d6f3a | 545 | } |
Mike Fiore |
1:f155d94d6f3a | 546 | |
Mike Fiore |
3:04046eebaef5 | 547 | void UIP::reset() |
Mike Fiore |
1:f155d94d6f3a | 548 | { |
Mike Fiore |
1:f155d94d6f3a | 549 | disconnect(); |
Mike Fiore |
1:f155d94d6f3a | 550 | Code code = sendBasicCommand("AT#RESET=0", 10000); |
Mike Fiore |
1:f155d94d6f3a | 551 | if(code != SUCCESS) { |
Mike Fiore |
1:f155d94d6f3a | 552 | printf("[ERROR] Socket Modem did not accept RESET command\n\r"); |
Mike Fiore |
1:f155d94d6f3a | 553 | } else { |
Mike Fiore |
1:f155d94d6f3a | 554 | printf("[WARNING] Socket Modem is resetting, allow 30 seconds for it to come back\n\r"); |
Mike Fiore |
1:f155d94d6f3a | 555 | } |
Mike Fiore |
1:f155d94d6f3a | 556 | } |
Mike Fiore |
1:f155d94d6f3a | 557 | |
Mike Fiore |
3:04046eebaef5 | 558 | std::string UIP::getDeviceIP() |
Mike Fiore |
1:f155d94d6f3a | 559 | { |
Mike Fiore |
1:f155d94d6f3a | 560 | return local_address; |
Mike Fiore |
1:f155d94d6f3a | 561 | } |
Mike Fiore |
1:f155d94d6f3a | 562 | |
Mike Fiore |
3:04046eebaef5 | 563 | Code UIP::echo(bool state) |
Mike Fiore |
1:f155d94d6f3a | 564 | { |
Mike Fiore |
1:f155d94d6f3a | 565 | Code code; |
Mike Fiore |
1:f155d94d6f3a | 566 | if (state) { |
Mike Fiore |
1:f155d94d6f3a | 567 | code = sendBasicCommand("ATE0", 1000); |
Mike Fiore |
1:f155d94d6f3a | 568 | echoMode = (code == SUCCESS) ? false : echoMode; |
Mike Fiore |
1:f155d94d6f3a | 569 | } else { |
Mike Fiore |
1:f155d94d6f3a | 570 | code = sendBasicCommand("ATE1", 1000); |
Mike Fiore |
1:f155d94d6f3a | 571 | echoMode = (code == SUCCESS) ? true : echoMode; |
Mike Fiore |
1:f155d94d6f3a | 572 | } |
Mike Fiore |
1:f155d94d6f3a | 573 | return code; |
Mike Fiore |
1:f155d94d6f3a | 574 | } |
Mike Fiore |
1:f155d94d6f3a | 575 | |
Mike Fiore |
3:04046eebaef5 | 576 | Code UIP::setApn(const std::string& apn) |
Mike Fiore |
1:f155d94d6f3a | 577 | { |
Mike Fiore |
1:f155d94d6f3a | 578 | Code code = sendBasicCommand("AT#APNSERV=\"" + apn + "\"", 1000); |
Mike Fiore |
1:f155d94d6f3a | 579 | if (code != SUCCESS) { |
Mike Fiore |
1:f155d94d6f3a | 580 | return code; |
Mike Fiore |
1:f155d94d6f3a | 581 | } |
Mike Fiore |
1:f155d94d6f3a | 582 | this->apn = apn; |
Mike Fiore |
1:f155d94d6f3a | 583 | return code; |
Mike Fiore |
1:f155d94d6f3a | 584 | } |
Mike Fiore |
1:f155d94d6f3a | 585 | |
Mike Fiore |
1:f155d94d6f3a | 586 | |
Mike Fiore |
3:04046eebaef5 | 587 | Code UIP::setDns(const std::string& primary, const std::string& secondary) |
Mike Fiore |
1:f155d94d6f3a | 588 | { |
Mike Fiore |
1:f155d94d6f3a | 589 | return sendBasicCommand("AT#DNS=1," + primary + "," + secondary, 1000); |
Mike Fiore |
1:f155d94d6f3a | 590 | } |
Mike Fiore |
1:f155d94d6f3a | 591 | |
Mike Fiore |
3:04046eebaef5 | 592 | bool UIP::ping(const std::string& address) |
Mike Fiore |
1:f155d94d6f3a | 593 | { |
Mike Fiore |
1:f155d94d6f3a | 594 | char buffer[256] = {0}; |
Mike Fiore |
1:f155d94d6f3a | 595 | Code code; |
Mike Fiore |
1:f155d94d6f3a | 596 | |
Mike Fiore |
1:f155d94d6f3a | 597 | code = sendBasicCommand("AT#PINGREMOTE=\"" + address + "\"", 1000); |
Mike Fiore |
1:f155d94d6f3a | 598 | if (code != SUCCESS) { |
Mike Fiore |
1:f155d94d6f3a | 599 | return false; |
Mike Fiore |
1:f155d94d6f3a | 600 | } |
Mike Fiore |
1:f155d94d6f3a | 601 | |
Mike Fiore |
1:f155d94d6f3a | 602 | sprintf(buffer, "AT#PINGNUM=%d", 1); |
Mike Fiore |
1:f155d94d6f3a | 603 | code = sendBasicCommand(buffer , 1000); |
Mike Fiore |
1:f155d94d6f3a | 604 | if (code != SUCCESS) { |
Mike Fiore |
1:f155d94d6f3a | 605 | return false; |
Mike Fiore |
1:f155d94d6f3a | 606 | } |
Mike Fiore |
1:f155d94d6f3a | 607 | |
Mike Fiore |
1:f155d94d6f3a | 608 | sprintf(buffer, "AT#PINGDELAY=%d", PINGDELAY); |
Mike Fiore |
1:f155d94d6f3a | 609 | code = sendBasicCommand(buffer , 1000); |
Mike Fiore |
1:f155d94d6f3a | 610 | if (code != SUCCESS) { |
Mike Fiore |
1:f155d94d6f3a | 611 | return false; |
Mike Fiore |
1:f155d94d6f3a | 612 | } |
Mike Fiore |
1:f155d94d6f3a | 613 | |
Mike Fiore |
1:f155d94d6f3a | 614 | std::string response; |
Mike Fiore |
1:f155d94d6f3a | 615 | for (int i = 0; i < PINGNUM; i++) { |
Mike Fiore |
1:f155d94d6f3a | 616 | response = sendCommand("AT#PING", PINGDELAY * 1000); |
Mike Fiore |
1:f155d94d6f3a | 617 | if (response.find("alive") != std::string::npos) { |
Mike Fiore |
1:f155d94d6f3a | 618 | return true; |
Mike Fiore |
1:f155d94d6f3a | 619 | } |
Mike Fiore |
1:f155d94d6f3a | 620 | } |
Mike Fiore |
1:f155d94d6f3a | 621 | return false; |
Mike Fiore |
1:f155d94d6f3a | 622 | } |
Mike Fiore |
1:f155d94d6f3a | 623 | |
Mike Fiore |
3:04046eebaef5 | 624 | Code UIP::setSocketCloseable(bool enabled) |
Mike Fiore |
1:f155d94d6f3a | 625 | { |
Mike Fiore |
1:f155d94d6f3a | 626 | if(socketCloseable == enabled) { |
Mike Fiore |
1:f155d94d6f3a | 627 | return SUCCESS; |
Mike Fiore |
1:f155d94d6f3a | 628 | } |
Mike Fiore |
1:f155d94d6f3a | 629 | |
Mike Fiore |
1:f155d94d6f3a | 630 | if(socketOpened) { |
Mike Fiore |
1:f155d94d6f3a | 631 | printf("[ERROR] socket is already opened. Can not set closeable\r\n"); |
Mike Fiore |
1:f155d94d6f3a | 632 | return ERROR; |
Mike Fiore |
1:f155d94d6f3a | 633 | } |
Mike Fiore |
1:f155d94d6f3a | 634 | |
Mike Fiore |
1:f155d94d6f3a | 635 | socketCloseable = enabled; |
Mike Fiore |
1:f155d94d6f3a | 636 | |
Mike Fiore |
1:f155d94d6f3a | 637 | return SUCCESS; |
Mike Fiore |
1:f155d94d6f3a | 638 | } |
Mike Fiore |
1:f155d94d6f3a | 639 | |
Mike Fiore |
3:04046eebaef5 | 640 | Code UIP::sendBasicCommand(const std::string& command, unsigned int timeoutMillis, char esc) |
Mike Fiore |
1:f155d94d6f3a | 641 | { |
Mike Fiore |
1:f155d94d6f3a | 642 | if(socketOpened) { |
Mike Fiore |
1:f155d94d6f3a | 643 | printf("[ERROR] socket is open. Can not send AT commands\r\n"); |
Mike Fiore |
1:f155d94d6f3a | 644 | return ERROR; |
Mike Fiore |
1:f155d94d6f3a | 645 | } |
Mike Fiore |
1:f155d94d6f3a | 646 | |
Mike Fiore |
1:f155d94d6f3a | 647 | string response = sendCommand(command, timeoutMillis, esc); |
Mike Fiore |
1:f155d94d6f3a | 648 | if (response.size() == 0) { |
Mike Fiore |
1:f155d94d6f3a | 649 | return NO_RESPONSE; |
Mike Fiore |
1:f155d94d6f3a | 650 | } else if (response.find("OK") != string::npos) { |
Mike Fiore |
1:f155d94d6f3a | 651 | return SUCCESS; |
Mike Fiore |
1:f155d94d6f3a | 652 | } else if (response.find("ERROR") != string::npos) { |
Mike Fiore |
1:f155d94d6f3a | 653 | return ERROR; |
Mike Fiore |
1:f155d94d6f3a | 654 | } else { |
Mike Fiore |
1:f155d94d6f3a | 655 | return FAILURE; |
Mike Fiore |
1:f155d94d6f3a | 656 | } |
Mike Fiore |
1:f155d94d6f3a | 657 | } |
Mike Fiore |
1:f155d94d6f3a | 658 | |
Mike Fiore |
3:04046eebaef5 | 659 | string UIP::sendCommand(const std::string& command, unsigned int timeoutMillis, char esc) |
Mike Fiore |
1:f155d94d6f3a | 660 | { |
Mike Fiore |
1:f155d94d6f3a | 661 | if(io == NULL) { |
Mike Fiore |
1:f155d94d6f3a | 662 | printf("[ERROR] MTSBufferedIO not set\r\n"); |
Mike Fiore |
1:f155d94d6f3a | 663 | return ""; |
Mike Fiore |
1:f155d94d6f3a | 664 | } |
Mike Fiore |
1:f155d94d6f3a | 665 | if(socketOpened) { |
Mike Fiore |
1:f155d94d6f3a | 666 | printf("[ERROR] socket is open. Can not send AT commands\r\n"); |
Mike Fiore |
1:f155d94d6f3a | 667 | return ""; |
Mike Fiore |
1:f155d94d6f3a | 668 | } |
Mike Fiore |
1:f155d94d6f3a | 669 | |
Mike Fiore |
1:f155d94d6f3a | 670 | io->rxClear(); |
Mike Fiore |
1:f155d94d6f3a | 671 | io->txClear(); |
Mike Fiore |
1:f155d94d6f3a | 672 | std::string result; |
Mike Fiore |
1:f155d94d6f3a | 673 | |
Mike Fiore |
1:f155d94d6f3a | 674 | //Attempt to write command |
Mike Fiore |
1:f155d94d6f3a | 675 | if(io->write(command.data(), command.size(), timeoutMillis) != command.size()) { |
Mike Fiore |
1:f155d94d6f3a | 676 | //Failed to write command |
Mike Fiore |
1:f155d94d6f3a | 677 | if (command != "AT" && command != "at") { |
Mike Fiore |
1:f155d94d6f3a | 678 | printf("[ERROR] failed to send command to radio within %d milliseconds\r\n", timeoutMillis); |
Mike Fiore |
1:f155d94d6f3a | 679 | } |
Mike Fiore |
1:f155d94d6f3a | 680 | return ""; |
Mike Fiore |
1:f155d94d6f3a | 681 | } |
Mike Fiore |
1:f155d94d6f3a | 682 | |
Mike Fiore |
1:f155d94d6f3a | 683 | //Send Escape Character |
Mike Fiore |
1:f155d94d6f3a | 684 | if (esc != 0x00) { |
Mike Fiore |
1:f155d94d6f3a | 685 | if(io->write(esc, timeoutMillis) != 1) { |
Mike Fiore |
1:f155d94d6f3a | 686 | if (command != "AT" && command != "at") { |
Mike Fiore |
1:f155d94d6f3a | 687 | printf("[ERROR] failed to send character '%c' (0x%02X) to radio within %d milliseconds\r\n", esc, esc, timeoutMillis); |
Mike Fiore |
1:f155d94d6f3a | 688 | } |
Mike Fiore |
1:f155d94d6f3a | 689 | return ""; |
Mike Fiore |
1:f155d94d6f3a | 690 | } |
Mike Fiore |
1:f155d94d6f3a | 691 | } |
Mike Fiore |
1:f155d94d6f3a | 692 | |
Mike Fiore |
1:f155d94d6f3a | 693 | int timer = 0; |
Mike Fiore |
1:f155d94d6f3a | 694 | size_t previous = 0; |
Mike Fiore |
1:f155d94d6f3a | 695 | char tmp[256]; |
Mike Fiore |
1:f155d94d6f3a | 696 | tmp[255] = 0; |
Mike Fiore |
1:f155d94d6f3a | 697 | bool started = !echoMode; |
Mike Fiore |
1:f155d94d6f3a | 698 | bool done = false; |
Mike Fiore |
1:f155d94d6f3a | 699 | do { |
Mike Fiore |
1:f155d94d6f3a | 700 | wait(0.1); |
Mike Fiore |
1:f155d94d6f3a | 701 | timer += 100; |
Mike Fiore |
1:f155d94d6f3a | 702 | |
Mike Fiore |
1:f155d94d6f3a | 703 | previous = result.size(); |
Mike Fiore |
1:f155d94d6f3a | 704 | //Make a non-blocking read call by passing timeout of zero |
Mike Fiore |
1:f155d94d6f3a | 705 | int size = io->read(tmp,255,0); //1 less than allocated (timeout is instant) |
Mike Fiore |
1:f155d94d6f3a | 706 | if(size > 0) { |
Mike Fiore |
1:f155d94d6f3a | 707 | result.append(tmp, size); |
Mike Fiore |
1:f155d94d6f3a | 708 | } |
Mike Fiore |
1:f155d94d6f3a | 709 | if(!started) { |
Mike Fiore |
1:f155d94d6f3a | 710 | //In Echo Mode (Command will have echo'd + 2 characters for \r\n) |
Mike Fiore |
1:f155d94d6f3a | 711 | if(result.size() > command.size() + 2) { |
Mike Fiore |
1:f155d94d6f3a | 712 | started = true; |
Mike Fiore |
1:f155d94d6f3a | 713 | } |
Mike Fiore |
1:f155d94d6f3a | 714 | } else { |
Mike Fiore |
1:f155d94d6f3a | 715 | done = (result.size() == previous); |
Mike Fiore |
1:f155d94d6f3a | 716 | } |
Mike Fiore |
1:f155d94d6f3a | 717 | if(timer >= timeoutMillis) { |
Mike Fiore |
1:f155d94d6f3a | 718 | if (command != "AT" && command != "at") { |
Mike Fiore |
1:f155d94d6f3a | 719 | printf("[WARNING] sendCommand [%s] timed out after %d milliseconds\r\n", command.c_str(), timeoutMillis); |
Mike Fiore |
1:f155d94d6f3a | 720 | } |
Mike Fiore |
1:f155d94d6f3a | 721 | done = true; |
Mike Fiore |
1:f155d94d6f3a | 722 | } |
Mike Fiore |
1:f155d94d6f3a | 723 | } while (!done); |
Mike Fiore |
1:f155d94d6f3a | 724 | |
Mike Fiore |
1:f155d94d6f3a | 725 | return result; |
Mike Fiore |
1:f155d94d6f3a | 726 | } |
Mike Fiore |
3:04046eebaef5 | 727 | |
Mike Fiore |
3:04046eebaef5 | 728 | Code UIP::sendSMS(const Sms& sms) |
Mike Fiore |
3:04046eebaef5 | 729 | { |
Mike Fiore |
3:04046eebaef5 | 730 | return sendSMS(sms.phoneNumber, sms.message); |
Mike Fiore |
3:04046eebaef5 | 731 | } |
Mike Fiore |
3:04046eebaef5 | 732 | |
Mike Fiore |
3:04046eebaef5 | 733 | Code UIP::sendSMS(const std::string& phoneNumber, const std::string& message) |
Mike Fiore |
3:04046eebaef5 | 734 | { |
Mike Fiore |
3:04046eebaef5 | 735 | Code code = sendBasicCommand("AT+CMGF=1", 1000); |
Mike Fiore |
3:04046eebaef5 | 736 | if (code != SUCCESS) { |
Mike Fiore |
3:04046eebaef5 | 737 | return code; |
Mike Fiore |
3:04046eebaef5 | 738 | } |
Mike Fiore |
3:04046eebaef5 | 739 | string cmd = "AT+CMGS=\"+"; |
Mike Fiore |
3:04046eebaef5 | 740 | cmd.append(phoneNumber); |
Mike Fiore |
3:04046eebaef5 | 741 | cmd.append("\""); |
Mike Fiore |
3:04046eebaef5 | 742 | string response1 = sendCommand(cmd, 1000); |
Mike Fiore |
3:04046eebaef5 | 743 | if (response1.find('>') == string::npos) { |
Mike Fiore |
3:04046eebaef5 | 744 | return NO_RESPONSE; |
Mike Fiore |
3:04046eebaef5 | 745 | } |
Mike Fiore |
3:04046eebaef5 | 746 | wait(.2); |
Mike Fiore |
3:04046eebaef5 | 747 | string response2 = sendCommand(message, 4000, CTRL_Z); |
Mike Fiore |
3:04046eebaef5 | 748 | printf("SMS Response: %s\r\n", response2.c_str()); |
Mike Fiore |
3:04046eebaef5 | 749 | if (response2.find("+CMGS:") == string::npos) { |
Mike Fiore |
3:04046eebaef5 | 750 | return FAILURE; |
Mike Fiore |
3:04046eebaef5 | 751 | } |
Mike Fiore |
3:04046eebaef5 | 752 | return SUCCESS; |
Mike Fiore |
3:04046eebaef5 | 753 | } |
Mike Fiore |
3:04046eebaef5 | 754 | |
Mike Fiore |
3:04046eebaef5 | 755 | std::vector<Cellular::Sms> UIP::getReceivedSms() |
Mike Fiore |
3:04046eebaef5 | 756 | { |
Mike Fiore |
3:04046eebaef5 | 757 | int smsNumber = 0; |
Mike Fiore |
3:04046eebaef5 | 758 | std::vector<Sms> vSms; |
Mike Fiore |
3:04046eebaef5 | 759 | std::string received = sendCommand("AT+CMGL=\"ALL\"", 4000); |
Mike Fiore |
3:04046eebaef5 | 760 | size_t pos = received.find("+CMGL: "); |
Mike Fiore |
3:04046eebaef5 | 761 | |
Mike Fiore |
3:04046eebaef5 | 762 | while (pos != std::string::npos) { |
Mike Fiore |
3:04046eebaef5 | 763 | Cellular::Sms sms; |
Mike Fiore |
3:04046eebaef5 | 764 | std::string line(Text::getLine(received, pos, pos)); |
Mike Fiore |
3:04046eebaef5 | 765 | //printf("[DEBUG] Top of SMS Parse Loop. LINE[%s]\r\n", line.c_str()); |
Mike Fiore |
3:04046eebaef5 | 766 | if(line.find("+CMGL: ") == std::string::npos) { |
Mike Fiore |
3:04046eebaef5 | 767 | continue; |
Mike Fiore |
3:04046eebaef5 | 768 | } |
Mike Fiore |
3:04046eebaef5 | 769 | |
Mike Fiore |
3:04046eebaef5 | 770 | //Start of SMS message |
Mike Fiore |
3:04046eebaef5 | 771 | std::vector<std::string> vSmsParts = Text::split(line, ','); |
Mike Fiore |
3:04046eebaef5 | 772 | if(vSmsParts.size() != 6) { |
Mike Fiore |
3:04046eebaef5 | 773 | printf("[WARNING] Expected 6 commas. SMS[%d] DATA[%s]. Continuing ...\r\n", smsNumber, line.c_str()); |
Mike Fiore |
3:04046eebaef5 | 774 | continue; |
Mike Fiore |
3:04046eebaef5 | 775 | } |
Mike Fiore |
3:04046eebaef5 | 776 | |
Mike Fiore |
3:04046eebaef5 | 777 | sms.phoneNumber = vSmsParts[2]; |
Mike Fiore |
3:04046eebaef5 | 778 | sms.timestamp = vSmsParts[4] + ", " + vSmsParts[5]; |
Mike Fiore |
3:04046eebaef5 | 779 | |
Mike Fiore |
3:04046eebaef5 | 780 | if(pos == std::string::npos) { |
Mike Fiore |
3:04046eebaef5 | 781 | printf("[WARNING] Expected SMS body. SMS[%d]. Leaving ...\r\n", smsNumber); |
Mike Fiore |
3:04046eebaef5 | 782 | break; |
Mike Fiore |
3:04046eebaef5 | 783 | } |
Mike Fiore |
3:04046eebaef5 | 784 | //Check for the start of the next SMS message |
Mike Fiore |
3:04046eebaef5 | 785 | size_t bodyEnd = received.find("\r\n+CMGL: ", pos); |
Mike Fiore |
3:04046eebaef5 | 786 | if(bodyEnd == std::string::npos) { |
Mike Fiore |
3:04046eebaef5 | 787 | //printf("[DEBUG] Parsing Last SMS. SMS[%d]\r\n", smsNumber); |
Mike Fiore |
3:04046eebaef5 | 788 | //This must be the last SMS message |
Mike Fiore |
3:04046eebaef5 | 789 | bodyEnd = received.find("\r\n\r\nOK", pos); |
Mike Fiore |
3:04046eebaef5 | 790 | } |
Mike Fiore |
3:04046eebaef5 | 791 | |
Mike Fiore |
3:04046eebaef5 | 792 | //Safety check that we found the boundary of this current SMS message |
Mike Fiore |
3:04046eebaef5 | 793 | if(bodyEnd != std::string::npos) { |
Mike Fiore |
3:04046eebaef5 | 794 | sms.message = received.substr(pos, bodyEnd - pos); |
Mike Fiore |
3:04046eebaef5 | 795 | } else { |
Mike Fiore |
3:04046eebaef5 | 796 | sms.message = received.substr(pos); |
Mike Fiore |
3:04046eebaef5 | 797 | printf("[WARNING] Expected to find end of SMS list. SMS[%d] DATA[%s].\r\n", smsNumber, sms.message.c_str()); |
Mike Fiore |
3:04046eebaef5 | 798 | } |
Mike Fiore |
3:04046eebaef5 | 799 | vSms.push_back(sms); |
Mike Fiore |
3:04046eebaef5 | 800 | pos = bodyEnd; |
Mike Fiore |
3:04046eebaef5 | 801 | //printf("[DEBUG] Parsed SMS[%d]. Starting Next at position [%d]\r\n", smsNumber, pos); |
Mike Fiore |
3:04046eebaef5 | 802 | smsNumber++; |
Mike Fiore |
3:04046eebaef5 | 803 | } |
Mike Fiore |
3:04046eebaef5 | 804 | printf("Received %d SMS\r\n", smsNumber); |
Mike Fiore |
3:04046eebaef5 | 805 | return vSms; |
Mike Fiore |
3:04046eebaef5 | 806 | } |
Mike Fiore |
3:04046eebaef5 | 807 | |
Mike Fiore |
3:04046eebaef5 | 808 | Code UIP::deleteOnlyReceivedReadSms() |
Mike Fiore |
3:04046eebaef5 | 809 | { |
Mike Fiore |
3:04046eebaef5 | 810 | return sendBasicCommand("AT+CMGD=1,1", 1000); |
Mike Fiore |
3:04046eebaef5 | 811 | } |
Mike Fiore |
3:04046eebaef5 | 812 | |
Mike Fiore |
3:04046eebaef5 | 813 | Code UIP::deleteAllReceivedSms() |
Mike Fiore |
3:04046eebaef5 | 814 | { |
Mike Fiore |
3:04046eebaef5 | 815 | return sendBasicCommand("AT+CMGD=1,4", 1000); |
Mike Fiore |
3:04046eebaef5 | 816 | } |