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.

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