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.

329 lines
7.5 KiB

8 years ago
8 years ago
8 years ago
6 years ago
6 years ago
  1. /**
  2. * @file TinyGsmCommon.h
  3. * @author Volodymyr Shymanskyy
  4. * @license LGPL-3.0
  5. * @copyright Copyright (c) 2016 Volodymyr Shymanskyy
  6. * @date Nov 2016
  7. */
  8. #ifndef TinyGsmCommon_h
  9. #define TinyGsmCommon_h
  10. #if defined(SPARK) || defined(PARTICLE)
  11. #include "Particle.h"
  12. #elif defined(ARDUINO)
  13. #if ARDUINO >= 100
  14. #include "Arduino.h"
  15. #else
  16. #include "WProgram.h"
  17. #endif
  18. #endif
  19. #if defined(ARDUINO_DASH)
  20. #include <ArduinoCompat/Client.h>
  21. #else
  22. #include <Client.h>
  23. #endif
  24. #include <TinyGsmFifo.h>
  25. #ifndef TINY_GSM_YIELD
  26. #define TINY_GSM_YIELD() { delay(0); }
  27. #endif
  28. #define TINY_GSM_ATTR_NOT_AVAILABLE __attribute__((error("Not available on this modem type")))
  29. #define TINY_GSM_ATTR_NOT_IMPLEMENTED __attribute__((error("Not implemented")))
  30. #if defined(__AVR__)
  31. #define TINY_GSM_PROGMEM PROGMEM
  32. typedef const __FlashStringHelper* GsmConstStr;
  33. #define GFP(x) (reinterpret_cast<GsmConstStr>(x))
  34. #define GF(x) F(x)
  35. #else
  36. #define TINY_GSM_PROGMEM
  37. typedef const char* GsmConstStr;
  38. #define GFP(x) x
  39. #define GF(x) x
  40. #endif
  41. #ifdef TINY_GSM_DEBUG
  42. namespace {
  43. template<typename T>
  44. static void DBG_PLAIN(T last) {
  45. TINY_GSM_DEBUG.println(last);
  46. }
  47. template<typename T, typename... Args>
  48. static void DBG_PLAIN(T head, Args... tail) {
  49. TINY_GSM_DEBUG.print(head);
  50. TINY_GSM_DEBUG.print(' ');
  51. DBG_PLAIN(tail...);
  52. }
  53. template<typename... Args>
  54. static void DBG(Args... args) {
  55. TINY_GSM_DEBUG.print(GF("["));
  56. TINY_GSM_DEBUG.print(millis());
  57. TINY_GSM_DEBUG.print(GF("] "));
  58. DBG_PLAIN(args...);
  59. }
  60. }
  61. #else
  62. #define DBG_PLAIN(...)
  63. #define DBG(...)
  64. #endif
  65. template<class T>
  66. const T& TinyGsmMin(const T& a, const T& b)
  67. {
  68. return (b < a) ? b : a;
  69. }
  70. template<class T>
  71. const T& TinyGsmMax(const T& a, const T& b)
  72. {
  73. return (b < a) ? a : b;
  74. }
  75. template<class T>
  76. uint32_t TinyGsmAutoBaud(T& SerialAT, uint32_t minimum = 9600, uint32_t maximum = 115200)
  77. {
  78. static uint32_t rates[] = { 115200, 57600, 38400, 19200, 9600, 74400, 74880, 230400, 460800, 2400, 4800, 14400, 28800 };
  79. for (unsigned i = 0; i < sizeof(rates)/sizeof(rates[0]); i++) {
  80. uint32_t rate = rates[i];
  81. if (rate < minimum || rate > maximum) continue;
  82. DBG("Trying baud rate", rate, "...");
  83. SerialAT.begin(rate);
  84. delay(10);
  85. for (int i=0; i<3; i++) {
  86. SerialAT.print("AT\r\n");
  87. String input = SerialAT.readString();
  88. if (input.indexOf("OK") >= 0) {
  89. DBG("Modem responded at rate", rate);
  90. return rate;
  91. }
  92. }
  93. }
  94. return 0;
  95. }
  96. static inline
  97. IPAddress TinyGsmIpFromString(const String& strIP) {
  98. int Parts[4] = {0, };
  99. int Part = 0;
  100. for (uint8_t i=0; i<strIP.length(); i++) {
  101. char c = strIP[i];
  102. if (c == '.') {
  103. Part++;
  104. if (Part > 3) {
  105. return IPAddress(0,0,0,0);
  106. }
  107. continue;
  108. } else if (c >= '0' && c <= '9') {
  109. Parts[Part] *= 10;
  110. Parts[Part] += c - '0';
  111. } else {
  112. if (Part == 3) break;
  113. }
  114. }
  115. return IPAddress(Parts[0], Parts[1], Parts[2], Parts[3]);
  116. }
  117. static inline
  118. String TinyGsmDecodeHex7bit(String &instr) {
  119. String result;
  120. byte reminder = 0;
  121. int bitstate = 7;
  122. for (unsigned i=0; i<instr.length(); i+=2) {
  123. char buf[4] = { 0, };
  124. buf[0] = instr[i];
  125. buf[1] = instr[i+1];
  126. byte b = strtol(buf, NULL, 16);
  127. byte bb = b << (7 - bitstate);
  128. char c = (bb + reminder) & 0x7F;
  129. result += c;
  130. reminder = b >> bitstate;
  131. bitstate--;
  132. if (bitstate == 0) {
  133. char c = reminder;
  134. result += c;
  135. reminder = 0;
  136. bitstate = 7;
  137. }
  138. }
  139. return result;
  140. }
  141. static inline
  142. String TinyGsmDecodeHex8bit(String &instr) {
  143. String result;
  144. for (unsigned i=0; i<instr.length(); i+=2) {
  145. char buf[4] = { 0, };
  146. buf[0] = instr[i];
  147. buf[1] = instr[i+1];
  148. char b = strtol(buf, NULL, 16);
  149. result += b;
  150. }
  151. return result;
  152. }
  153. static inline
  154. String TinyGsmDecodeHex16bit(String &instr) {
  155. String result;
  156. for (unsigned i=0; i<instr.length(); i+=4) {
  157. char buf[4] = { 0, };
  158. buf[0] = instr[i];
  159. buf[1] = instr[i+1];
  160. char b = strtol(buf, NULL, 16);
  161. if (b) { // If high byte is non-zero, we can't handle it ;(
  162. #if defined(TINY_GSM_UNICODE_TO_HEX)
  163. result += "\\x";
  164. result += instr.substring(i, i+4);
  165. #else
  166. result += "?";
  167. #endif
  168. } else {
  169. buf[0] = instr[i+2];
  170. buf[1] = instr[i+3];
  171. b = strtol(buf, NULL, 16);
  172. result += b;
  173. }
  174. }
  175. return result;
  176. }
  177. class TinyGsmModem
  178. {
  179. public:
  180. TinyGsmModem(Stream& stream)
  181. : stream(stream)
  182. {}
  183. /*
  184. * Basic functions
  185. */
  186. // Prepare the modem for further functionality
  187. virtual bool init(const char* pin = NULL) = 0;
  188. // Begin is redundant with init
  189. virtual bool begin(const char* pin = NULL) {
  190. return init(pin);
  191. }
  192. // Returns a string with the chip name
  193. virtual String getModemName() = 0;
  194. // Sets the serial communication baud rate
  195. virtual void setBaud(unsigned long baud) = 0;
  196. // Checks that the modem is responding to standard AT commands
  197. virtual bool testAT(unsigned long timeout = 10000L) = 0;
  198. // Holds open communication with the modem waiting for data to come in
  199. virtual void maintain() = 0;
  200. // Resets all modem chip settings to factor defaults
  201. virtual bool factoryDefault() = 0;
  202. // Returns the response to a get info request. The format varies by modem.
  203. virtual String getModemInfo() = 0;
  204. // Answers whether types of communication are available on this modem
  205. virtual bool hasSSL() = 0;
  206. virtual bool hasWifi() = 0;
  207. virtual bool hasGPRS() = 0;
  208. /*
  209. * Power functions
  210. */
  211. virtual bool restart() = 0;
  212. /*
  213. * SIM card functions - only apply to cellular modems
  214. */
  215. virtual bool simUnlock(const char *pin) { return false; }
  216. virtual String getSimCCID() { return ""; }
  217. virtual String getIMEI() { return ""; }
  218. virtual String getOperator() { return ""; }
  219. /*
  220. * Generic network functions
  221. */
  222. virtual int getSignalQuality() = 0;
  223. // NOTE: this returns whether the modem is registered on the cellular or WiFi
  224. // network NOT whether GPRS or other internet connections are available
  225. virtual bool isNetworkConnected() = 0;
  226. virtual bool waitForNetwork(unsigned long timeout = 60000L) {
  227. for (unsigned long start = millis(); millis() - start < timeout; ) {
  228. if (isNetworkConnected()) {
  229. return true;
  230. }
  231. delay(250);
  232. }
  233. return false;
  234. }
  235. /*
  236. * WiFi functions - only apply to WiFi modems
  237. */
  238. virtual bool networkConnect(const char* ssid, const char* pwd) { return false; }
  239. virtual bool networkDisconnect() { return false; }
  240. /*
  241. * GPRS functions - only apply to cellular modems
  242. */
  243. virtual bool gprsConnect(const char* apn, const char* user = NULL, const char* pwd = NULL) {
  244. return false;
  245. }
  246. virtual bool gprsDisconnect() { return false; }
  247. /*
  248. * IP Address functions
  249. */
  250. virtual String getLocalIP() = 0;
  251. virtual IPAddress localIP() {
  252. return TinyGsmIpFromString(getLocalIP());
  253. }
  254. /*
  255. Utilities
  256. */
  257. template<typename T>
  258. void streamWrite(T last) {
  259. stream.print(last);
  260. }
  261. template<typename T, typename... Args>
  262. void streamWrite(T head, Args... tail) {
  263. stream.print(head);
  264. streamWrite(tail...);
  265. }
  266. bool streamSkipUntil(const char c, const unsigned long timeout = 1000L) {
  267. unsigned long startMillis = millis();
  268. while (millis() - startMillis < timeout) {
  269. while (millis() - startMillis < timeout && !stream.available()) {
  270. TINY_GSM_YIELD();
  271. }
  272. if (stream.read() == c)
  273. return true;
  274. }
  275. return false;
  276. }
  277. public:
  278. Stream& stream;
  279. };
  280. #endif