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

Committer:
mfiore
Date:
Tue Sep 02 18:38:55 2014 +0000
Revision:
152:9a2c7ed27744
Parent:
148:df9feef182b4
Wifi: fix compatibility break with old shields by checking for both old and new style responses to "show connection" command

Who changed what in which revision?

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