A library for talking to Multi-Tech's Cellular SocketModem Devices.
Dependents: M2X_dev axeda_wrapper_dev MTS_M2x_Example1 MTS_Cellular_Connect_Example ... more
cellular/Cellular.cpp@36:bb6b293c7495, 2013-12-19 (annotated)
- Committer:
- jengbrecht
- Date:
- Thu Dec 19 16:47:26 2013 +0000
- Revision:
- 36:bb6b293c7495
- Parent:
- 33:e04aa7c013c9
- Child:
- 37:61373f492403
Added a ton more documentation to most of the headers files. Also removed the capacity and available functions from MTSBufferedIO in favor of readable and writeable. Removed the single available method call from the cellular class.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
jengbrecht | 0:563b70517320 | 1 | #ifndef CELLULAR_CPP |
jengbrecht | 0:563b70517320 | 2 | #define CELLULAR_CPP |
jengbrecht | 0:563b70517320 | 3 | |
jengbrecht | 0:563b70517320 | 4 | #include "Cellular.h" |
sgodinez | 4:6561c9128c6f | 5 | #include "MTSText.h" |
sgodinez | 19:38794784e009 | 6 | #include "MTSSerial.h" |
jengbrecht | 0:563b70517320 | 7 | |
sgodinez | 19:38794784e009 | 8 | Cellular* Cellular::instance = NULL; |
sgodinez | 19:38794784e009 | 9 | |
sgodinez | 19:38794784e009 | 10 | Cellular* Cellular::getInstance() { |
sgodinez | 19:38794784e009 | 11 | if(instance == NULL) { |
sgodinez | 19:38794784e009 | 12 | instance = new Cellular(NULL); |
sgodinez | 19:38794784e009 | 13 | } |
sgodinez | 19:38794784e009 | 14 | return instance; |
sgodinez | 19:38794784e009 | 15 | } |
sgodinez | 19:38794784e009 | 16 | |
sgodinez | 19:38794784e009 | 17 | |
sgodinez | 19:38794784e009 | 18 | Cellular* Cellular::getInstance(MTSBufferedIO* io) { |
sgodinez | 19:38794784e009 | 19 | if(instance == NULL) { |
sgodinez | 19:38794784e009 | 20 | instance = new Cellular(io); |
sgodinez | 19:38794784e009 | 21 | } |
sgodinez | 19:38794784e009 | 22 | instance->io = io; |
sgodinez | 19:38794784e009 | 23 | return instance; |
sgodinez | 19:38794784e009 | 24 | } |
sgodinez | 19:38794784e009 | 25 | |
sgodinez | 19:38794784e009 | 26 | Cellular::Cellular(MTSBufferedIO* io) |
sgodinez | 11:134435d8a2d5 | 27 | : io(io) |
sgodinez | 13:0af863114629 | 28 | , echoMode(true) |
sgodinez | 11:134435d8a2d5 | 29 | , pppConnected(false) |
sgodinez | 11:134435d8a2d5 | 30 | , mode(TCP) |
sgodinez | 11:134435d8a2d5 | 31 | , socketOpened(false) |
sgodinez | 17:2d7c4ea7491b | 32 | , socketCloseable(false) |
sgodinez | 11:134435d8a2d5 | 33 | , local_port(0) |
sgodinez | 11:134435d8a2d5 | 34 | , host_port(0) |
jengbrecht | 0:563b70517320 | 35 | { |
mfiore | 29:7408b1bdad37 | 36 | // the radio's DCD signal is mapped to PTA4 |
mfiore | 29:7408b1bdad37 | 37 | // the radio will raise and lower this line |
mfiore | 29:7408b1bdad37 | 38 | dcd = new DigitalIn(PTA4); |
mfiore | 29:7408b1bdad37 | 39 | // the DTR line to the radio is mapped PTC9 |
mfiore | 29:7408b1bdad37 | 40 | // this line should be lowered when we want to talk to the radio and raised when we're done |
mfiore | 29:7408b1bdad37 | 41 | // for now we will lower it in the constructor and raise it in the destructor |
mfiore | 29:7408b1bdad37 | 42 | dtr = new DigitalOut(PTC9); |
mfiore | 29:7408b1bdad37 | 43 | dtr->write(0); |
jengbrecht | 0:563b70517320 | 44 | } |
jengbrecht | 0:563b70517320 | 45 | |
jengbrecht | 0:563b70517320 | 46 | Cellular::~Cellular() |
jengbrecht | 0:563b70517320 | 47 | { |
mfiore | 29:7408b1bdad37 | 48 | dtr->write(1); |
jengbrecht | 0:563b70517320 | 49 | } |
jengbrecht | 0:563b70517320 | 50 | |
sgodinez | 11:134435d8a2d5 | 51 | bool Cellular::connect() { |
sgodinez | 13:0af863114629 | 52 | //Check if socket is open |
sgodinez | 13:0af863114629 | 53 | if(socketOpened) { |
sgodinez | 13:0af863114629 | 54 | return true; |
sgodinez | 13:0af863114629 | 55 | } |
sgodinez | 13:0af863114629 | 56 | |
sgodinez | 11:134435d8a2d5 | 57 | //Run Test first to validate a good state |
sgodinez | 13:0af863114629 | 58 | if(isConnected()) { |
sgodinez | 13:0af863114629 | 59 | return true; |
sgodinez | 13:0af863114629 | 60 | } |
sgodinez | 13:0af863114629 | 61 | |
sgodinez | 11:134435d8a2d5 | 62 | //Check RSSI: AT+CSQ |
sgodinez | 13:0af863114629 | 63 | int rssi = getSignalStrength(); |
sgodinez | 17:2d7c4ea7491b | 64 | printf("[DEBUG] Signal strength: %d\r\n", rssi); |
sgodinez | 13:0af863114629 | 65 | |
sgodinez | 11:134435d8a2d5 | 66 | //Check Registration: AT+CREG? == 0,1 |
sgodinez | 13:0af863114629 | 67 | Registration registration = getRegistration(); |
sgodinez | 13:0af863114629 | 68 | if(registration != REGISTERED) { |
sgodinez | 17:2d7c4ea7491b | 69 | printf("[WARNING] Not Registered [%d]\r\n", (int)registration); |
sgodinez | 13:0af863114629 | 70 | } |
sgodinez | 11:134435d8a2d5 | 71 | |
sgodinez | 11:134435d8a2d5 | 72 | //AT#CONNECTIONSTART: Make a PPP connection |
sgodinez | 17:2d7c4ea7491b | 73 | printf("[DEBUG] Making PPP Connection Attempt. APN[%s]\r\n", apn.c_str()); |
sgodinez | 13:0af863114629 | 74 | std::string pppResult = sendCommand("AT#CONNECTIONSTART", 120000); |
sgodinez | 17:2d7c4ea7491b | 75 | std::vector<std::string> parts = Text::split(pppResult, "\r\n"); |
sgodinez | 13:0af863114629 | 76 | |
sgodinez | 17:2d7c4ea7491b | 77 | //printf("[DEBUG] PPP CONNECT RESULT [%s]\r\n", pppResult.c_str()); |
sgodinez | 17:2d7c4ea7491b | 78 | // for(uint32_t i = 0; i < parts.size(); i++) { |
sgodinez | 17:2d7c4ea7491b | 79 | // printf("[%d] [%s]\r\n", i, parts[i].c_str()); |
sgodinez | 17:2d7c4ea7491b | 80 | // } |
sgodinez | 13:0af863114629 | 81 | |
sgodinez | 13:0af863114629 | 82 | if(pppResult.find("Ok_Info_GprsActivation") != std::string::npos) { |
sgodinez | 13:0af863114629 | 83 | if(parts.size() >= 2) { |
sgodinez | 13:0af863114629 | 84 | local_address = parts[1]; |
sgodinez | 13:0af863114629 | 85 | } |
sgodinez | 17:2d7c4ea7491b | 86 | printf("[INFO] PPP Connection Established: IP[%s]\r\n", local_address.c_str()); |
sgodinez | 13:0af863114629 | 87 | pppConnected = true; |
sgodinez | 13:0af863114629 | 88 | |
sgodinez | 13:0af863114629 | 89 | } else { |
sgodinez | 13:0af863114629 | 90 | pppConnected = false; |
sgodinez | 13:0af863114629 | 91 | } |
sgodinez | 11:134435d8a2d5 | 92 | |
sgodinez | 13:0af863114629 | 93 | return pppConnected; |
sgodinez | 11:134435d8a2d5 | 94 | } |
sgodinez | 11:134435d8a2d5 | 95 | |
sgodinez | 11:134435d8a2d5 | 96 | void Cellular::disconnect() { |
sgodinez | 17:2d7c4ea7491b | 97 | //AT#CONNECTIONSTOP: Close a PPP connection |
sgodinez | 17:2d7c4ea7491b | 98 | printf("[DEBUG] Closing PPP Connection\r\n"); |
sgodinez | 11:134435d8a2d5 | 99 | |
sgodinez | 17:2d7c4ea7491b | 100 | if(socketOpened) { |
sgodinez | 17:2d7c4ea7491b | 101 | close(); |
sgodinez | 17:2d7c4ea7491b | 102 | } |
sgodinez | 17:2d7c4ea7491b | 103 | |
sgodinez | 17:2d7c4ea7491b | 104 | Code code = sendBasicCommand("AT#CONNECTIONSTOP", 10000); |
sgodinez | 17:2d7c4ea7491b | 105 | if(code == OK) { |
sgodinez | 17:2d7c4ea7491b | 106 | printf("[DEBUG] Successfully closed PPP Connection\r\n"); |
sgodinez | 17:2d7c4ea7491b | 107 | } else { |
sgodinez | 17:2d7c4ea7491b | 108 | printf("[ERROR] Closing PPP Connection [%d]. Continuing ...\r\n", (int)code); |
sgodinez | 17:2d7c4ea7491b | 109 | } |
sgodinez | 17:2d7c4ea7491b | 110 | |
sgodinez | 17:2d7c4ea7491b | 111 | pppConnected = false; |
sgodinez | 11:134435d8a2d5 | 112 | } |
sgodinez | 11:134435d8a2d5 | 113 | |
sgodinez | 11:134435d8a2d5 | 114 | bool Cellular::isConnected() { |
sgodinez | 11:134435d8a2d5 | 115 | //1) Check if APN was set |
sgodinez | 11:134435d8a2d5 | 116 | if(apn.size() == 0) { |
sgodinez | 17:2d7c4ea7491b | 117 | printf("[DEBUG] APN is not set\r\n"); |
sgodinez | 11:134435d8a2d5 | 118 | return false; |
sgodinez | 11:134435d8a2d5 | 119 | } |
sgodinez | 11:134435d8a2d5 | 120 | |
sgodinez | 11:134435d8a2d5 | 121 | //1) Check that we do not have a live connection up |
sgodinez | 11:134435d8a2d5 | 122 | if(socketOpened) { |
sgodinez | 17:2d7c4ea7491b | 123 | printf("[DEBUG] Socket is opened\r\n"); |
sgodinez | 11:134435d8a2d5 | 124 | return true; |
sgodinez | 11:134435d8a2d5 | 125 | } |
sgodinez | 11:134435d8a2d5 | 126 | //2) Query the radio |
sgodinez | 11:134435d8a2d5 | 127 | pppConnected = false; |
sgodinez | 11:134435d8a2d5 | 128 | std::string result = sendCommand("AT#VSTATE", 1000); |
sgodinez | 11:134435d8a2d5 | 129 | if(result.find("CONNECTED") != std::string::npos) { |
sgodinez | 11:134435d8a2d5 | 130 | pppConnected = true; |
sgodinez | 11:134435d8a2d5 | 131 | } |
sgodinez | 11:134435d8a2d5 | 132 | |
sgodinez | 11:134435d8a2d5 | 133 | return pppConnected; |
sgodinez | 11:134435d8a2d5 | 134 | } |
sgodinez | 11:134435d8a2d5 | 135 | |
sgodinez | 11:134435d8a2d5 | 136 | bool Cellular::bind(unsigned int port) { |
sgodinez | 11:134435d8a2d5 | 137 | return false; |
sgodinez | 11:134435d8a2d5 | 138 | } |
sgodinez | 11:134435d8a2d5 | 139 | |
sgodinez | 11:134435d8a2d5 | 140 | bool Cellular::open(const std::string& address, unsigned int port, Mode mode) { |
sgodinez | 17:2d7c4ea7491b | 141 | char buffer[256] = {0}; |
sgodinez | 11:134435d8a2d5 | 142 | Code portCode, addressCode; |
sgodinez | 17:2d7c4ea7491b | 143 | printf("[DEBUG] Attempting to Open Socket\r\n"); |
sgodinez | 11:134435d8a2d5 | 144 | |
sgodinez | 11:134435d8a2d5 | 145 | //1) Check that we do not have a live connection up |
sgodinez | 11:134435d8a2d5 | 146 | if(socketOpened) { |
sgodinez | 17:2d7c4ea7491b | 147 | printf("[DEBUG] Socket already opened\r\n"); |
sgodinez | 11:134435d8a2d5 | 148 | return true; |
sgodinez | 11:134435d8a2d5 | 149 | } |
sgodinez | 11:134435d8a2d5 | 150 | |
sgodinez | 11:134435d8a2d5 | 151 | //2) Check PPP connection |
sgodinez | 11:134435d8a2d5 | 152 | if(!isConnected()) { |
sgodinez | 17:2d7c4ea7491b | 153 | printf("[ERROR] PPP not established. Attempting to connect\r\n"); |
sgodinez | 11:134435d8a2d5 | 154 | if(!connect()) { |
sgodinez | 17:2d7c4ea7491b | 155 | printf("[ERROR] PPP connection failed\r\n"); |
sgodinez | 11:134435d8a2d5 | 156 | return false; |
sgodinez | 11:134435d8a2d5 | 157 | } else { |
sgodinez | 17:2d7c4ea7491b | 158 | printf("[DEBUG] PPP connection established\r\n"); |
sgodinez | 11:134435d8a2d5 | 159 | } |
sgodinez | 11:134435d8a2d5 | 160 | } |
sgodinez | 11:134435d8a2d5 | 161 | |
sgodinez | 17:2d7c4ea7491b | 162 | ////Setup IP Connection |
sgodinez | 11:134435d8a2d5 | 163 | if(mode == TCP) { |
sgodinez | 17:2d7c4ea7491b | 164 | if(socketCloseable) { |
sgodinez | 17:2d7c4ea7491b | 165 | Code code = sendBasicCommand("AT#DLEMODE=1,0", 1000); |
sgodinez | 17:2d7c4ea7491b | 166 | if(code != OK) { |
sgodinez | 17:2d7c4ea7491b | 167 | printf("[WARNING] Unable to set socket closeable [%d]\r\n", (int) code); |
sgodinez | 17:2d7c4ea7491b | 168 | } |
sgodinez | 17:2d7c4ea7491b | 169 | } |
sgodinez | 17:2d7c4ea7491b | 170 | sprintf(buffer, "AT#TCPPORT=1,%d", port); |
sgodinez | 17:2d7c4ea7491b | 171 | portCode = sendBasicCommand(buffer, 1000); |
sgodinez | 17:2d7c4ea7491b | 172 | addressCode = sendBasicCommand("AT#TCPSERV=1,\"" + address + "\"", 1000); |
sgodinez | 11:134435d8a2d5 | 173 | } else { |
sgodinez | 17:2d7c4ea7491b | 174 | if(socketCloseable) { |
sgodinez | 17:2d7c4ea7491b | 175 | Code code = sendBasicCommand("AT#UDPDLEMODE=1", 1000); |
sgodinez | 17:2d7c4ea7491b | 176 | if(code != OK) { |
sgodinez | 17:2d7c4ea7491b | 177 | printf("[WARNING] Unable to set socket closeable [%d]\r\n", (int) code); |
sgodinez | 17:2d7c4ea7491b | 178 | } |
sgodinez | 17:2d7c4ea7491b | 179 | } |
sgodinez | 17:2d7c4ea7491b | 180 | sprintf(buffer, "AT#UDPPORT=1,%d", port); |
sgodinez | 17:2d7c4ea7491b | 181 | portCode = sendBasicCommand(buffer, 1000); |
sgodinez | 17:2d7c4ea7491b | 182 | addressCode = sendBasicCommand("AT#UDPSERV=1,\"" + address + "\"", 1000); |
sgodinez | 11:134435d8a2d5 | 183 | } |
sgodinez | 11:134435d8a2d5 | 184 | |
sgodinez | 11:134435d8a2d5 | 185 | if(portCode == OK) { |
sgodinez | 11:134435d8a2d5 | 186 | host_port = port; |
sgodinez | 11:134435d8a2d5 | 187 | } else { |
sgodinez | 17:2d7c4ea7491b | 188 | printf("[ERROR] Host port could not be set\r\n"); |
sgodinez | 11:134435d8a2d5 | 189 | } |
sgodinez | 11:134435d8a2d5 | 190 | |
sgodinez | 11:134435d8a2d5 | 191 | if(addressCode == OK) { |
sgodinez | 11:134435d8a2d5 | 192 | host_address = address; |
sgodinez | 11:134435d8a2d5 | 193 | } else { |
sgodinez | 17:2d7c4ea7491b | 194 | printf("[ERROR] Host address could not be set\r\n"); |
sgodinez | 11:134435d8a2d5 | 195 | } |
sgodinez | 11:134435d8a2d5 | 196 | |
sgodinez | 13:0af863114629 | 197 | // Try and Connect |
sgodinez | 13:0af863114629 | 198 | string response = sendCommand("AT#OTCP=1", 30000); |
sgodinez | 13:0af863114629 | 199 | if (response.find("Ok_Info_WaitingForData") != string::npos) { |
sgodinez | 17:2d7c4ea7491b | 200 | printf("[INFO] Opened TCP Socket [%s:%d]\r\n", address.c_str(), port); |
sgodinez | 13:0af863114629 | 201 | socketOpened = true; |
sgodinez | 13:0af863114629 | 202 | } else { |
sgodinez | 17:2d7c4ea7491b | 203 | printf("[WARNING] Unable to open TCP Socket [%s:%d]\r\n", address.c_str(), port); |
sgodinez | 13:0af863114629 | 204 | socketOpened = false; |
sgodinez | 13:0af863114629 | 205 | } |
sgodinez | 11:134435d8a2d5 | 206 | |
sgodinez | 13:0af863114629 | 207 | return socketOpened; |
sgodinez | 11:134435d8a2d5 | 208 | } |
sgodinez | 11:134435d8a2d5 | 209 | |
sgodinez | 11:134435d8a2d5 | 210 | bool Cellular::isOpen() { |
sgodinez | 17:2d7c4ea7491b | 211 | return socketOpened; |
sgodinez | 11:134435d8a2d5 | 212 | } |
sgodinez | 11:134435d8a2d5 | 213 | |
sgodinez | 17:2d7c4ea7491b | 214 | bool Cellular::close() { |
sgodinez | 13:0af863114629 | 215 | if(!socketOpened) { |
sgodinez | 17:2d7c4ea7491b | 216 | printf("[ERROR] Socket is not open\r\n"); |
sgodinez | 17:2d7c4ea7491b | 217 | return false; |
sgodinez | 13:0af863114629 | 218 | } |
sgodinez | 11:134435d8a2d5 | 219 | |
sgodinez | 17:2d7c4ea7491b | 220 | if(!socketCloseable) { |
sgodinez | 17:2d7c4ea7491b | 221 | printf("[ERROR] Socket is not closeable\r\n"); |
sgodinez | 17:2d7c4ea7491b | 222 | return false; |
sgodinez | 17:2d7c4ea7491b | 223 | } |
sgodinez | 17:2d7c4ea7491b | 224 | |
sgodinez | 17:2d7c4ea7491b | 225 | //Build Escape Message => ETX |
sgodinez | 17:2d7c4ea7491b | 226 | char buffer[2] = { 0x03, 0x00 }; |
sgodinez | 13:0af863114629 | 227 | Code code = sendBasicCommand(buffer, 1000, NONE); |
sgodinez | 13:0af863114629 | 228 | if(code != OK) { |
mfiore | 29:7408b1bdad37 | 229 | printf("[ERROR] Radio did not accept close socket command\r\n"); |
sgodinez | 17:2d7c4ea7491b | 230 | return false; |
sgodinez | 13:0af863114629 | 231 | } |
sgodinez | 17:2d7c4ea7491b | 232 | socketOpened = false; |
sgodinez | 17:2d7c4ea7491b | 233 | return true; |
sgodinez | 11:134435d8a2d5 | 234 | } |
sgodinez | 11:134435d8a2d5 | 235 | |
sgodinez | 11:134435d8a2d5 | 236 | int Cellular::read(char* data, int max, int timeout) { |
sgodinez | 19:38794784e009 | 237 | if(io == NULL) { |
sgodinez | 19:38794784e009 | 238 | printf("[ERROR] MTSBufferedIO not set\r\n"); |
sgodinez | 19:38794784e009 | 239 | return -1; |
sgodinez | 19:38794784e009 | 240 | } |
sgodinez | 19:38794784e009 | 241 | |
sgodinez | 17:2d7c4ea7491b | 242 | if(!socketOpened) { |
sgodinez | 17:2d7c4ea7491b | 243 | printf("[ERROR] Socket is not open\r\n"); |
sgodinez | 17:2d7c4ea7491b | 244 | return -1; |
sgodinez | 17:2d7c4ea7491b | 245 | } |
sgodinez | 17:2d7c4ea7491b | 246 | int bytesRead = 0; |
sgodinez | 32:629e6b1c8e22 | 247 | |
sgodinez | 17:2d7c4ea7491b | 248 | if(timeout >= 0) { |
sgodinez | 17:2d7c4ea7491b | 249 | Timer tmr; |
sgodinez | 17:2d7c4ea7491b | 250 | tmr.start(); |
sgodinez | 17:2d7c4ea7491b | 251 | while (tmr.read_ms() <= timeout && bytesRead < max) { |
sgodinez | 32:629e6b1c8e22 | 252 | int available = io->readable(); |
sgodinez | 32:629e6b1c8e22 | 253 | if (available > 0) { |
sgodinez | 32:629e6b1c8e22 | 254 | int size = MIN(available, max - bytesRead); |
sgodinez | 32:629e6b1c8e22 | 255 | bytesRead += io->read(&data[bytesRead], size); |
sgodinez | 17:2d7c4ea7491b | 256 | } else { |
sgodinez | 17:2d7c4ea7491b | 257 | wait(0.05); |
sgodinez | 17:2d7c4ea7491b | 258 | } |
sgodinez | 17:2d7c4ea7491b | 259 | } |
sgodinez | 17:2d7c4ea7491b | 260 | } else { |
sgodinez | 19:38794784e009 | 261 | bytesRead = io->read(data, max); |
sgodinez | 17:2d7c4ea7491b | 262 | } |
sgodinez | 17:2d7c4ea7491b | 263 | |
sgodinez | 32:629e6b1c8e22 | 264 | if(bytesRead > 0 && socketCloseable) { |
sgodinez | 32:629e6b1c8e22 | 265 | //Remove escape characters |
sgodinez | 32:629e6b1c8e22 | 266 | int index = 0; |
sgodinez | 32:629e6b1c8e22 | 267 | bool escapeFlag = false; |
sgodinez | 32:629e6b1c8e22 | 268 | for(int i = 0; i < bytesRead; i++) { |
sgodinez | 32:629e6b1c8e22 | 269 | if(data[i] == DLE || data[i] == ETX) { |
sgodinez | 32:629e6b1c8e22 | 270 | if(escapeFlag == true) { |
sgodinez | 32:629e6b1c8e22 | 271 | //This character has been escaped |
sgodinez | 32:629e6b1c8e22 | 272 | escapeFlag = false; |
sgodinez | 32:629e6b1c8e22 | 273 | } else if(data[bytesRead] == DLE) { |
sgodinez | 32:629e6b1c8e22 | 274 | //Found escape character |
sgodinez | 32:629e6b1c8e22 | 275 | escapeFlag = true; |
sgodinez | 32:629e6b1c8e22 | 276 | continue; |
sgodinez | 32:629e6b1c8e22 | 277 | } else { |
sgodinez | 32:629e6b1c8e22 | 278 | //ETX sent without escape -> Socket closed |
sgodinez | 32:629e6b1c8e22 | 279 | printf("[INFO] Read ETX character without DLE escape. Socket closed\r\n"); |
sgodinez | 32:629e6b1c8e22 | 280 | socketOpened = false; |
sgodinez | 32:629e6b1c8e22 | 281 | continue; |
sgodinez | 32:629e6b1c8e22 | 282 | } |
sgodinez | 32:629e6b1c8e22 | 283 | } |
sgodinez | 32:629e6b1c8e22 | 284 | |
sgodinez | 32:629e6b1c8e22 | 285 | if(index != i) { |
sgodinez | 32:629e6b1c8e22 | 286 | data[index] = data[i]; |
sgodinez | 32:629e6b1c8e22 | 287 | } |
sgodinez | 32:629e6b1c8e22 | 288 | index++; |
sgodinez | 32:629e6b1c8e22 | 289 | } |
sgodinez | 32:629e6b1c8e22 | 290 | bytesRead = index; |
sgodinez | 32:629e6b1c8e22 | 291 | } |
sgodinez | 32:629e6b1c8e22 | 292 | |
sgodinez | 32:629e6b1c8e22 | 293 | printf("[DEBUG] Scanning received data for socket closed message\r\n"); |
sgodinez | 32:629e6b1c8e22 | 294 | //Scan for socket closed message |
sgodinez | 32:629e6b1c8e22 | 295 | for(size_t i = 0; i < bytesRead; i++) { |
sgodinez | 32:629e6b1c8e22 | 296 | if(data[i] == 'O') { |
sgodinez | 32:629e6b1c8e22 | 297 | if(strstr(&data[i], "Ok_Info_SocketClosed")) { |
sgodinez | 32:629e6b1c8e22 | 298 | printf("[INFO] Found socket closed message. Socket closed\r\n"); |
sgodinez | 32:629e6b1c8e22 | 299 | //Close socket and Cut Off End of Message |
sgodinez | 32:629e6b1c8e22 | 300 | socketOpened = false; |
sgodinez | 32:629e6b1c8e22 | 301 | data[i] = '\0'; |
sgodinez | 32:629e6b1c8e22 | 302 | bytesRead = i; |
sgodinez | 32:629e6b1c8e22 | 303 | break; |
sgodinez | 32:629e6b1c8e22 | 304 | } |
sgodinez | 32:629e6b1c8e22 | 305 | } |
sgodinez | 32:629e6b1c8e22 | 306 | } |
sgodinez | 17:2d7c4ea7491b | 307 | return bytesRead; |
sgodinez | 11:134435d8a2d5 | 308 | } |
sgodinez | 11:134435d8a2d5 | 309 | |
sgodinez | 11:134435d8a2d5 | 310 | int Cellular::write(char* data, int length, int timeout) { |
sgodinez | 19:38794784e009 | 311 | if(io == NULL) { |
sgodinez | 19:38794784e009 | 312 | printf("[ERROR] MTSBufferedIO not set\r\n"); |
sgodinez | 19:38794784e009 | 313 | return -1; |
sgodinez | 19:38794784e009 | 314 | } |
sgodinez | 19:38794784e009 | 315 | |
sgodinez | 17:2d7c4ea7491b | 316 | if(!socketOpened) { |
sgodinez | 17:2d7c4ea7491b | 317 | printf("[ERROR] Socket is not open\r\n"); |
sgodinez | 17:2d7c4ea7491b | 318 | return -1; |
sgodinez | 17:2d7c4ea7491b | 319 | } |
sgodinez | 17:2d7c4ea7491b | 320 | |
sgodinez | 17:2d7c4ea7491b | 321 | int bytesWritten = 0; |
sgodinez | 17:2d7c4ea7491b | 322 | |
sgodinez | 17:2d7c4ea7491b | 323 | if(timeout >= 0) { |
sgodinez | 17:2d7c4ea7491b | 324 | Timer tmr; |
sgodinez | 17:2d7c4ea7491b | 325 | tmr.start(); |
sgodinez | 17:2d7c4ea7491b | 326 | while (tmr.read_ms() <= timeout && bytesWritten < length) { |
sgodinez | 19:38794784e009 | 327 | if (io->writeable()) { |
sgodinez | 19:38794784e009 | 328 | if(io->write(*data) == 1) { |
sgodinez | 17:2d7c4ea7491b | 329 | data++; |
sgodinez | 17:2d7c4ea7491b | 330 | bytesWritten++; |
sgodinez | 17:2d7c4ea7491b | 331 | } |
sgodinez | 17:2d7c4ea7491b | 332 | } else { |
sgodinez | 17:2d7c4ea7491b | 333 | wait(0.05); |
sgodinez | 17:2d7c4ea7491b | 334 | } |
sgodinez | 17:2d7c4ea7491b | 335 | } |
sgodinez | 17:2d7c4ea7491b | 336 | } else { |
sgodinez | 19:38794784e009 | 337 | bytesWritten = io->write(data, length); |
sgodinez | 17:2d7c4ea7491b | 338 | } |
sgodinez | 17:2d7c4ea7491b | 339 | |
sgodinez | 17:2d7c4ea7491b | 340 | return bytesWritten; |
sgodinez | 11:134435d8a2d5 | 341 | } |
sgodinez | 11:134435d8a2d5 | 342 | |
sgodinez | 11:134435d8a2d5 | 343 | unsigned int Cellular::readable() { |
sgodinez | 19:38794784e009 | 344 | if(io == NULL) { |
sgodinez | 19:38794784e009 | 345 | printf("[ERROR] MTSBufferedIO not set\r\n"); |
sgodinez | 19:38794784e009 | 346 | return 0; |
sgodinez | 19:38794784e009 | 347 | } |
sgodinez | 17:2d7c4ea7491b | 348 | if(!socketOpened) { |
sgodinez | 17:2d7c4ea7491b | 349 | printf("[ERROR] Socket is not open\r\n"); |
sgodinez | 17:2d7c4ea7491b | 350 | return 0; |
sgodinez | 17:2d7c4ea7491b | 351 | } |
sgodinez | 19:38794784e009 | 352 | return io->readable(); |
sgodinez | 11:134435d8a2d5 | 353 | } |
sgodinez | 11:134435d8a2d5 | 354 | |
sgodinez | 11:134435d8a2d5 | 355 | unsigned int Cellular::writeable() { |
sgodinez | 19:38794784e009 | 356 | if(io == NULL) { |
sgodinez | 19:38794784e009 | 357 | printf("[ERROR] MTSBufferedIO not set\r\n"); |
sgodinez | 19:38794784e009 | 358 | return 0; |
sgodinez | 19:38794784e009 | 359 | } |
sgodinez | 17:2d7c4ea7491b | 360 | if(!socketOpened) { |
sgodinez | 17:2d7c4ea7491b | 361 | printf("[ERROR] Socket is not open\r\n"); |
sgodinez | 17:2d7c4ea7491b | 362 | return 0; |
sgodinez | 17:2d7c4ea7491b | 363 | } |
sgodinez | 17:2d7c4ea7491b | 364 | |
sgodinez | 19:38794784e009 | 365 | return io->writeable(); |
sgodinez | 11:134435d8a2d5 | 366 | } |
sgodinez | 11:134435d8a2d5 | 367 | |
sgodinez | 11:134435d8a2d5 | 368 | void Cellular::reset() { |
mfiore | 29:7408b1bdad37 | 369 | disconnect(); |
mfiore | 29:7408b1bdad37 | 370 | Code code = sendBasicCommand("AT#RESET=0", 10000); |
mfiore | 29:7408b1bdad37 | 371 | if(code != OK) { |
mfiore | 29:7408b1bdad37 | 372 | printf("[ERROR] Socket Modem did not accept RESET command\n\r"); |
mfiore | 29:7408b1bdad37 | 373 | } else { |
mfiore | 29:7408b1bdad37 | 374 | printf("[WARNING] Socket Modem is resetting, allow 30 seconds for it to come back\n\r"); |
mfiore | 29:7408b1bdad37 | 375 | } |
sgodinez | 11:134435d8a2d5 | 376 | } |
sgodinez | 11:134435d8a2d5 | 377 | |
sgodinez | 11:134435d8a2d5 | 378 | Cellular::Code Cellular::test() |
jengbrecht | 0:563b70517320 | 379 | { |
sgodinez | 11:134435d8a2d5 | 380 | Code code = sendBasicCommand("AT", 1000); |
sgodinez | 11:134435d8a2d5 | 381 | |
sgodinez | 11:134435d8a2d5 | 382 | if(code != OK) { |
sgodinez | 11:134435d8a2d5 | 383 | printf("[Error] Failed basic AT command"); |
sgodinez | 11:134435d8a2d5 | 384 | return code; |
sgodinez | 11:134435d8a2d5 | 385 | } |
sgodinez | 11:134435d8a2d5 | 386 | |
sgodinez | 11:134435d8a2d5 | 387 | //AT#VSTATE != "CHECKING" |
sgodinez | 11:134435d8a2d5 | 388 | |
sgodinez | 11:134435d8a2d5 | 389 | //AT#GPRSMODE == |
sgodinez | 12:40ac31a09132 | 390 | return OK; |
jengbrecht | 0:563b70517320 | 391 | } |
jengbrecht | 0:563b70517320 | 392 | |
mfiore | 29:7408b1bdad37 | 393 | Cellular::Code Cellular::echo(bool state) |
jengbrecht | 0:563b70517320 | 394 | { |
sgodinez | 13:0af863114629 | 395 | Code code; |
jengbrecht | 0:563b70517320 | 396 | if (state) { |
sgodinez | 13:0af863114629 | 397 | code = sendBasicCommand("ATE0", 1000); |
sgodinez | 13:0af863114629 | 398 | echoMode = (code == OK) ? false : echoMode; |
jengbrecht | 0:563b70517320 | 399 | } else { |
sgodinez | 13:0af863114629 | 400 | code = sendBasicCommand("ATE1", 1000); |
sgodinez | 13:0af863114629 | 401 | echoMode = (code == OK) ? true : echoMode; |
jengbrecht | 0:563b70517320 | 402 | } |
sgodinez | 13:0af863114629 | 403 | return code; |
jengbrecht | 0:563b70517320 | 404 | } |
jengbrecht | 0:563b70517320 | 405 | |
jengbrecht | 0:563b70517320 | 406 | int Cellular::getSignalStrength() |
jengbrecht | 0:563b70517320 | 407 | { |
jengbrecht | 0:563b70517320 | 408 | string response = sendCommand("AT+CSQ", 1000); |
jengbrecht | 0:563b70517320 | 409 | if (response.find("OK") == string::npos) { |
jengbrecht | 0:563b70517320 | 410 | return -1; |
jengbrecht | 0:563b70517320 | 411 | } |
jengbrecht | 0:563b70517320 | 412 | int start = response.find(':'); |
jengbrecht | 0:563b70517320 | 413 | int stop = response.find(',', start); |
jengbrecht | 0:563b70517320 | 414 | string signal = response.substr(start + 2, stop - start - 2); |
jengbrecht | 0:563b70517320 | 415 | int value; |
jengbrecht | 0:563b70517320 | 416 | sscanf(signal.c_str(), "%d", &value); |
jengbrecht | 0:563b70517320 | 417 | return value; |
jengbrecht | 0:563b70517320 | 418 | } |
jengbrecht | 0:563b70517320 | 419 | |
sgodinez | 5:93e889a5abc6 | 420 | std::string Cellular::getPhoneNumber() { |
sgodinez | 5:93e889a5abc6 | 421 | return "unknown"; |
sgodinez | 5:93e889a5abc6 | 422 | } |
sgodinez | 5:93e889a5abc6 | 423 | |
jengbrecht | 0:563b70517320 | 424 | Cellular::Registration Cellular::getRegistration() |
jengbrecht | 0:563b70517320 | 425 | { |
jengbrecht | 0:563b70517320 | 426 | string response = sendCommand("AT+CREG?", 1000); |
jengbrecht | 0:563b70517320 | 427 | if (response.find("OK") == string::npos) { |
jengbrecht | 0:563b70517320 | 428 | return UNKNOWN; |
jengbrecht | 0:563b70517320 | 429 | } |
jengbrecht | 0:563b70517320 | 430 | int start = response.find(','); |
jengbrecht | 0:563b70517320 | 431 | int stop = response.find(' ', start); |
jengbrecht | 0:563b70517320 | 432 | string regStat = response.substr(start + 1, stop - start - 1); |
jengbrecht | 0:563b70517320 | 433 | int value; |
jengbrecht | 0:563b70517320 | 434 | sscanf(regStat.c_str(), "%d", &value); |
jengbrecht | 0:563b70517320 | 435 | switch (value) { |
jengbrecht | 0:563b70517320 | 436 | case 0: |
jengbrecht | 0:563b70517320 | 437 | return NOT_REGISTERED; |
jengbrecht | 0:563b70517320 | 438 | case 1: |
jengbrecht | 0:563b70517320 | 439 | return REGISTERED; |
jengbrecht | 0:563b70517320 | 440 | case 2: |
jengbrecht | 0:563b70517320 | 441 | return SEARCHING; |
jengbrecht | 0:563b70517320 | 442 | case 3: |
jengbrecht | 0:563b70517320 | 443 | return DENIED; |
jengbrecht | 0:563b70517320 | 444 | case 4: |
jengbrecht | 0:563b70517320 | 445 | return UNKNOWN; |
jengbrecht | 0:563b70517320 | 446 | case 5: |
jengbrecht | 0:563b70517320 | 447 | return ROAMING; |
jengbrecht | 0:563b70517320 | 448 | } |
sgodinez | 4:6561c9128c6f | 449 | return UNKNOWN; |
jengbrecht | 0:563b70517320 | 450 | } |
jengbrecht | 0:563b70517320 | 451 | |
jengbrecht | 0:563b70517320 | 452 | Cellular::Code Cellular::sendBasicCommand(string command, int timeoutMillis, ESC_CHAR esc) |
jengbrecht | 0:563b70517320 | 453 | { |
sgodinez | 17:2d7c4ea7491b | 454 | if(socketOpened) { |
sgodinez | 17:2d7c4ea7491b | 455 | printf("[ERROR] socket is open. Can not send AT commands\r\n"); |
sgodinez | 17:2d7c4ea7491b | 456 | return ERROR; |
sgodinez | 17:2d7c4ea7491b | 457 | } |
sgodinez | 17:2d7c4ea7491b | 458 | |
jengbrecht | 0:563b70517320 | 459 | string response = sendCommand(command, timeoutMillis, esc); |
jengbrecht | 0:563b70517320 | 460 | if (response.size() == 0) { |
jengbrecht | 0:563b70517320 | 461 | return NO_RESPONSE; |
jengbrecht | 0:563b70517320 | 462 | } else if (response.find("OK") != string::npos) { |
jengbrecht | 0:563b70517320 | 463 | return OK; |
jengbrecht | 0:563b70517320 | 464 | } else if (response.find("ERROR") != string::npos) { |
jengbrecht | 0:563b70517320 | 465 | return ERROR; |
jengbrecht | 0:563b70517320 | 466 | } else { |
jengbrecht | 0:563b70517320 | 467 | return FAILURE; |
jengbrecht | 0:563b70517320 | 468 | } |
jengbrecht | 0:563b70517320 | 469 | } |
jengbrecht | 0:563b70517320 | 470 | |
sgodinez | 11:134435d8a2d5 | 471 | Cellular::Code Cellular::setApn(const std::string& apn) { |
sgodinez | 11:134435d8a2d5 | 472 | Code code = sendBasicCommand("AT#APNSERV=\"" + apn + "\"", 1000); |
sgodinez | 11:134435d8a2d5 | 473 | if (code != OK) { |
sgodinez | 11:134435d8a2d5 | 474 | return code; |
sgodinez | 11:134435d8a2d5 | 475 | } |
sgodinez | 11:134435d8a2d5 | 476 | this->apn = apn; |
sgodinez | 11:134435d8a2d5 | 477 | return code; |
sgodinez | 11:134435d8a2d5 | 478 | } |
sgodinez | 11:134435d8a2d5 | 479 | |
jengbrecht | 27:8e6188cbcfd4 | 480 | Cellular::Code Cellular::setDns(const std::string& address) { |
sgodinez | 12:40ac31a09132 | 481 | return FAILURE; |
sgodinez | 11:134435d8a2d5 | 482 | } |
sgodinez | 11:134435d8a2d5 | 483 | |
jengbrecht | 23:bc6f98a1eb22 | 484 | bool Cellular::ping(const std::string& address) { |
jengbrecht | 23:bc6f98a1eb22 | 485 | char buffer[256] = {0}; |
jengbrecht | 23:bc6f98a1eb22 | 486 | Code code; |
jengbrecht | 23:bc6f98a1eb22 | 487 | |
jengbrecht | 23:bc6f98a1eb22 | 488 | code = sendBasicCommand("AT#PINGREMOTE=\"" + address + "\"", 1000); |
jengbrecht | 23:bc6f98a1eb22 | 489 | if (code != OK) { |
jengbrecht | 23:bc6f98a1eb22 | 490 | return false; |
jengbrecht | 23:bc6f98a1eb22 | 491 | } |
jengbrecht | 23:bc6f98a1eb22 | 492 | |
jengbrecht | 23:bc6f98a1eb22 | 493 | sprintf(buffer, "AT#PINGNUM=%d", 1); |
jengbrecht | 23:bc6f98a1eb22 | 494 | code = sendBasicCommand(buffer , 1000); |
jengbrecht | 23:bc6f98a1eb22 | 495 | if (code != OK) { |
jengbrecht | 23:bc6f98a1eb22 | 496 | return false; |
jengbrecht | 23:bc6f98a1eb22 | 497 | } |
jengbrecht | 23:bc6f98a1eb22 | 498 | |
jengbrecht | 23:bc6f98a1eb22 | 499 | sprintf(buffer, "AT#PINGDELAY=%d", PINGDELAY); |
jengbrecht | 23:bc6f98a1eb22 | 500 | code = sendBasicCommand(buffer , 1000); |
jengbrecht | 23:bc6f98a1eb22 | 501 | if (code != OK) { |
jengbrecht | 23:bc6f98a1eb22 | 502 | return false; |
jengbrecht | 23:bc6f98a1eb22 | 503 | } |
jengbrecht | 23:bc6f98a1eb22 | 504 | |
jengbrecht | 23:bc6f98a1eb22 | 505 | std::string response; |
jengbrecht | 23:bc6f98a1eb22 | 506 | for (int i = 0; i < PINGNUM; i++) { |
jengbrecht | 23:bc6f98a1eb22 | 507 | response = sendCommand("AT#PING", PINGDELAY * 1000); |
jengbrecht | 23:bc6f98a1eb22 | 508 | if (response.find("alive") != std::string::npos) { |
jengbrecht | 23:bc6f98a1eb22 | 509 | return true; |
jengbrecht | 23:bc6f98a1eb22 | 510 | } |
jengbrecht | 23:bc6f98a1eb22 | 511 | } |
jengbrecht | 23:bc6f98a1eb22 | 512 | return false; |
jengbrecht | 23:bc6f98a1eb22 | 513 | } |
jengbrecht | 23:bc6f98a1eb22 | 514 | |
sgodinez | 17:2d7c4ea7491b | 515 | Cellular::Code Cellular::setSocketCloseable(bool enabled) { |
sgodinez | 17:2d7c4ea7491b | 516 | if(socketCloseable == enabled) { |
sgodinez | 17:2d7c4ea7491b | 517 | return OK; |
sgodinez | 17:2d7c4ea7491b | 518 | } |
sgodinez | 17:2d7c4ea7491b | 519 | |
sgodinez | 17:2d7c4ea7491b | 520 | if(socketOpened) { |
sgodinez | 17:2d7c4ea7491b | 521 | printf("[ERROR] socket is already opened. Can not set closeable\r\n"); |
sgodinez | 17:2d7c4ea7491b | 522 | return ERROR; |
sgodinez | 17:2d7c4ea7491b | 523 | } |
sgodinez | 17:2d7c4ea7491b | 524 | |
sgodinez | 17:2d7c4ea7491b | 525 | socketCloseable = enabled; |
sgodinez | 17:2d7c4ea7491b | 526 | |
sgodinez | 17:2d7c4ea7491b | 527 | return OK; |
sgodinez | 17:2d7c4ea7491b | 528 | } |
sgodinez | 17:2d7c4ea7491b | 529 | |
sgodinez | 4:6561c9128c6f | 530 | Cellular::Code Cellular::sendSMS(const Sms& sms) { |
sgodinez | 4:6561c9128c6f | 531 | return sendSMS(sms.phoneNumber, sms.message); |
sgodinez | 4:6561c9128c6f | 532 | } |
sgodinez | 4:6561c9128c6f | 533 | |
sgodinez | 4:6561c9128c6f | 534 | Cellular::Code Cellular::sendSMS(const std::string& phoneNumber, const std::string& message) |
sgodinez | 17:2d7c4ea7491b | 535 | { |
jengbrecht | 0:563b70517320 | 536 | Code code = sendBasicCommand("AT+CMGF=1", 1000); |
jengbrecht | 0:563b70517320 | 537 | if (code != OK) { |
jengbrecht | 0:563b70517320 | 538 | return code; |
jengbrecht | 0:563b70517320 | 539 | } |
jengbrecht | 0:563b70517320 | 540 | string cmd = "AT+CMGS=\"+"; |
jengbrecht | 0:563b70517320 | 541 | cmd.append(phoneNumber); |
jengbrecht | 0:563b70517320 | 542 | cmd.append("\""); |
jengbrecht | 0:563b70517320 | 543 | string response1 = sendCommand(cmd, 1000); |
jengbrecht | 0:563b70517320 | 544 | if (response1.find('>') == string::npos) { |
jengbrecht | 0:563b70517320 | 545 | return NO_RESPONSE; |
jengbrecht | 0:563b70517320 | 546 | } |
jengbrecht | 0:563b70517320 | 547 | wait(.2); |
jengbrecht | 0:563b70517320 | 548 | string response2 = sendCommand(message, 4000, CTRL_Z); |
sgodinez | 17:2d7c4ea7491b | 549 | printf("SMS Response: %s\r\n", response2.c_str()); |
jengbrecht | 0:563b70517320 | 550 | if (response2.find("+CMGS:") == string::npos) { |
jengbrecht | 0:563b70517320 | 551 | return FAILURE; |
jengbrecht | 0:563b70517320 | 552 | } |
jengbrecht | 0:563b70517320 | 553 | return OK; |
jengbrecht | 0:563b70517320 | 554 | } |
jengbrecht | 0:563b70517320 | 555 | |
sgodinez | 4:6561c9128c6f | 556 | std::vector<Cellular::Sms> Cellular::getReceivedSms() { |
sgodinez | 9:5b12c5a8dde4 | 557 | int smsNumber = 0; |
sgodinez | 4:6561c9128c6f | 558 | std::vector<Sms> vSms; |
sgodinez | 4:6561c9128c6f | 559 | std::string received = sendCommand("AT+CMGL=\"ALL\"", 4000); |
sgodinez | 5:93e889a5abc6 | 560 | size_t pos = received.find("+CMGL: "); |
sgodinez | 4:6561c9128c6f | 561 | |
sgodinez | 5:93e889a5abc6 | 562 | while (pos != std::string::npos) { |
sgodinez | 4:6561c9128c6f | 563 | Cellular::Sms sms; |
sgodinez | 4:6561c9128c6f | 564 | std::string line(Text::getLine(received, pos, pos)); |
sgodinez | 17:2d7c4ea7491b | 565 | //printf("[DEBUG] Top of SMS Parse Loop. LINE[%s]\r\n", line.c_str()); |
sgodinez | 9:5b12c5a8dde4 | 566 | if(line.find("+CMGL: ") == std::string::npos) { |
sgodinez | 4:6561c9128c6f | 567 | continue; |
sgodinez | 4:6561c9128c6f | 568 | } |
sgodinez | 4:6561c9128c6f | 569 | |
sgodinez | 4:6561c9128c6f | 570 | //Start of SMS message |
sgodinez | 4:6561c9128c6f | 571 | std::vector<std::string> vSmsParts = Text::split(line, ','); |
sgodinez | 4:6561c9128c6f | 572 | if(vSmsParts.size() != 6) { |
sgodinez | 17:2d7c4ea7491b | 573 | printf("[WARNING] Expected 6 commas. SMS[%d] DATA[%s]. Continuing ...\r\n", smsNumber, line.c_str()); |
sgodinez | 4:6561c9128c6f | 574 | continue; |
sgodinez | 4:6561c9128c6f | 575 | } |
sgodinez | 4:6561c9128c6f | 576 | |
sgodinez | 4:6561c9128c6f | 577 | sms.phoneNumber = vSmsParts[2]; |
sgodinez | 4:6561c9128c6f | 578 | sms.timestamp = vSmsParts[4] + ", " + vSmsParts[5]; |
sgodinez | 4:6561c9128c6f | 579 | |
sgodinez | 8:3fe68d6130a8 | 580 | if(pos == std::string::npos) { |
sgodinez | 17:2d7c4ea7491b | 581 | printf("[WARNING] Expected SMS body. SMS[%d]. Leaving ...\r\n", smsNumber); |
sgodinez | 8:3fe68d6130a8 | 582 | break; |
sgodinez | 8:3fe68d6130a8 | 583 | } |
sgodinez | 9:5b12c5a8dde4 | 584 | //Check for the start of the next SMS message |
sgodinez | 9:5b12c5a8dde4 | 585 | size_t bodyEnd = received.find("\r\n+CMGL: ", pos); |
sgodinez | 8:3fe68d6130a8 | 586 | if(bodyEnd == std::string::npos) { |
sgodinez | 17:2d7c4ea7491b | 587 | //printf("[DEBUG] Parsing Last SMS. SMS[%d]\r\n", smsNumber); |
sgodinez | 9:5b12c5a8dde4 | 588 | //This must be the last SMS message |
sgodinez | 9:5b12c5a8dde4 | 589 | bodyEnd = received.find("\r\n\r\nOK", pos); |
sgodinez | 8:3fe68d6130a8 | 590 | } |
sgodinez | 9:5b12c5a8dde4 | 591 | |
sgodinez | 9:5b12c5a8dde4 | 592 | //Safety check that we found the boundary of this current SMS message |
sgodinez | 9:5b12c5a8dde4 | 593 | if(bodyEnd != std::string::npos) { |
sgodinez | 9:5b12c5a8dde4 | 594 | sms.message = received.substr(pos, bodyEnd - pos); |
sgodinez | 9:5b12c5a8dde4 | 595 | } else { |
sgodinez | 8:3fe68d6130a8 | 596 | sms.message = received.substr(pos); |
sgodinez | 17:2d7c4ea7491b | 597 | printf("[WARNING] Expected to find end of SMS list. SMS[%d] DATA[%s].\r\n", smsNumber, sms.message.c_str()); |
sgodinez | 8:3fe68d6130a8 | 598 | } |
sgodinez | 5:93e889a5abc6 | 599 | vSms.push_back(sms); |
sgodinez | 4:6561c9128c6f | 600 | pos = bodyEnd; |
sgodinez | 17:2d7c4ea7491b | 601 | //printf("[DEBUG] Parsed SMS[%d]. Starting Next at position [%d]\r\n", smsNumber, pos); |
sgodinez | 9:5b12c5a8dde4 | 602 | smsNumber++; |
sgodinez | 4:6561c9128c6f | 603 | } |
sgodinez | 17:2d7c4ea7491b | 604 | printf("Received %d SMS\r\n", smsNumber); |
sgodinez | 4:6561c9128c6f | 605 | return vSms; |
sgodinez | 4:6561c9128c6f | 606 | } |
sgodinez | 4:6561c9128c6f | 607 | |
sgodinez | 4:6561c9128c6f | 608 | Cellular::Code Cellular::deleteOnlyReceivedReadSms() { |
sgodinez | 4:6561c9128c6f | 609 | return sendBasicCommand("AT+CMGD=1,1", 1000); |
sgodinez | 4:6561c9128c6f | 610 | } |
sgodinez | 4:6561c9128c6f | 611 | |
sgodinez | 4:6561c9128c6f | 612 | Cellular::Code Cellular::deleteAllReceivedSms() { |
sgodinez | 4:6561c9128c6f | 613 | return sendBasicCommand("AT+CMGD=1,4", 1000); |
sgodinez | 4:6561c9128c6f | 614 | } |
sgodinez | 4:6561c9128c6f | 615 | |
sgodinez | 4:6561c9128c6f | 616 | |
jengbrecht | 0:563b70517320 | 617 | string Cellular::sendCommand(string command, int timeoutMillis, ESC_CHAR esc) |
jengbrecht | 0:563b70517320 | 618 | { |
sgodinez | 19:38794784e009 | 619 | if(io == NULL) { |
sgodinez | 19:38794784e009 | 620 | printf("[ERROR] MTSBufferedIO not set\r\n"); |
sgodinez | 19:38794784e009 | 621 | return ""; |
sgodinez | 19:38794784e009 | 622 | } |
sgodinez | 17:2d7c4ea7491b | 623 | if(socketOpened) { |
sgodinez | 17:2d7c4ea7491b | 624 | printf("[ERROR] socket is open. Can not send AT commands\r\n"); |
sgodinez | 17:2d7c4ea7491b | 625 | return ""; |
sgodinez | 17:2d7c4ea7491b | 626 | } |
sgodinez | 17:2d7c4ea7491b | 627 | |
jengbrecht | 0:563b70517320 | 628 | int size = command.size() + 1; |
jengbrecht | 0:563b70517320 | 629 | char cmd[size]; |
jengbrecht | 0:563b70517320 | 630 | strcpy(cmd, command.c_str()); |
jengbrecht | 0:563b70517320 | 631 | if (esc == CR) { |
jengbrecht | 0:563b70517320 | 632 | cmd[size -1] = '\r'; |
jengbrecht | 0:563b70517320 | 633 | } else if (esc == CTRL_Z) { |
jengbrecht | 0:563b70517320 | 634 | cmd[size -1] = 0x1A; |
sgodinez | 13:0af863114629 | 635 | } else if(esc == NONE) { |
sgodinez | 13:0af863114629 | 636 | cmd[size -1] = '\0'; |
jengbrecht | 0:563b70517320 | 637 | } |
jengbrecht | 0:563b70517320 | 638 | |
sgodinez | 19:38794784e009 | 639 | io->rxClear(); |
sgodinez | 19:38794784e009 | 640 | io->txClear(); |
sgodinez | 8:3fe68d6130a8 | 641 | std::string result; |
sgodinez | 19:38794784e009 | 642 | int status = io->write(cmd, size); |
jengbrecht | 36:bb6b293c7495 | 643 | int available = io->readable(); |
jengbrecht | 0:563b70517320 | 644 | int previous = -1; |
jengbrecht | 0:563b70517320 | 645 | int timer = 0; |
sgodinez | 8:3fe68d6130a8 | 646 | char tmp[256]; |
sgodinez | 8:3fe68d6130a8 | 647 | tmp[255] = 0; |
sgodinez | 13:0af863114629 | 648 | bool started = !echoMode; |
sgodinez | 13:0af863114629 | 649 | bool done = false; |
sgodinez | 8:3fe68d6130a8 | 650 | do { |
jengbrecht | 0:563b70517320 | 651 | wait(.1); |
jengbrecht | 0:563b70517320 | 652 | timer = timer + 100; |
jengbrecht | 0:563b70517320 | 653 | previous = available; |
sgodinez | 19:38794784e009 | 654 | available = io->rxAvailable(); |
sgodinez | 8:3fe68d6130a8 | 655 | |
sgodinez | 19:38794784e009 | 656 | int size = io->read(tmp,255); //1 less than allocated |
sgodinez | 8:3fe68d6130a8 | 657 | if(size > 0) { |
sgodinez | 8:3fe68d6130a8 | 658 | result.append(tmp, size); |
sgodinez | 8:3fe68d6130a8 | 659 | } |
sgodinez | 13:0af863114629 | 660 | |
sgodinez | 13:0af863114629 | 661 | if(!started) { |
sgodinez | 13:0af863114629 | 662 | //In Echo Mode (Command will have echo'd + 2 characters for \r\n) |
sgodinez | 13:0af863114629 | 663 | if(result.size() > command.size() + 2) { |
sgodinez | 13:0af863114629 | 664 | started = true; |
sgodinez | 13:0af863114629 | 665 | } |
sgodinez | 13:0af863114629 | 666 | } else { |
sgodinez | 13:0af863114629 | 667 | done = (available == previous); |
sgodinez | 13:0af863114629 | 668 | } |
sgodinez | 13:0af863114629 | 669 | if(timer >= timeoutMillis) { |
sgodinez | 17:2d7c4ea7491b | 670 | printf("[WARNING] sendCommand timed out after %d milliseconds\r\n", timeoutMillis); |
sgodinez | 13:0af863114629 | 671 | done = true; |
sgodinez | 13:0af863114629 | 672 | } |
sgodinez | 13:0af863114629 | 673 | } while (!done); |
sgodinez | 8:3fe68d6130a8 | 674 | |
sgodinez | 8:3fe68d6130a8 | 675 | return result; |
jengbrecht | 0:563b70517320 | 676 | } |
jengbrecht | 0:563b70517320 | 677 | |
jengbrecht | 0:563b70517320 | 678 | #endif /* CELLULAR_CPP */ |