You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

622 lines
19 KiB

7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
5 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
5 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
  1. /**
  2. * @file TinyGsmClientMC60.h
  3. * @author Volodymyr Shymanskyy
  4. * @license LGPL-3.0
  5. * @copyright Copyright (c) 2016 Volodymyr Shymanskyy
  6. * @date Nov 2016
  7. *
  8. * @MC60 support added by Tamas Dajka 2017.10.15 - with fixes by Sara Damiano
  9. *
  10. */
  11. #ifndef SRC_TINYGSMCLIENTMC60_H_
  12. #define SRC_TINYGSMCLIENTMC60_H_
  13. // #pragma message("TinyGSM: TinyGsmClientMC60")
  14. // #define TINY_GSM_DEBUG Serial
  15. #define TINY_GSM_MUX_COUNT 6
  16. #define TINY_GSM_BUFFER_READ_NO_CHECK
  17. #include "TinyGsmBattery.tpp"
  18. #include "TinyGsmCalling.tpp"
  19. #include "TinyGsmGPRS.tpp"
  20. #include "TinyGsmModem.tpp"
  21. #include "TinyGsmSMS.tpp"
  22. #include "TinyGsmTCP.tpp"
  23. #include "TinyGsmTime.tpp"
  24. #define GSM_NL "\r\n"
  25. static const char GSM_OK[] TINY_GSM_PROGMEM = "OK" GSM_NL;
  26. static const char GSM_ERROR[] TINY_GSM_PROGMEM = "ERROR" GSM_NL;
  27. #if defined TINY_GSM_DEBUG
  28. static const char GSM_CME_ERROR[] TINY_GSM_PROGMEM = GSM_NL "+CME ERROR:";
  29. static const char GSM_CMS_ERROR[] TINY_GSM_PROGMEM = GSM_NL "+CMS ERROR:";
  30. #endif
  31. enum RegStatus {
  32. REG_NO_RESULT = -1,
  33. REG_UNREGISTERED = 0,
  34. REG_SEARCHING = 2,
  35. REG_DENIED = 3,
  36. REG_OK_HOME = 1,
  37. REG_OK_ROAMING = 5,
  38. REG_UNKNOWN = 4,
  39. };
  40. class TinyGsmMC60 : public TinyGsmModem<TinyGsmMC60>,
  41. public TinyGsmGPRS<TinyGsmMC60>,
  42. public TinyGsmTCP<TinyGsmMC60, TINY_GSM_MUX_COUNT>,
  43. public TinyGsmCalling<TinyGsmMC60>,
  44. public TinyGsmSMS<TinyGsmMC60>,
  45. public TinyGsmTime<TinyGsmMC60>,
  46. public TinyGsmBattery<TinyGsmMC60> {
  47. friend class TinyGsmModem<TinyGsmMC60>;
  48. friend class TinyGsmGPRS<TinyGsmMC60>;
  49. friend class TinyGsmTCP<TinyGsmMC60, TINY_GSM_MUX_COUNT>;
  50. friend class TinyGsmCalling<TinyGsmMC60>;
  51. friend class TinyGsmSMS<TinyGsmMC60>;
  52. friend class TinyGsmTime<TinyGsmMC60>;
  53. friend class TinyGsmBattery<TinyGsmMC60>;
  54. /*
  55. * Inner Client
  56. */
  57. public:
  58. class GsmClientMC60 : public GsmClient {
  59. friend class TinyGsmMC60;
  60. public:
  61. GsmClientMC60() {}
  62. explicit GsmClientMC60(TinyGsmMC60& modem, uint8_t mux = 0) {
  63. init(&modem, mux);
  64. }
  65. bool init(TinyGsmMC60* modem, uint8_t mux = 0) {
  66. this->at = modem;
  67. sock_available = 0;
  68. sock_connected = false;
  69. if (mux < TINY_GSM_MUX_COUNT) {
  70. this->mux = mux;
  71. } else {
  72. this->mux = (mux % TINY_GSM_MUX_COUNT);
  73. }
  74. at->sockets[this->mux] = this;
  75. return true;
  76. }
  77. public:
  78. virtual int connect(const char* host, uint16_t port, int timeout_s) {
  79. stop();
  80. TINY_GSM_YIELD();
  81. rx.clear();
  82. sock_connected = at->modemConnect(host, port, mux, false, timeout_s);
  83. return sock_connected;
  84. }
  85. TINY_GSM_CLIENT_CONNECT_OVERRIDES
  86. void stop(uint32_t maxWaitMs) {
  87. uint32_t startMillis = millis();
  88. dumpModemBuffer(maxWaitMs);
  89. at->sendAT(GF("+QICLOSE="), mux);
  90. sock_connected = false;
  91. at->waitResponse((maxWaitMs - (millis() - startMillis)), GF("CLOSED"),
  92. GF("CLOSE OK"), GF("ERROR"));
  93. }
  94. void stop() override {
  95. stop(75000L);
  96. }
  97. /*
  98. * Extended API
  99. */
  100. String remoteIP() TINY_GSM_ATTR_NOT_IMPLEMENTED;
  101. };
  102. /*
  103. * Inner Secure Client
  104. */
  105. /*
  106. class GsmClientSecureMC60 : public GsmClientMC60
  107. {
  108. public:
  109. GsmClientSecure() {}
  110. GsmClientSecure(TinyGsmMC60& modem, uint8_t mux = 0)
  111. : GsmClient(modem, mux)
  112. {}
  113. public:
  114. int connect(const char* host, uint16_t port, int timeout_s) override {
  115. stop();
  116. TINY_GSM_YIELD();
  117. rx.clear();
  118. sock_connected = at->modemConnect(host, port, mux, true, timeout_s);
  119. return sock_connected;
  120. }
  121. TINY_GSM_CLIENT_CONNECT_OVERRIDES
  122. };
  123. */
  124. /*
  125. * Constructor
  126. */
  127. public:
  128. explicit TinyGsmMC60(Stream& stream) : stream(stream) {
  129. memset(sockets, 0, sizeof(sockets));
  130. }
  131. /*
  132. * Basic functions
  133. */
  134. protected:
  135. bool initImpl(const char* pin = NULL) {
  136. DBG(GF("### TinyGSM Version:"), TINYGSM_VERSION);
  137. DBG(GF("### TinyGSM Compiled Module: TinyGsmClientMC60"));
  138. if (!testAT()) { return false; }
  139. // sendAT(GF("&FZ")); // Factory + Reset
  140. // waitResponse();
  141. sendAT(GF("E0")); // Echo Off
  142. if (waitResponse() != 1) { return false; }
  143. #ifdef TINY_GSM_DEBUG
  144. sendAT(GF("+CMEE=2")); // turn on verbose error codes
  145. #else
  146. sendAT(GF("+CMEE=0")); // turn off error codes
  147. #endif
  148. waitResponse();
  149. DBG(GF("### Modem:"), getModemName());
  150. // Enable network time synchronization
  151. sendAT(GF("+QNITZ=1"));
  152. if (waitResponse(10000L) != 1) { return false; }
  153. SimStatus ret = getSimStatus();
  154. // if the sim isn't ready and a pin has been provided, try to unlock the sim
  155. if (ret != SIM_READY && pin != NULL && strlen(pin) > 0) {
  156. simUnlock(pin);
  157. return (getSimStatus() == SIM_READY);
  158. } else {
  159. // if the sim is ready, or it's locked but no pin has been provided,
  160. // return true
  161. return (ret == SIM_READY || ret == SIM_LOCKED);
  162. }
  163. }
  164. /*
  165. * Power functions
  166. */
  167. protected:
  168. bool restartImpl(const char* pin = NULL) {
  169. if (!testAT()) { return false; }
  170. if (!setPhoneFunctionality(0)) { return false; }
  171. if (!setPhoneFunctionality(1, true)) { return false; }
  172. delay(3000);
  173. return init(pin);
  174. }
  175. bool powerOffImpl() {
  176. sendAT(GF("+QPOWD=1"));
  177. return waitResponse(GF("NORMAL POWER DOWN")) == 1;
  178. }
  179. // When entering into sleep mode is enabled, DTR is pulled up, and WAKEUP_IN
  180. // is pulled up, the module can directly enter into sleep mode.If entering
  181. // into sleep mode is enabled, DTR is pulled down, and WAKEUP_IN is pulled
  182. // down, there is a need to pull the DTR pin and the WAKEUP_IN pin up first,
  183. // and then the module can enter into sleep mode.
  184. bool sleepEnableImpl(bool enable = true) {
  185. sendAT(GF("+QSCLK="), enable);
  186. return waitResponse() == 1;
  187. }
  188. bool setPhoneFunctionalityImpl(uint8_t fun, bool reset = false) {
  189. sendAT(GF("+CFUN="), fun, reset ? ",1" : "");
  190. return waitResponse(10000L) == 1;
  191. }
  192. /*
  193. * Generic network functions
  194. */
  195. public:
  196. RegStatus getRegistrationStatus() {
  197. return (RegStatus)getRegistrationStatusXREG("CREG");
  198. }
  199. protected:
  200. bool isNetworkConnectedImpl() {
  201. RegStatus s = getRegistrationStatus();
  202. return (s == REG_OK_HOME || s == REG_OK_ROAMING);
  203. }
  204. String getLocalIPImpl() {
  205. sendAT(GF("+QILOCIP"));
  206. streamSkipUntil('\n');
  207. String res = stream.readStringUntil('\n');
  208. res.trim();
  209. return res;
  210. }
  211. /*
  212. * GPRS functions
  213. */
  214. protected:
  215. bool gprsConnectImpl(const char* apn, const char* user = NULL,
  216. const char* pwd = NULL) {
  217. gprsDisconnect();
  218. // select foreground context 0 = VIRTUAL_UART_1
  219. sendAT(GF("+QIFGCNT=0"));
  220. if (waitResponse() != 1) { return false; }
  221. // Select GPRS (=1) as the Bearer
  222. sendAT(GF("+QICSGP=1,\""), apn, GF("\",\""), user, GF("\",\""), pwd,
  223. GF("\""));
  224. if (waitResponse() != 1) { return false; }
  225. // Define PDP context - is this necessary?
  226. sendAT(GF("+CGDCONT=1,\"IP\",\""), apn, '"');
  227. waitResponse();
  228. // Activate PDP context - is this necessary?
  229. sendAT(GF("+CGACT=1,1"));
  230. waitResponse(60000L);
  231. // Select TCP/IP transfer mode - NOT transparent mode
  232. sendAT(GF("+QIMODE=0"));
  233. if (waitResponse() != 1) { return false; }
  234. // Enable multiple TCP/IP connections
  235. sendAT(GF("+QIMUX=1"));
  236. if (waitResponse() != 1) { return false; }
  237. // Modem is used as a client
  238. sendAT(GF("+QISRVC=1"));
  239. if (waitResponse() != 1) { return false; }
  240. // Start TCPIP Task and Set APN, User Name and Password
  241. sendAT("+QIREGAPP=\"", apn, "\",\"", user, "\",\"", pwd, "\"");
  242. if (waitResponse() != 1) { return false; }
  243. // Activate GPRS/CSD Context
  244. sendAT(GF("+QIACT"));
  245. if (waitResponse(60000L) != 1) { return false; }
  246. // Check that we have a local IP address
  247. if (localIP() == IPAddress(0, 0, 0, 0)) { return false; }
  248. // Set Method to Handle Received TCP/IP Data
  249. // Mode=2 - Output a notification statement:
  250. // +QIRDI: <id>,<sc>,<sid>,<num>,<len>,< tlen>
  251. sendAT(GF("+QINDI=2"));
  252. if (waitResponse() != 1) { return false; }
  253. return true;
  254. }
  255. bool gprsDisconnectImpl() {
  256. sendAT(GF("+QIDEACT")); // Deactivate the bearer context
  257. return waitResponse(60000L, GF("DEACT OK"), GF("ERROR")) == 1;
  258. }
  259. /*
  260. * SIM card functions
  261. */
  262. protected:
  263. SimStatus getSimStatusImpl(uint32_t timeout_ms = 10000L) {
  264. for (uint32_t start = millis(); millis() - start < timeout_ms;) {
  265. sendAT(GF("+CPIN?"));
  266. if (waitResponse(GF(GSM_NL "+CPIN:")) != 1) {
  267. delay(1000);
  268. continue;
  269. }
  270. int8_t status = waitResponse(GF("READY"), GF("SIM PIN"), GF("SIM PUK"),
  271. GF("NOT INSERTED"), GF("PH_SIM PIN"),
  272. GF("PH_SIM PUK"));
  273. waitResponse();
  274. switch (status) {
  275. case 2:
  276. case 3: return SIM_LOCKED;
  277. case 5:
  278. case 6: return SIM_ANTITHEFT_LOCKED;
  279. case 1: return SIM_READY;
  280. default: return SIM_ERROR;
  281. }
  282. }
  283. return SIM_ERROR;
  284. }
  285. /*
  286. * Phone Call functions
  287. */
  288. protected:
  289. // Can follow all of the phone call functions from the template
  290. /*
  291. * Messaging functions
  292. */
  293. protected:
  294. // Can follow all template functions
  295. public:
  296. /** Delete all SMS */
  297. bool deleteAllSMS() {
  298. sendAT(GF("+QMGDA=6"));
  299. if (waitResponse(waitResponse(60000L, GF("OK"), GF("ERROR")) == 1)) {
  300. return true;
  301. }
  302. return false;
  303. }
  304. /*
  305. * Time functions
  306. */
  307. protected:
  308. // Can follow the standard CCLK function in the template
  309. /*
  310. * Battery functions
  311. */
  312. // Can follow battery functions as in the template
  313. /*
  314. * Client related functions
  315. */
  316. protected:
  317. bool modemConnect(const char* host, uint16_t port, uint8_t mux,
  318. bool ssl = false, int timeout_s = 75) {
  319. if (ssl) { DBG("SSL not yet supported on this module!"); }
  320. // By default, MC60 expects IP address as 'host' parameter.
  321. // If it is a domain name, "AT+QIDNSIP=1" should be executed.
  322. // "AT+QIDNSIP=0" is for dotted decimal IP address.
  323. IPAddress addr;
  324. sendAT(GF("+QIDNSIP="),
  325. (TinyGsmIpFromString(host) == IPAddress(0, 0, 0, 0) ? 0 : 1));
  326. if (waitResponse() != 1) { return false; }
  327. uint32_t timeout_ms = ((uint32_t)timeout_s) * 1000;
  328. sendAT(GF("+QIOPEN="), mux, GF(",\""), GF("TCP"), GF("\",\""), host,
  329. GF("\","), port);
  330. int8_t rsp = waitResponse(timeout_ms, GF("CONNECT OK" GSM_NL),
  331. GF("CONNECT FAIL" GSM_NL),
  332. GF("ALREADY CONNECT" GSM_NL));
  333. return (1 == rsp);
  334. }
  335. int16_t modemSend(const void* buff, size_t len, uint8_t mux) {
  336. sendAT(GF("+QISEND="), mux, ',', (uint16_t)len);
  337. if (waitResponse(GF(">")) != 1) { return 0; }
  338. stream.write(reinterpret_cast<const uint8_t*>(buff), len);
  339. stream.flush();
  340. if (waitResponse(GF(GSM_NL "SEND OK")) != 1) { return 0; }
  341. bool allAcknowledged = false;
  342. // bool failed = false;
  343. while (!allAcknowledged) {
  344. sendAT(GF("+QISACK="), mux); // If 'mux' is not specified, MC60 returns
  345. // 'ERRROR' (for QIMUX == 1)
  346. if (waitResponse(5000L, GF(GSM_NL "+QISACK:")) != 1) {
  347. return -1;
  348. } else {
  349. streamSkipUntil(','); /** Skip total */
  350. streamSkipUntil(','); /** Skip acknowledged data size */
  351. if (streamGetIntBefore('\n') == 0) { allAcknowledged = true; }
  352. }
  353. }
  354. waitResponse(5000L);
  355. // streamSkipUntil(','); // Skip mux
  356. // return streamGetIntBefore('\n');
  357. return len; // TODO(?): verify len/ack
  358. }
  359. size_t modemRead(size_t size, uint8_t mux) {
  360. if (!sockets[mux]) return 0;
  361. // TODO(?): Does this even work????
  362. // AT+QIRD=<id>,<sc>,<sid>,<len>
  363. // id = GPRS context number = 0, set in GPRS connect
  364. // sc = role in connection = 1, client of connection
  365. // sid = index of connection = mux
  366. // len = maximum length of data to retrieve
  367. sendAT(GF("+QIRD=0,1,"), mux, ',', (uint16_t)size);
  368. // If it replies only OK for the write command, it means there is no
  369. // received data in the buffer of the connection.
  370. int8_t res = waitResponse(GF("+QIRD:"), GFP(GSM_OK), GFP(GSM_ERROR));
  371. if (res == 1) {
  372. streamSkipUntil(':'); // skip IP address
  373. streamSkipUntil(','); // skip port
  374. streamSkipUntil(','); // skip connection type (TCP/UDP)
  375. // read the real length of the retrieved data
  376. uint16_t len = streamGetIntBefore('\n');
  377. // It's possible that the real length available is less than expected
  378. // This is quite likely if the buffer is broken into packets - which may
  379. // be different sizes.
  380. // If so, make sure we make sure we re-set the amount of data available.
  381. if (len < size) { sockets[mux]->sock_available = len; }
  382. for (uint16_t i = 0; i < len; i++) {
  383. moveCharFromStreamToFifo(mux);
  384. sockets[mux]->sock_available--;
  385. // ^^ One less character available after moving from modem's FIFO to our
  386. // FIFO
  387. }
  388. waitResponse(); // ends with an OK
  389. // DBG("### READ:", len, "from", mux);
  390. return len;
  391. } else {
  392. sockets[mux]->sock_available = 0;
  393. return 0;
  394. }
  395. }
  396. // Not possible to check the number of characters remaining in buffer
  397. size_t modemGetAvailable(uint8_t) {
  398. return 0;
  399. }
  400. bool modemGetConnected(uint8_t mux) {
  401. sendAT(GF("+QISTATE=1,"), mux);
  402. // +QISTATE: 0,"TCP","151.139.237.11",80,5087,4,1,0,0,"uart1"
  403. if (waitResponse(GF("+QISTATE:")) != 1) { return false; }
  404. streamSkipUntil(','); // Skip mux
  405. streamSkipUntil(','); // Skip socket type
  406. streamSkipUntil(','); // Skip remote ip
  407. streamSkipUntil(','); // Skip remote port
  408. streamSkipUntil(','); // Skip local port
  409. int8_t res = streamGetIntBefore(','); // socket state
  410. waitResponse();
  411. // 0 Initial, 1 Opening, 2 Connected, 3 Listening, 4 Closing
  412. return 2 == res;
  413. }
  414. /*
  415. * Utilities
  416. */
  417. public:
  418. // TODO(vshymanskyy): Optimize this!
  419. int8_t waitResponse(uint32_t timeout_ms, String& data,
  420. GsmConstStr r1 = GFP(GSM_OK),
  421. GsmConstStr r2 = GFP(GSM_ERROR),
  422. #if defined TINY_GSM_DEBUG
  423. GsmConstStr r3 = GFP(GSM_CME_ERROR),
  424. GsmConstStr r4 = GFP(GSM_CMS_ERROR),
  425. #else
  426. GsmConstStr r3 = NULL, GsmConstStr r4 = NULL,
  427. #endif
  428. GsmConstStr r5 = NULL, GsmConstStr r6 = NULL) {
  429. /*String r1s(r1); r1s.trim();
  430. String r2s(r2); r2s.trim();
  431. String r3s(r3); r3s.trim();
  432. String r4s(r4); r4s.trim();
  433. String r5s(r5); r5s.trim();
  434. String r6s(r6); r6s.trim();
  435. DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s, ",", r6s);*/
  436. data.reserve(64);
  437. uint8_t index = 0;
  438. uint32_t startMillis = millis();
  439. do {
  440. TINY_GSM_YIELD();
  441. while (stream.available() > 0) {
  442. TINY_GSM_YIELD();
  443. int8_t a = stream.read();
  444. if (a <= 0) continue; // Skip 0x00 bytes, just in case
  445. data += static_cast<char>(a);
  446. if (r1 && data.endsWith(r1)) {
  447. index = 1;
  448. goto finish;
  449. } else if (r2 && data.endsWith(r2)) {
  450. index = 2;
  451. goto finish;
  452. } else if (r3 && data.endsWith(r3)) {
  453. #if defined TINY_GSM_DEBUG
  454. if (r3 == GFP(GSM_CME_ERROR)) {
  455. streamSkipUntil('\n'); // Read out the error
  456. }
  457. #endif
  458. index = 3;
  459. goto finish;
  460. } else if (r4 && data.endsWith(r4)) {
  461. index = 4;
  462. goto finish;
  463. } else if (r5 && data.endsWith(r5)) {
  464. index = 5;
  465. goto finish;
  466. } else if (r6 && data.endsWith(r6)) {
  467. index = 6;
  468. goto finish;
  469. } else if (data.endsWith(
  470. GF(GSM_NL "+QIRDI:"))) { // TODO(?): QIRD? or QIRDI?
  471. // +QIRDI: <id>,<sc>,<sid>,<num>,<len>,< tlen>
  472. streamSkipUntil(','); // Skip the context
  473. streamSkipUntil(','); // Skip the role
  474. // read the connection id
  475. int8_t mux = streamGetIntBefore(',');
  476. // read the number of packets in the buffer
  477. int8_t num_packets = streamGetIntBefore(',');
  478. // read the length of the current packet
  479. streamSkipUntil(
  480. ','); // Skip the length of the current package in the buffer
  481. int16_t len_total =
  482. streamGetIntBefore('\n'); // Total length of all packages
  483. if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux] &&
  484. num_packets >= 0 && len_total >= 0) {
  485. sockets[mux]->sock_available = len_total;
  486. }
  487. data = "";
  488. // DBG("### Got Data:", len_total, "on", mux);
  489. } else if (data.endsWith(GF("CLOSED" GSM_NL))) {
  490. int8_t nl = data.lastIndexOf(GSM_NL, data.length() - 8);
  491. int8_t coma = data.indexOf(',', nl + 2);
  492. int8_t mux = data.substring(nl + 2, coma).toInt();
  493. if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
  494. sockets[mux]->sock_connected = false;
  495. }
  496. data = "";
  497. DBG("### Closed: ", mux);
  498. } else if (data.endsWith(GF("+QNITZ:"))) {
  499. streamSkipUntil('\n'); // URC for time sync
  500. DBG("### Network time updated.");
  501. data = "";
  502. }
  503. }
  504. } while (millis() - startMillis < timeout_ms);
  505. finish:
  506. if (!index) {
  507. data.trim();
  508. if (data.length()) { DBG("### Unhandled:", data); }
  509. data = "";
  510. }
  511. // data.replace(GSM_NL, "/");
  512. // DBG('<', index, '>', data);
  513. return index;
  514. }
  515. int8_t waitResponse(uint32_t timeout_ms, GsmConstStr r1 = GFP(GSM_OK),
  516. GsmConstStr r2 = GFP(GSM_ERROR),
  517. #if defined TINY_GSM_DEBUG
  518. GsmConstStr r3 = GFP(GSM_CME_ERROR),
  519. GsmConstStr r4 = GFP(GSM_CMS_ERROR),
  520. #else
  521. GsmConstStr r3 = NULL, GsmConstStr r4 = NULL,
  522. #endif
  523. GsmConstStr r5 = NULL, GsmConstStr r6 = NULL) {
  524. String data;
  525. return waitResponse(timeout_ms, data, r1, r2, r3, r4, r5, r6);
  526. }
  527. int8_t waitResponse(GsmConstStr r1 = GFP(GSM_OK),
  528. GsmConstStr r2 = GFP(GSM_ERROR),
  529. #if defined TINY_GSM_DEBUG
  530. GsmConstStr r3 = GFP(GSM_CME_ERROR),
  531. GsmConstStr r4 = GFP(GSM_CMS_ERROR),
  532. #else
  533. GsmConstStr r3 = NULL, GsmConstStr r4 = NULL,
  534. #endif
  535. GsmConstStr r5 = NULL, GsmConstStr r6 = NULL) {
  536. return waitResponse(1000, r1, r2, r3, r4, r5, r6);
  537. }
  538. public:
  539. Stream& stream;
  540. protected:
  541. GsmClientMC60* sockets[TINY_GSM_MUX_COUNT];
  542. const char* gsmNL = GSM_NL;
  543. };
  544. #endif // SRC_TINYGSMCLIENTMC60_H_