├── LICENSE ├── README_CN.md ├── ReadMe.md ├── examples ├── SIM808_CallUp │ └── SIM808_CallUp.ino ├── SIM808_GetGPS │ └── SIM808_GetGPS.ino ├── SIM808_LoopHandle │ └── SIM808_LoopHandle.ino ├── SIM808_SMSread │ └── SIM808_SMSread.ino ├── SIM808_SendSMS │ └── SIM808_SendSMS.ino └── SIM808_TCPConnection │ └── SIM808_TCPConnection.ino ├── keywords.txt ├── library.properties ├── resources └── images │ └── SIM808.png └── src ├── DFRobot_SIM808.cpp ├── DFRobot_SIM808.h ├── sim808.cpp └── sim808.h /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2010 DFRobot Co.Ltd 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README_CN.md: -------------------------------------------------------------------------------- 1 | # DFRobot_SIM808 2 | * [English Version](./README.md) 3 | 4 | SIM808 GPS/GPRS/GSM 是一款集成了四频段GSM/GPRS和GPS导航技术的Arduino扩展板。尺寸仅与一块信用卡相当,符合标准Arduino管脚分装,兼容Arduino UNO、 Leonardo、Mega等主控器。 SIM808相比上一代的SIM908在性能和稳定性上做了一定提升,除了正常的短信和电话功能外,还支持彩信、DTMF、FTP等功能。可以实现数据采集,无线数据收发等物联网应用。板载麦克风和耳机接口,节约了用户的使用成本,更加简单和方便,还可以通过外接天线接口直连GSM和GPS天线。 SIM808 GPS/GPRS/GSM Shield V1.0采用Simcom最新版SIM808模块,与市面上现有的SIM808模块相比,新版的模块具有更好的稳定性。 5 | 6 | ![产品实物图](./resources/images/SIM808.png) 7 | 8 | 9 | ## 产品链接 (https://www.dfrobot.com.cn/goods-1278.html) 10 | SKU: TEL0097 11 | 12 | 13 | ## 目录 14 | 15 | * [概述](#概述) 16 | * [库安装](#库安装) 17 | * [方法](#方法) 18 | * [兼容性](#兼容性) 19 | * [历史](#历史) 20 | * [创作者](#创作者) 21 | 22 | 23 | ## 概述 24 | 25 | * 发送和接收GPRS数据(TCP/IP, HTTP等) 26 | * 接收GPS数据和A-GPS数据 27 | * 发送和接收短信 28 | * 打电话和接电话 29 | 30 | 31 | ## 库安装 32 | 33 | 要使用这个库, 首先下载库文件, 将其粘贴到\Arduino\libraries目录中, 然后打开示例文件夹并在文件夹中运行演示。 34 | 35 | 36 | ## 方法 37 | 38 | ```C++ 39 | 40 | /** 41 | * @fn DFRobot_SIM808 42 | * @brief Constructor 43 | * @param mySerial serial ports for communication, supporting hard and soft serial ports 44 | * @n Tx, rx, and baudRate can also be passed in this order 45 | * @return None 46 | */ 47 | DFRobot_SIM808(SoftwareSerial *mySerial); 48 | DFRobot_SIM808(HardwareSerial *mySerial); 49 | DFRobot_SIM808(uint8_t tx, uint8_t rx, uint32_t baudRate = 9600); 50 | 51 | /** 52 | * @fn getInstance 53 | * @brief get instance of DFRobot_SIM808 class 54 | * @return instance of DFRobot_SIM808 class 55 | */ 56 | static DFRobot_SIM808* getInstance() { return inst; }; 57 | 58 | /** 59 | * @fn init 60 | * @brief initialize DFRobot_SIM808 module including SIM card check & signal strength 61 | * @return true if connected, false otherwise 62 | */ 63 | bool init(void); 64 | 65 | /** 66 | * @fn checkPowerUp 67 | * @brief check if DFRobot_SIM808 module is powered on or not 68 | * @return true on success, false on error 69 | */ 70 | bool checkPowerUp(void); 71 | 72 | /** 73 | * @fn powerUpDown 74 | * @brief power Up DFRobot_SIM808 module (JP has to be soldered) 75 | * @param pin pin 9 connected to JP jumper so we can power up and down through software 76 | * @return None 77 | */ 78 | void powerUpDown(uint8_t pin); 79 | 80 | /** 81 | * @fn powerReset 82 | * @brief power reset for SIM800 board 83 | * @param pin (preconfigurated as OUTPUT) 84 | * @return None 85 | */ 86 | void powerReset(uint8_t pin); 87 | 88 | /** 89 | * @fn sendSMS 90 | * @brief send text SMS 91 | * @param number phone number which SMS will be send to 92 | * @param data message that will be send to 93 | * @return true on success, false on error 94 | */ 95 | bool sendSMS(char* number, char* data); 96 | 97 | /** 98 | * @fn isSMSunread 99 | * @brief Check if there is any UNREAD SMS: this function DOESN'T change the UNREAD status of the SMS 100 | * @return returned value 101 | * @retval 1~20 - on success, position/index where SMS is stored, suitable for the function ReadSMS 102 | * @retval -1 - on error 103 | * @retval 0 - there is no SMS with specified status (UNREAD) 104 | */ 105 | char isSMSunread(void); 106 | 107 | /** 108 | * @fn readSMS 109 | * @brief read SMS, phone and date if getting a SMS message. It changes SMS status to READ 110 | * @param messageIndex SIM position to read 111 | * @param message buffer used to get SMS message 112 | * @param length length of message buffer 113 | * @param phone buffer used to get SMS's sender phone number 114 | * @param datetime buffer used to get SMS's send datetime 115 | * @return true on success, false on error 116 | */ 117 | bool readSMS(int messageIndex, char *message, int length, char *phone, char *datetime); 118 | 119 | /** 120 | * @fn readSMS 121 | * @brief read SMS if getting a SMS message 122 | * @param buffer buffer that get from DFRobot_SIM808 module(when getting a SMS, DFRobot_SIM808 module will return a buffer array) 123 | * @param message buffer used to get SMS message 124 | * @param check whether to check phone number(we may only want to read SMS from specified phone number) 125 | * @return true on success, false on error 126 | */ 127 | bool readSMS(int messageIndex, char *message, int length); 128 | 129 | /** 130 | * @fn deleteSMS 131 | * @brief delete SMS message on SIM card 132 | * @param index the index number which SMS message will be delete 133 | * @return true on success, false on error 134 | */ 135 | bool deleteSMS(int index); 136 | 137 | /** 138 | * @fn callUp 139 | * @brief call someone 140 | * @param number the phone number which you want to call 141 | * @return true on success, false on error 142 | */ 143 | bool callUp(char* number); 144 | 145 | /** 146 | * @fn answer 147 | * @brief auto answer if coming a call 148 | * @return None 149 | */ 150 | void answer(void); 151 | 152 | /** 153 | * @fn hangup 154 | * @brief hang up if coming a call 155 | * @return true on success, false on error 156 | */ 157 | bool hangup(void); 158 | 159 | /** 160 | * @fn disableCLIPring 161 | * @brief Disable +CLIP notification when an incoming call is active, RING text is always shown. See isCallActive function 162 | * @note This is done in order no to overload serial outputCheck if there is a call active and get the phone number in that case 163 | * @return true on success, false on error 164 | */ 165 | bool disableCLIPring(void); 166 | 167 | /** 168 | * @fn getSubscriberNumber 169 | * @brief Get Subscriber Number (your number) using AT+CNUM command, but if nothing return, then 170 | * @n you need to command this to your SIM900. (See AT+CPBS, AT+CPBW) 171 | * @n AT+CPBS="ON" 172 | * @n AT+CPBW=1,"+{Your Number}",145 173 | * @n AT+CPBS="SM" 174 | * @param number your phone number 175 | * @return true on success, false on error 176 | */ 177 | bool getSubscriberNumber(char *number); 178 | 179 | /** 180 | * @fn isCallActive 181 | * @brief Check if there is a call active and get the phone number in that case 182 | * @param number Check if there is a call active and get the phone number in that case 183 | * @return true on success, false on error 184 | */ 185 | bool isCallActive(char *number); 186 | 187 | /** 188 | * @fn getDateTime 189 | * @brief get DateTime from SIM900 (see AT command: AT+CLTS=1) as string 190 | * @param buffer DateTime from SIM900 191 | * @return true on success, false on error 192 | * @note If it doesn't work may be for two reasons: 193 | * @n 1. Your carrier doesn't give that information 194 | * @n 2. You have to configurate the SIM900 IC. 195 | * @n - First with SIM900_Serial_Debug example try this AT command: AT+CLTS? 196 | * @n - If response is 0, then it is disabled. 197 | * @n - Enable it by: AT+CLTS=1 198 | * @n - Now you have to save this config to EEPROM memory of SIM900 IC by: AT&W 199 | * @n - Now, you have to power down and power up again the SIM900 200 | * @n - Try now again: AT+CCLK? 201 | * @n - It should work now 202 | * 203 | */ 204 | bool getDateTime(char *buffer); 205 | 206 | /** 207 | * @fn getSignalStrength 208 | * @brief get Signal Strength from SIM900 (see AT command: AT+CSQ) as integer 209 | * @param buffer Signal Strength 210 | * @return true on success, false on error 211 | */ 212 | bool getSignalStrength(int *buffer); 213 | 214 | /** 215 | * @fn sendUSSDSynchronous 216 | * @brief Send USSD Command Synchronously (Blocking call until unsolicited response is received) 217 | * @param ussdCommand command UUSD, ex: *123# 218 | * @param resultCode char Result Code, see AT+CUSD command 219 | * @param response string response 220 | * @return true on success, false on error 221 | */ 222 | bool sendUSSDSynchronous(char *ussdCommand, char *resultcode, char *response); 223 | 224 | /** 225 | * @fn cancelUSSDSession 226 | * @brief Cancel USSD Session 227 | * @return true on success cancel active session, false on error or because no active session 228 | */ 229 | bool cancelUSSDSession(void); 230 | 231 | /*************************** DFRobot_SIM808 ***************************/ 232 | 233 | /** 234 | * @fn join 235 | * @brief Connect the DFRobot_SIM808 module to the network. 236 | * @param apn APN(Access Point Name) 237 | * @param userName user name 238 | * @param passWord pass word 239 | * @return true if connected, false otherwise 240 | */ 241 | bool join(const __FlashStringHelper *apn = 0, const __FlashStringHelper *userName = 0, const __FlashStringHelper *passWord = 0); 242 | 243 | /** 244 | * @fn disconnect 245 | * @brief Disconnect the DFRobot_SIM808 module from the network 246 | * @return None 247 | */ 248 | void disconnect(void); 249 | 250 | /** 251 | * @fn connect 252 | * @brief Open a tcp/udp connection with the specified host on the specified port 253 | * @param ptl protocol for socket, TCP/UDP can be choosen 254 | * @param host host (can be either an ip address or a name. If a name is provided, a dns request will be established) 255 | * @param port port 256 | * @param timeout wait seconds till connected 257 | * @param chartimeout wait milliseconds between characters from DFRobot_SIM808 module 258 | * @return true if successful, false if error 259 | */ 260 | bool connect(Protocol ptl, const char * host, int port, int timeout = 2 * DEFAULT_TIMEOUT, int chartimeout = 2 * DEFAULT_INTERCHAR_TIMEOUT); 261 | bool connect(Protocol ptl, const __FlashStringHelper *host, const __FlashStringHelper *port, int timeout = 2 * DEFAULT_TIMEOUT, int chartimeout = 2 * DEFAULT_INTERCHAR_TIMEOUT); 262 | 263 | /** 264 | * @fn is_connected 265 | * @brief Check if a tcp link is active 266 | * @return true if successful, false if error 267 | */ 268 | bool is_connected(void); 269 | 270 | /** 271 | * @fn close 272 | * @brief Close a tcp connection 273 | * @return true if successful, false if error 274 | */ 275 | bool close(void); 276 | 277 | /** 278 | * @fn readable 279 | * @brief check if DFRobot_SIM808 module is readable or not 280 | * @return true if readable 281 | */ 282 | int readable(void); 283 | 284 | /** 285 | * @fn wait_readable 286 | * @brief wait a few time to check if DFRobot_SIM808 module is readable or not 287 | * @param wait_time time of waiting 288 | * @return Returns the length of readable data 289 | */ 290 | int wait_readable(int wait_time); 291 | 292 | /** 293 | * @fn wait_writeable 294 | * @brief wait a few time to check if DFRobot_SIM808 module is writeable or not 295 | * @param req_size time of waiting 296 | * @return req_size + 1 297 | */ 298 | int wait_writeable(int req_size); 299 | 300 | /** 301 | * @fn send 302 | * @brief send data to socket 303 | * @param str string to be sent 304 | * @param len string length 305 | * @return return bytes that actually been send 306 | */ 307 | int send(const char * str, int len); 308 | 309 | /** 310 | * @fn recv 311 | * @brief read data from socket 312 | * @param buf buffer that will store the data read from socket 313 | * @param len string length need to read from socket 314 | * @return bytes that actually read 315 | */ 316 | int recv(char* buf, int len); 317 | 318 | /** 319 | * @fn listen 320 | * @brief Enables the selected software serial port to listen 321 | * @return None 322 | */ 323 | void listen(void); 324 | 325 | /** 326 | * @fn isListening 327 | * @brief Tests to see if requested software serial port is actively listening. 328 | * @return Now masking enabled, return null 329 | */ 330 | bool isListening(void); 331 | 332 | /** 333 | * @fn gethostbyname 334 | * @brief convert the host to ip 335 | * @param host host ip string, ex. 10.11.12.13 336 | * @param ip long int ip address, ex. 0x11223344 337 | * @return true if successful 338 | */ 339 | //NOT USED bool gethostbyname(const char* host, uint32_t* ip); 340 | 341 | /** 342 | * @fn getIPAddress 343 | * @brief get IP address 344 | * @return IP address, char* 345 | */ 346 | char* getIPAddress(void); 347 | 348 | /** 349 | * @fn getIPnumber 350 | * @brief get IP number 351 | * @return IP number, unsigned long 352 | */ 353 | unsigned long getIPnumber(void); 354 | 355 | /** 356 | * @fn getLocation 357 | * @brief get Location 358 | * @param apn APN(Access Point Name) 359 | * @param longitude longitude 360 | * @param latitude latitude 361 | * @return true if successful, false if error 362 | */ 363 | bool getLocation(const __FlashStringHelper *apn, float *longitude, float *latitude); 364 | 365 | /** 366 | * @fn attachGPS 367 | * @brief Open GPS 368 | * @return true if successful, false if error 369 | */ 370 | bool attachGPS(void); 371 | 372 | /** 373 | * @fn detachGPS 374 | * @brief Close GPS 375 | * @return true if successful, false if error 376 | */ 377 | bool detachGPS(void); 378 | 379 | /** 380 | * @fn getTime 381 | * @brief parse time 382 | * @param time Time data to be parsed 383 | * @return None 384 | */ 385 | void getTime(uint32_t time); 386 | 387 | /** 388 | * @fn getDate 389 | * @brief parse date 390 | * @param date Date data to be parsed 391 | * @return None 392 | */ 393 | void getDate(uint32_t date); 394 | 395 | /** 396 | * @fn parseDecimal 397 | * @brief Parse a (potentially negative) number with up to 2 decimal digits -xxxx.yy 398 | * @param term Data to be parsed 399 | * @return Parsed data 400 | */ 401 | int32_t parseDecimal(const char *term); 402 | 403 | /** 404 | * @fn latitudeConverToDMS 405 | * @brief latitude Conver To DMS 406 | * @return None 407 | */ 408 | void latitudeConverToDMS(void); 409 | 410 | /** 411 | * @fn LongitudeConverToDMS 412 | * @brief Longitude Conver To DMS 413 | * @return None 414 | */ 415 | void LongitudeConverToDMS(void); 416 | 417 | /** 418 | * @fn parseGPRMC 419 | * @brief parser GPRMC, Determine whether gpsbuffer[18] is 'A' 420 | * @param gpsbuffer GPS buffer data to be parsed 421 | * @return true if gpsbuffer[18] is 'A' 422 | */ 423 | bool parseGPRMC(char *gpsbuffer); 424 | 425 | /** 426 | * @fn getGPRMC 427 | * @brief Get the parsed GPRMC 428 | * @return true if successful, false if error 429 | */ 430 | bool getGPRMC(void); 431 | 432 | /** 433 | * @fn getGPS 434 | * @brief get GPS signal 435 | * @return true if successful, false if error 436 | */ 437 | bool getGPS(void); 438 | 439 | ``` 440 | 441 | 442 | ## 兼容性 443 | 444 | MCU | Work Well | Work Wrong | Untested | Remarks 445 | ------------------ | :----------: | :----------: | :---------: | :----: 446 | Arduino Uno | √ | | | 447 | Arduino MEGA2560 | √ | | | 448 | Arduino Leonardo | √ | | | 449 | 450 | 451 | ## 历史 452 | 453 | - 2022/02/08 - 1.0.0 版本 454 | - 2022/06/30 - 1.0.1 版本 455 | 456 | 457 | ## 创作者 458 | 459 | Written by [Jason](jason.ling@dfrobot.com), 2022. (Welcome to our [website](https://www.dfrobot.com/)) 460 | 461 | -------------------------------------------------------------------------------- /ReadMe.md: -------------------------------------------------------------------------------- 1 | # DFRobot_SIM808 2 | * [中文版](./README_CN.md) 3 | 4 | SIM808 GPS/GPRS/GSM arduino shield is an integrated quad-band GSM/GPRS and GPS navigation technology Arduino expansion shields. A credit card size only, according to the standard Arduino pin packaging, compatible with Arduino UNO, arduino Leonardo, arduino Mega and other arduino mainboard. Compared to the previous generation SIM908, SIM808 made some improvement on the performance and stability. In addition to the normal SMS and phone functions, the shield also supports MMS, DTMF, FTP and other functions. You can achieve the data acquisition, wireless data transceiver, IoT application and GPS orientating. The should integrates onboard microphone and headphone jack, saving your cost and making your project easily. it can also directly connect to the GSM and GPS antenna by an external antenna connector. 5 | 6 | ![产品实物图](./resources/images/SIM808.png) 7 | 8 | 9 | ## Product Link (https://www.dfrobot.com/product-1469.html) 10 | SKU: TEL0097 11 | 12 | 13 | ## Table of Contents 14 | 15 | * [Summary](#summary) 16 | * [Installation](#installation) 17 | * [Methods](#methods) 18 | * [Compatibility](#compatibility) 19 | * [History](#history) 20 | * [Credits](#credits) 21 | 22 | 23 | ## Summary 24 | 25 | * Send and receive GPRS data (TCP/IP, HTTP, etc.) 26 | * Receive GPS data and A-GPS data 27 | * Send and receive SMS messages 28 | * Make and receive phone calls 29 | 30 | 31 | ## Installation 32 | 33 | To use this library, first download the library file, paste it into the \Arduino\libraries directory, 34 | then open the examples folder and run the demo in the folder. 35 | 36 | 37 | ## Methods 38 | 39 | ```C++ 40 | 41 | /** 42 | * @fn DFRobot_SIM808 43 | * @brief Constructor 44 | * @param mySerial serial ports for communication, supporting hard and soft serial ports 45 | * @n Tx, rx, and baudRate can also be passed in this order 46 | * @return None 47 | */ 48 | DFRobot_SIM808(SoftwareSerial *mySerial); 49 | DFRobot_SIM808(HardwareSerial *mySerial); 50 | DFRobot_SIM808(uint8_t tx, uint8_t rx, uint32_t baudRate = 9600); 51 | 52 | /** 53 | * @fn getInstance 54 | * @brief get instance of DFRobot_SIM808 class 55 | * @return instance of DFRobot_SIM808 class 56 | */ 57 | static DFRobot_SIM808* getInstance() { return inst; }; 58 | 59 | /** 60 | * @fn init 61 | * @brief initialize DFRobot_SIM808 module including SIM card check & signal strength 62 | * @return true if connected, false otherwise 63 | */ 64 | bool init(void); 65 | 66 | /** 67 | * @fn checkPowerUp 68 | * @brief check if DFRobot_SIM808 module is powered on or not 69 | * @return true on success, false on error 70 | */ 71 | bool checkPowerUp(void); 72 | 73 | /** 74 | * @fn powerUpDown 75 | * @brief power Up DFRobot_SIM808 module (JP has to be soldered) 76 | * @param pin pin 9 connected to JP jumper so we can power up and down through software 77 | * @return None 78 | */ 79 | void powerUpDown(uint8_t pin); 80 | 81 | /** 82 | * @fn powerReset 83 | * @brief power reset for SIM800 board 84 | * @param pin (preconfigurated as OUTPUT) 85 | * @return None 86 | */ 87 | void powerReset(uint8_t pin); 88 | 89 | /** 90 | * @fn sendSMS 91 | * @brief send text SMS 92 | * @param number phone number which SMS will be send to 93 | * @param data message that will be send to 94 | * @return true on success, false on error 95 | */ 96 | bool sendSMS(char* number, char* data); 97 | 98 | /** 99 | * @fn isSMSunread 100 | * @brief Check if there is any UNREAD SMS: this function DOESN'T change the UNREAD status of the SMS 101 | * @return returned value 102 | * @retval 1~20 - on success, position/index where SMS is stored, suitable for the function ReadSMS 103 | * @retval -1 - on error 104 | * @retval 0 - there is no SMS with specified status (UNREAD) 105 | */ 106 | char isSMSunread(void); 107 | 108 | /** 109 | * @fn readSMS 110 | * @brief read SMS, phone and date if getting a SMS message. It changes SMS status to READ 111 | * @param messageIndex SIM position to read 112 | * @param message buffer used to get SMS message 113 | * @param length length of message buffer 114 | * @param phone buffer used to get SMS's sender phone number 115 | * @param datetime buffer used to get SMS's send datetime 116 | * @return true on success, false on error 117 | */ 118 | bool readSMS(int messageIndex, char *message, int length, char *phone, char *datetime); 119 | 120 | /** 121 | * @fn readSMS 122 | * @brief read SMS if getting a SMS message 123 | * @param buffer buffer that get from DFRobot_SIM808 module(when getting a SMS, DFRobot_SIM808 module will return a buffer array) 124 | * @param message buffer used to get SMS message 125 | * @param check whether to check phone number(we may only want to read SMS from specified phone number) 126 | * @return true on success, false on error 127 | */ 128 | bool readSMS(int messageIndex, char *message, int length); 129 | 130 | /** 131 | * @fn deleteSMS 132 | * @brief delete SMS message on SIM card 133 | * @param index the index number which SMS message will be delete 134 | * @return true on success, false on error 135 | */ 136 | bool deleteSMS(int index); 137 | 138 | /** 139 | * @fn callUp 140 | * @brief call someone 141 | * @param number the phone number which you want to call 142 | * @return true on success, false on error 143 | */ 144 | bool callUp(char* number); 145 | 146 | /** 147 | * @fn answer 148 | * @brief auto answer if coming a call 149 | * @return None 150 | */ 151 | void answer(void); 152 | 153 | /** 154 | * @fn hangup 155 | * @brief hang up if coming a call 156 | * @return true on success, false on error 157 | */ 158 | bool hangup(void); 159 | 160 | /** 161 | * @fn disableCLIPring 162 | * @brief Disable +CLIP notification when an incoming call is active, RING text is always shown. See isCallActive function 163 | * @note This is done in order no to overload serial outputCheck if there is a call active and get the phone number in that case 164 | * @return true on success, false on error 165 | */ 166 | bool disableCLIPring(void); 167 | 168 | /** 169 | * @fn getSubscriberNumber 170 | * @brief Get Subscriber Number (your number) using AT+CNUM command, but if nothing return, then 171 | * @n you need to command this to your SIM900. (See AT+CPBS, AT+CPBW) 172 | * @n AT+CPBS="ON" 173 | * @n AT+CPBW=1,"+{Your Number}",145 174 | * @n AT+CPBS="SM" 175 | * @param number your phone number 176 | * @return true on success, false on error 177 | */ 178 | bool getSubscriberNumber(char *number); 179 | 180 | /** 181 | * @fn isCallActive 182 | * @brief Check if there is a call active and get the phone number in that case 183 | * @param number Check if there is a call active and get the phone number in that case 184 | * @return true on success, false on error 185 | */ 186 | bool isCallActive(char *number); 187 | 188 | /** 189 | * @fn getDateTime 190 | * @brief get DateTime from SIM900 (see AT command: AT+CLTS=1) as string 191 | * @param buffer DateTime from SIM900 192 | * @return true on success, false on error 193 | * @note If it doesn't work may be for two reasons: 194 | * @n 1. Your carrier doesn't give that information 195 | * @n 2. You have to configurate the SIM900 IC. 196 | * @n - First with SIM900_Serial_Debug example try this AT command: AT+CLTS? 197 | * @n - If response is 0, then it is disabled. 198 | * @n - Enable it by: AT+CLTS=1 199 | * @n - Now you have to save this config to EEPROM memory of SIM900 IC by: AT&W 200 | * @n - Now, you have to power down and power up again the SIM900 201 | * @n - Try now again: AT+CCLK? 202 | * @n - It should work now 203 | * 204 | */ 205 | bool getDateTime(char *buffer); 206 | 207 | /** 208 | * @fn getSignalStrength 209 | * @brief get Signal Strength from SIM900 (see AT command: AT+CSQ) as integer 210 | * @param buffer Signal Strength 211 | * @return true on success, false on error 212 | */ 213 | bool getSignalStrength(int *buffer); 214 | 215 | /** 216 | * @fn sendUSSDSynchronous 217 | * @brief Send USSD Command Synchronously (Blocking call until unsolicited response is received) 218 | * @param ussdCommand command UUSD, ex: *123# 219 | * @param resultCode char Result Code, see AT+CUSD command 220 | * @param response string response 221 | * @return true on success, false on error 222 | */ 223 | bool sendUSSDSynchronous(char *ussdCommand, char *resultcode, char *response); 224 | 225 | /** 226 | * @fn cancelUSSDSession 227 | * @brief Cancel USSD Session 228 | * @return true on success cancel active session, false on error or because no active session 229 | */ 230 | bool cancelUSSDSession(void); 231 | 232 | /*************************** DFRobot_SIM808 ***************************/ 233 | 234 | /** 235 | * @fn join 236 | * @brief Connect the DFRobot_SIM808 module to the network. 237 | * @param apn APN(Access Point Name) 238 | * @param userName user name 239 | * @param passWord pass word 240 | * @return true if connected, false otherwise 241 | */ 242 | bool join(const __FlashStringHelper *apn = 0, const __FlashStringHelper *userName = 0, const __FlashStringHelper *passWord = 0); 243 | 244 | /** 245 | * @fn disconnect 246 | * @brief Disconnect the DFRobot_SIM808 module from the network 247 | * @return None 248 | */ 249 | void disconnect(void); 250 | 251 | /** 252 | * @fn connect 253 | * @brief Open a tcp/udp connection with the specified host on the specified port 254 | * @param ptl protocol for socket, TCP/UDP can be choosen 255 | * @param host host (can be either an ip address or a name. If a name is provided, a dns request will be established) 256 | * @param port port 257 | * @param timeout wait seconds till connected 258 | * @param chartimeout wait milliseconds between characters from DFRobot_SIM808 module 259 | * @return true if successful, false if error 260 | */ 261 | bool connect(Protocol ptl, const char * host, int port, int timeout = 2 * DEFAULT_TIMEOUT, int chartimeout = 2 * DEFAULT_INTERCHAR_TIMEOUT); 262 | bool connect(Protocol ptl, const __FlashStringHelper *host, const __FlashStringHelper *port, int timeout = 2 * DEFAULT_TIMEOUT, int chartimeout = 2 * DEFAULT_INTERCHAR_TIMEOUT); 263 | 264 | /** 265 | * @fn is_connected 266 | * @brief Check if a tcp link is active 267 | * @return true if successful, false if error 268 | */ 269 | bool is_connected(void); 270 | 271 | /** 272 | * @fn close 273 | * @brief Close a tcp connection 274 | * @return true if successful, false if error 275 | */ 276 | bool close(void); 277 | 278 | /** 279 | * @fn readable 280 | * @brief check if DFRobot_SIM808 module is readable or not 281 | * @return true if readable 282 | */ 283 | int readable(void); 284 | 285 | /** 286 | * @fn wait_readable 287 | * @brief wait a few time to check if DFRobot_SIM808 module is readable or not 288 | * @param wait_time time of waiting 289 | * @return Returns the length of readable data 290 | */ 291 | int wait_readable(int wait_time); 292 | 293 | /** 294 | * @fn wait_writeable 295 | * @brief wait a few time to check if DFRobot_SIM808 module is writeable or not 296 | * @param req_size time of waiting 297 | * @return req_size + 1 298 | */ 299 | int wait_writeable(int req_size); 300 | 301 | /** 302 | * @fn send 303 | * @brief send data to socket 304 | * @param str string to be sent 305 | * @param len string length 306 | * @return return bytes that actually been send 307 | */ 308 | int send(const char * str, int len); 309 | 310 | /** 311 | * @fn recv 312 | * @brief read data from socket 313 | * @param buf buffer that will store the data read from socket 314 | * @param len string length need to read from socket 315 | * @return bytes that actually read 316 | */ 317 | int recv(char* buf, int len); 318 | 319 | /** 320 | * @fn listen 321 | * @brief Enables the selected software serial port to listen 322 | * @return None 323 | */ 324 | void listen(void); 325 | 326 | /** 327 | * @fn isListening 328 | * @brief Tests to see if requested software serial port is actively listening. 329 | * @return Now masking enabled, return null 330 | */ 331 | bool isListening(void); 332 | 333 | /** 334 | * @fn gethostbyname 335 | * @brief convert the host to ip 336 | * @param host host ip string, ex. 10.11.12.13 337 | * @param ip long int ip address, ex. 0x11223344 338 | * @return true if successful 339 | */ 340 | //NOT USED bool gethostbyname(const char* host, uint32_t* ip); 341 | 342 | /** 343 | * @fn getIPAddress 344 | * @brief get IP address 345 | * @return IP address, char* 346 | */ 347 | char* getIPAddress(void); 348 | 349 | /** 350 | * @fn getIPnumber 351 | * @brief get IP number 352 | * @return IP number, unsigned long 353 | */ 354 | unsigned long getIPnumber(void); 355 | 356 | /** 357 | * @fn getLocation 358 | * @brief get Location 359 | * @param apn APN(Access Point Name) 360 | * @param longitude longitude 361 | * @param latitude latitude 362 | * @return true if successful, false if error 363 | */ 364 | bool getLocation(const __FlashStringHelper *apn, float *longitude, float *latitude); 365 | 366 | /** 367 | * @fn attachGPS 368 | * @brief Open GPS 369 | * @return true if successful, false if error 370 | */ 371 | bool attachGPS(void); 372 | 373 | /** 374 | * @fn detachGPS 375 | * @brief Close GPS 376 | * @return true if successful, false if error 377 | */ 378 | bool detachGPS(void); 379 | 380 | /** 381 | * @fn getTime 382 | * @brief parse time 383 | * @param time Time data to be parsed 384 | * @return None 385 | */ 386 | void getTime(uint32_t time); 387 | 388 | /** 389 | * @fn getDate 390 | * @brief parse date 391 | * @param date Date data to be parsed 392 | * @return None 393 | */ 394 | void getDate(uint32_t date); 395 | 396 | /** 397 | * @fn parseDecimal 398 | * @brief Parse a (potentially negative) number with up to 2 decimal digits -xxxx.yy 399 | * @param term Data to be parsed 400 | * @return Parsed data 401 | */ 402 | int32_t parseDecimal(const char *term); 403 | 404 | /** 405 | * @fn latitudeConverToDMS 406 | * @brief latitude Conver To DMS 407 | * @return None 408 | */ 409 | void latitudeConverToDMS(void); 410 | 411 | /** 412 | * @fn LongitudeConverToDMS 413 | * @brief Longitude Conver To DMS 414 | * @return None 415 | */ 416 | void LongitudeConverToDMS(void); 417 | 418 | /** 419 | * @fn parseGPRMC 420 | * @brief parser GPRMC, Determine whether gpsbuffer[18] is 'A' 421 | * @param gpsbuffer GPS buffer data to be parsed 422 | * @return true if gpsbuffer[18] is 'A' 423 | */ 424 | bool parseGPRMC(char *gpsbuffer); 425 | 426 | /** 427 | * @fn getGPRMC 428 | * @brief Get the parsed GPRMC 429 | * @return true if successful, false if error 430 | */ 431 | bool getGPRMC(void); 432 | 433 | /** 434 | * @fn getGPS 435 | * @brief get GPS signal 436 | * @return true if successful, false if error 437 | */ 438 | bool getGPS(void); 439 | 440 | ``` 441 | 442 | 443 | ## Compatibility 444 | 445 | MCU | Work Well | Work Wrong | Untested | Remarks 446 | ------------------ | :----------: | :----------: | :---------: | :----: 447 | Arduino Uno | √ | | | 448 | Arduino MEGA2560 | √ | | | 449 | Arduino Leonardo | √ | | | 450 | 451 | 452 | ## History 453 | 454 | - 2022/02/08 - Version 1.0.0 released. 455 | - 2022/06/30 - Version 1.0.1 released. 456 | 457 | 458 | ## Credits 459 | 460 | Written by [Jason](jason.ling@dfrobot.com), 2022. (Welcome to our [website](https://www.dfrobot.com/)) 461 | 462 | -------------------------------------------------------------------------------- /examples/SIM808_CallUp/SIM808_CallUp.ino: -------------------------------------------------------------------------------- 1 | /*! 2 | * @file SIM808_CallUp.ino 3 | * @brief Make phone calls 4 | * @details 1. This example is used to test DFRobot_SIM808 SIM808 GPS/GPRS/GSM Shield's callUp function. 5 | * @n 2. Open the SIM808_CallUp example or copy these code to your project 6 | * @n 3. Replace the phoneNumber:#define PHONE_NUMBER "187******39" 7 | * @n 4. Download and dial the function switch to Arduino, and enjoy it 8 | * @copyright Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com) 9 | * @license The MIT License (MIT) 10 | * @author [Jason](jason.ling@dfrobot.com) 11 | * @maintainer [qsjhyy](yihuan.huang@dfrobot.com) 12 | * @version V1.0 13 | * @date 2022-02-08 14 | * @url https://github.com/DFRobot/DFRobot_SIM808 15 | */ 16 | #include 17 | 18 | /** 19 | * Besides push-in connection with expansion board, it can also be connected by jump wires 20 | * Set DIP switch to 3-Arduino, open the following macro 21 | * Connect the main controller to the module with Dupont wires: 22 | * Arduino | module 23 | * PIN_TX | TX1 24 | * PIN_RX | RX1 25 | * Power the module, which is successful when the power indicator on the module is ON 26 | */ 27 | // #define CONNECT_BY_JUMPER 1 28 | #if CONNECT_BY_JUMPER 29 | #define PIN_TX 10 30 | #define PIN_RX 11 31 | SoftwareSerial mySerial(PIN_TX, PIN_RX); 32 | DFRobot_SIM808 sim808(&mySerial); 33 | /** 34 | * Use Leonardo for push-in connection 35 | * Set DIP switch to 3-Arduino, and use the Serial1 of Leonardo for communication 36 | */ 37 | #elif defined(ARDUINO_AVR_LEONARDO) 38 | DFRobot_SIM808 sim808(&Serial1); 39 | /** 40 | * Try using ESP32 41 | */ 42 | #elif defined(ESP32) 43 | DFRobot_SIM808 sim808(&Serial1); 44 | /** 45 | * Use UNO & MEGA2560 for push-in connection 46 | * Set DIP switch to 3-Arduino, and use the Serial of UNO and MEGA2560 for communication 47 | */ 48 | #else 49 | DFRobot_SIM808 sim808(&Serial); 50 | #endif 51 | 52 | //Mobile phone number,need to change 53 | #define PHONE_NUMBER "187******39" 54 | 55 | void setup() { 56 | #if CONNECT_BY_JUMPER 57 | mySerial.begin(9600); 58 | #elif defined(ARDUINO_AVR_LEONARDO) 59 | Serial1.begin(9600); 60 | #elif defined(ESP32) 61 | Serial1.begin(9600, SERIAL_8N1, /*rx =*/D3, /*tx =*/D2); 62 | #endif 63 | Serial.begin(9600); 64 | //********Initialize sim808 module************* 65 | while(!sim808.init()) { 66 | delay(1000); 67 | Serial.print("Sim808 init error\r\n"); 68 | } 69 | Serial.println("Sim808 init success"); 70 | Serial.println("Start to call ..."); 71 | 72 | //*********Call specified number*************** 73 | sim808.callUp((char *)PHONE_NUMBER); 74 | } 75 | void loop() { 76 | //nothing to do 77 | } 78 | -------------------------------------------------------------------------------- /examples/SIM808_GetGPS/SIM808_GetGPS.ino: -------------------------------------------------------------------------------- 1 | /*! 2 | * @file SIM808_GetGPS.ino 3 | * @brief Get GPS data 4 | * @details 1. This example is used to test SIM808 GPS/GPRS/GSM Shield's reading GPS data. 5 | * @n 2. Open the SIM808_GetGPS example or copy these code to your project 6 | * @n 3. Download and dial the function switch to Arduino 7 | * @n 4. open serial helper 8 | * @n 4. Place it outside, waiting for a few minutes and then it will send GPS data to serial 9 | * @copyright Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com) 10 | * @license The MIT License (MIT) 11 | * @author [Jason](jason.ling@dfrobot.com) 12 | * @maintainer [qsjhyy](yihuan.huang@dfrobot.com) 13 | * @version V1.0 14 | * @date 2022-02-08 15 | * @url https://github.com/DFRobot/DFRobot_SIM808 16 | */ 17 | #include 18 | 19 | /** 20 | * Besides push-in connection with expansion board, it can also be connected by jump wires 21 | * Set DIP switch to 3-Arduino, open the following macro 22 | * Connect the main controller to the module with Dupont wires: 23 | * Arduino | module 24 | * PIN_TX | TX1 25 | * PIN_RX | RX1 26 | * Power the module, which is successful when the power indicator on the module is ON 27 | */ 28 | // #define CONNECT_BY_JUMPER 1 29 | #if CONNECT_BY_JUMPER 30 | #define PIN_TX 10 31 | #define PIN_RX 11 32 | SoftwareSerial mySerial(PIN_TX, PIN_RX); 33 | DFRobot_SIM808 sim808(&mySerial); 34 | /** 35 | * Use Leonardo for push-in connection 36 | * Set DIP switch to 3-Arduino, and use the Serial1 of Leonardo for communication 37 | */ 38 | #elif defined(ARDUINO_AVR_LEONARDO) 39 | DFRobot_SIM808 sim808(&Serial1); 40 | /** 41 | * Use UNO & MEGA2560 for push-in connection 42 | * Set DIP switch to 3-Arduino, and use the Serial of UNO and MEGA2560 for communication 43 | */ 44 | #else 45 | DFRobot_SIM808 sim808(&Serial); 46 | #endif 47 | 48 | void setup() { 49 | #if CONNECT_BY_JUMPER 50 | mySerial.begin(9600); 51 | #elif defined(ARDUINO_AVR_LEONARDO) 52 | Serial1.begin(9600); 53 | #endif 54 | Serial.begin(9600); 55 | 56 | //******** Initialize sim808 module ************* 57 | while(!sim808.init()) { 58 | delay(1000); 59 | Serial.print("Sim808 init error\r\n"); 60 | } 61 | 62 | //************* Turn on the GPS power************ 63 | if( sim808.attachGPS()) 64 | Serial.println("Open the GPS power success"); 65 | else 66 | Serial.println("Open the GPS power failure"); 67 | 68 | } 69 | 70 | void loop() { 71 | //************** Get GPS data ******************* 72 | if (sim808.getGPS()) { 73 | Serial.print(sim808.GPSdata.year); 74 | Serial.print("/"); 75 | Serial.print(sim808.GPSdata.month); 76 | Serial.print("/"); 77 | Serial.print(sim808.GPSdata.day); 78 | Serial.print(" "); 79 | Serial.print(sim808.GPSdata.hour); 80 | Serial.print(":"); 81 | Serial.print(sim808.GPSdata.minute); 82 | Serial.print(":"); 83 | Serial.print(sim808.GPSdata.second); 84 | Serial.print(":"); 85 | Serial.println(sim808.GPSdata.centisecond); 86 | 87 | Serial.print("latitude :"); 88 | Serial.println(sim808.GPSdata.lat,6); 89 | 90 | sim808.latitudeConverToDMS(); 91 | Serial.print("latitude :"); 92 | Serial.print(sim808.latDMS.degrees); 93 | Serial.print("\^"); 94 | Serial.print(sim808.latDMS.minutes); 95 | Serial.print("\'"); 96 | Serial.print(sim808.latDMS.seconeds,6); 97 | Serial.println("\""); 98 | Serial.print("longitude :"); 99 | Serial.println(sim808.GPSdata.lon,6); 100 | sim808.LongitudeConverToDMS(); 101 | Serial.print("longitude :"); 102 | Serial.print(sim808.longDMS.degrees); 103 | Serial.print("\^"); 104 | Serial.print(sim808.longDMS.minutes); 105 | Serial.print("\'"); 106 | Serial.print(sim808.longDMS.seconeds,6); 107 | Serial.println("\""); 108 | 109 | Serial.print("speed_kph :"); 110 | Serial.println(sim808.GPSdata.speed_kph); 111 | Serial.print("heading :"); 112 | Serial.println(sim808.GPSdata.heading); 113 | 114 | //************* Turn off the GPS power ************ 115 | sim808.detachGPS(); 116 | } 117 | 118 | } 119 | -------------------------------------------------------------------------------- /examples/SIM808_LoopHandle/SIM808_LoopHandle.ino: -------------------------------------------------------------------------------- 1 | /*! 2 | * @file SIM808_LoopHandle.ino 3 | * @brief Auto answer phone calls and read SMS Messages 4 | * @details 1. This example is used to test DFRobot_SIM808 GPS/GPRS/GSM Shield's 5 | * @n call answering and reading SMS function. 6 | * @n 2. Open the SIM808_LoopHandle example or copy these code to your project 7 | * @n 3. Download and dial the function switch to Arduino 8 | * @n 4. it will Auto-Answer phone calls or send SMS Messages to serial 9 | * @copyright Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com) 10 | * @license The MIT License (MIT) 11 | * @author [Jason](jason.ling@dfrobot.com) 12 | * @maintainer [qsjhyy](yihuan.huang@dfrobot.com) 13 | * @version V1.0 14 | * @date 2022-02-08 15 | * @url https://github.com/DFRobot/DFRobot_SIM808 16 | */ 17 | #include 18 | 19 | /** 20 | * Besides push-in connection with expansion board, it can also be connected by jump wires 21 | * Set DIP switch to 3-Arduino, open the following macro 22 | * Connect the main controller to the module with Dupont wires: 23 | * Arduino | module 24 | * PIN_TX | TX1 25 | * PIN_RX | RX1 26 | * Power the module, which is successful when the power indicator on the module is ON 27 | */ 28 | // #define CONNECT_BY_JUMPER 1 29 | #if CONNECT_BY_JUMPER 30 | #define PIN_TX 10 31 | #define PIN_RX 11 32 | SoftwareSerial mySerial(PIN_TX, PIN_RX); 33 | DFRobot_SIM808 sim808(&mySerial); 34 | /** 35 | * Use Leonardo for push-in connection 36 | * Set DIP switch to 3-Arduino, and use the Serial1 of Leonardo for communication 37 | */ 38 | #elif defined(ARDUINO_AVR_LEONARDO) 39 | DFRobot_SIM808 sim808(&Serial1); 40 | /** 41 | * Use UNO & MEGA2560 for push-in connection 42 | * Set DIP switch to 3-Arduino, and use the Serial of UNO and MEGA2560 for communication 43 | */ 44 | #else 45 | DFRobot_SIM808 sim808(&Serial); 46 | #endif 47 | 48 | #define MESSAGE_LENGTH 20 49 | char gprsBuffer[64]; 50 | char *s = NULL; 51 | 52 | void setup() { 53 | #if CONNECT_BY_JUMPER 54 | mySerial.begin(9600); 55 | #elif defined(ARDUINO_AVR_LEONARDO) 56 | Serial1.begin(9600); 57 | #endif 58 | Serial.begin(9600); 59 | 60 | //******** Initialize sim808 module ************* 61 | while(!sim808.init()) { 62 | Serial.print("Sim808 init error\r\n"); 63 | delay(1000); 64 | } 65 | delay(3000); 66 | Serial.println("Init Success, please call or send SMS message to me!"); 67 | } 68 | 69 | void loop() { 70 | //******** Wait serial data ************* 71 | if(sim808.readable()){ 72 | sim808_read_buffer(gprsBuffer,32,DEFAULT_TIMEOUT); 73 | //Serial.print(gprsBuffer); 74 | 75 | //************** Detect the current state of the telephone or SMS ************************ 76 | if(NULL != strstr(gprsBuffer,"RING")) { 77 | sim808.answer(); 78 | }else if(NULL != (s = strstr(gprsBuffer,"+CMTI: \"SM\""))) { //SMS: $$+CMTI: "SM",24$$ 79 | char message[MESSAGE_LENGTH]; 80 | int messageIndex = atoi(s+12); 81 | sim808.readSMS(messageIndex, message,MESSAGE_LENGTH); 82 | Serial.print("Recv Message: "); 83 | Serial.println(message); 84 | } 85 | sim808_clean_buffer(gprsBuffer,32); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /examples/SIM808_SMSread/SIM808_SMSread.ino: -------------------------------------------------------------------------------- 1 | /*! 2 | * @file SIM808_SMSread.ino 3 | * @brief Read SMS messages 4 | * @details 1. This example is used to test DFRobot_SIM808 GPS/GPRS/GSM Shield's reading SMS 5 | * @n 2. Open the SIM808_SMSread example or copy these code to your project 6 | * @n 3. Download and dial the function switch to Arduino 7 | * @n 4. it will receive SMS Messages and send it to serial 8 | * @copyright Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com) 9 | * @license The MIT License (MIT) 10 | * @author [Jason](jason.ling@dfrobot.com) 11 | * @maintainer [qsjhyy](yihuan.huang@dfrobot.com) 12 | * @version V1.0 13 | * @date 2022-02-08 14 | * @url https://github.com/DFRobot/DFRobot_SIM808 15 | */ 16 | #include 17 | 18 | /** 19 | * Besides push-in connection with expansion board, it can also be connected by jump wires 20 | * Set DIP switch to 3-Arduino, open the following macro 21 | * Connect the main controller to the module with Dupont wires: 22 | * Arduino | module 23 | * PIN_TX | TX1 24 | * PIN_RX | RX1 25 | * Power the module, which is successful when the power indicator on the module is ON 26 | */ 27 | // #define CONNECT_BY_JUMPER 1 28 | #if CONNECT_BY_JUMPER 29 | #define PIN_TX 10 30 | #define PIN_RX 11 31 | SoftwareSerial mySerial(PIN_TX, PIN_RX); 32 | DFRobot_SIM808 sim808(&mySerial); 33 | /** 34 | * Use Leonardo for push-in connection 35 | * Set DIP switch to 3-Arduino, and use the Serial1 of Leonardo for communication 36 | */ 37 | #elif defined(ARDUINO_AVR_LEONARDO) 38 | DFRobot_SIM808 sim808(&Serial1); 39 | /** 40 | * Use UNO & MEGA2560 for push-in connection 41 | * Set DIP switch to 3-Arduino, and use the Serial of UNO and MEGA2560 for communication 42 | */ 43 | #else 44 | DFRobot_SIM808 sim808(&Serial); 45 | #endif 46 | 47 | #define MESSAGE_LENGTH 160 48 | char message[MESSAGE_LENGTH]; 49 | int messageIndex = 0; 50 | 51 | char phone[16]; 52 | char datetime[24]; 53 | 54 | void setup() { 55 | #if CONNECT_BY_JUMPER 56 | mySerial.begin(9600); 57 | #elif defined(ARDUINO_AVR_LEONARDO) 58 | Serial1.begin(9600); 59 | #endif 60 | Serial.begin(9600); 61 | 62 | //******** Initialize sim808 module ************* 63 | while(!sim808.init()) { 64 | Serial.print("Sim808 init error\r\n"); 65 | delay(1000); 66 | } 67 | delay(3000); 68 | Serial.println("Init Success, please send SMS message to me!"); 69 | } 70 | 71 | void loop() { 72 | //*********** Detecting unread SMS ************************ 73 | messageIndex = sim808.isSMSunread(); 74 | Serial.print("messageIndex: "); 75 | Serial.println(messageIndex); 76 | 77 | //*********** At least, there is one UNREAD SMS *********** 78 | if (messageIndex > 0) { 79 | sim808.readSMS(messageIndex, message, MESSAGE_LENGTH, phone, datetime); 80 | 81 | //***********In order not to full SIM Memory, is better to delete it********** 82 | sim808.deleteSMS(messageIndex); 83 | Serial.print("From number: "); 84 | Serial.println(phone); 85 | Serial.print("Datetime: "); 86 | Serial.println(datetime); 87 | Serial.print("Recieved Message: "); 88 | Serial.println(message); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /examples/SIM808_SendSMS/SIM808_SendSMS.ino: -------------------------------------------------------------------------------- 1 | /*! 2 | * @file SIM808_SendSMS.ino 3 | * @brief Send SMS messages 4 | * @details 1. This example is used to test DFRobot_SIM808 GPS/GPRS/GSM Shield's send SMS func. 5 | * @n 2. Open the SIM808_SendSMS example or copy these code to your project 6 | * @n 3. Replace the phoneNumber:#define PHONE_NUMBER "187******39" 7 | * @n 4. Download and dial the function switch to Arduino, and enjoy it 8 | * @copyright Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com) 9 | * @license The MIT License (MIT) 10 | * @author [Jason](jason.ling@dfrobot.com) 11 | * @maintainer [qsjhyy](yihuan.huang@dfrobot.com) 12 | * @version V1.0 13 | * @date 2022-02-08 14 | * @url https://github.com/DFRobot/DFRobot_SIM808 15 | */ 16 | #include 17 | 18 | /** 19 | * Besides push-in connection with expansion board, it can also be connected by jump wires 20 | * Set DIP switch to 3-Arduino, open the following macro 21 | * Connect the main controller to the module with Dupont wires: 22 | * Arduino | module 23 | * PIN_TX | TX1 24 | * PIN_RX | RX1 25 | * Power the module, which is successful when the power indicator on the module is ON 26 | */ 27 | // #define CONNECT_BY_JUMPER 1 28 | #if CONNECT_BY_JUMPER 29 | #define PIN_TX 10 30 | #define PIN_RX 11 31 | SoftwareSerial mySerial(PIN_TX, PIN_RX); 32 | DFRobot_SIM808 sim808(&mySerial); 33 | /** 34 | * Use Leonardo for push-in connection 35 | * Set DIP switch to 3-Arduino, and use the Serial1 of Leonardo for communication 36 | */ 37 | #elif defined(ARDUINO_AVR_LEONARDO) 38 | DFRobot_SIM808 sim808(&Serial1); 39 | /** 40 | * Use UNO & MEGA2560 for push-in connection 41 | * Set DIP switch to 3-Arduino, and use the Serial of UNO and MEGA2560 for communication 42 | */ 43 | #else 44 | DFRobot_SIM808 sim808(&Serial); 45 | #endif 46 | 47 | //Mobile phone number,need to change 48 | #define PHONE_NUMBER "187******39" 49 | 50 | //The content of messages sent 51 | #define MESSAGE "hello,world" 52 | 53 | void setup() { 54 | #if CONNECT_BY_JUMPER 55 | mySerial.begin(9600); 56 | #elif defined(ARDUINO_AVR_LEONARDO) 57 | Serial1.begin(9600); 58 | #endif 59 | Serial.begin(9600); 60 | 61 | //******** Initialize sim808 module ************* 62 | while(!sim808.init()) { 63 | delay(1000); 64 | Serial.print("Sim808 init error\r\n"); 65 | } 66 | Serial.println("Sim808 init success"); 67 | Serial.println("Start to send message ..."); 68 | 69 | //******** define phone number and text ********** 70 | sim808.sendSMS((char *)PHONE_NUMBER, (char *)MESSAGE); 71 | } 72 | 73 | void loop() { 74 | //nothing to do 75 | } 76 | -------------------------------------------------------------------------------- /examples/SIM808_TCPConnection/SIM808_TCPConnection.ino: -------------------------------------------------------------------------------- 1 | /*! 2 | * @file SIM808_TCPConnection.ino 3 | * @brief Connect TCP and send GET request. 4 | * @details 1. This example is used to test DFRobot_SIM808 GPS/GPRS/GSM Shield's connect TCP and send GET request. 5 | * @n 2. Open the SIM808_TCPConnection example or copy these code to your project 6 | * @n 3. Download and dial the function switch to Arduino 7 | * @n 4. Open serial helper 8 | * @n 5. Waiting for a few minutes, until serial has sent "Connect mbed.org success" 9 | * @n 6. Serial will send "Hello world!" 10 | * @copyright Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com) 11 | * @license The MIT License (MIT) 12 | * @author [Jason](jason.ling@dfrobot.com) 13 | * @maintainer [qsjhyy](yihuan.huang@dfrobot.com) 14 | * @version V1.0 15 | * @date 2022-02-08 16 | * @url https://github.com/DFRobot/DFRobot_SIM808 17 | */ 18 | #include 19 | 20 | /** 21 | * Besides push-in connection with expansion board, it can also be connected by jump wires 22 | * Set DIP switch to 3-Arduino, open the following macro 23 | * Connect the main controller to the module with Dupont wires: 24 | * Arduino | module 25 | * PIN_TX | TX1 26 | * PIN_RX | RX1 27 | * Power the module, which is successful when the power indicator on the module is ON 28 | */ 29 | // #define CONNECT_BY_JUMPER 1 30 | #if CONNECT_BY_JUMPER 31 | #define PIN_TX 10 32 | #define PIN_RX 11 33 | SoftwareSerial mySerial(PIN_TX, PIN_RX); 34 | DFRobot_SIM808 sim808(&mySerial); 35 | /** 36 | * Use Leonardo for push-in connection 37 | * Set DIP switch to 3-Arduino, and use the Serial1 of Leonardo for communication 38 | */ 39 | #elif defined(ARDUINO_AVR_LEONARDO) 40 | DFRobot_SIM808 sim808(&Serial1); 41 | /** 42 | * Use UNO & MEGA2560 for push-in connection 43 | * Set DIP switch to 3-Arduino, and use the Serial of UNO and MEGA2560 for communication 44 | */ 45 | #else 46 | DFRobot_SIM808 sim808(&Serial); 47 | #endif 48 | 49 | char http_cmd[] = "GET /media/uploads/mbed_official/hello.txt HTTP/1.0\r\n\r\n"; 50 | char buffer[512]; 51 | 52 | void setup() { 53 | #if CONNECT_BY_JUMPER 54 | mySerial.begin(9600); 55 | #elif defined(ARDUINO_AVR_LEONARDO) 56 | Serial1.begin(9600); 57 | #endif 58 | Serial.begin(9600); 59 | 60 | //******** Initialize sim808 module ************* 61 | while(!sim808.init()) { 62 | delay(1000); 63 | Serial.print("Sim808 init error\r\n"); 64 | } 65 | delay(3000); 66 | 67 | //*********** Attempt DHCP ******************* 68 | while(!sim808.join(F("cmnet"))) { 69 | Serial.println("Sim808 join network error"); 70 | delay(2000); 71 | } 72 | 73 | //************ Successful DHCP **************** 74 | Serial.print("IP Address is "); 75 | Serial.println(sim808.getIPAddress()); 76 | 77 | //*********** Establish a TCP connection ************ 78 | if(!sim808.connect(TCP,"mbed.org", 80)) { 79 | Serial.println("Connect error"); 80 | }else{ 81 | Serial.println("Connect mbed.org success"); 82 | } 83 | 84 | //*********** Send a GET request ***************** 85 | Serial.println("waiting to fetch..."); 86 | sim808.send(http_cmd, sizeof(http_cmd)-1); 87 | while (true) { 88 | int ret = sim808.recv(buffer, sizeof(buffer)-1); 89 | if (ret <= 0){ 90 | Serial.println("fetch over..."); 91 | break; 92 | } 93 | buffer[ret] = '\0'; 94 | Serial.print("Recv: "); 95 | Serial.print(ret); 96 | Serial.print(" bytes: "); 97 | Serial.println(buffer); 98 | break; 99 | } 100 | 101 | //************* Close TCP or UDP connections ********** 102 | sim808.close(); 103 | 104 | //*** Disconnect wireless connection, Close Moving Scene ******* 105 | sim808.disconnect(); 106 | } 107 | 108 | void loop(){ 109 | 110 | } 111 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For DFRobot_SIM808 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | DFRobot_SIM808 KEYWORD1 10 | 11 | ####################################### 12 | # Methods and Functions (KEYWORD2) 13 | ####################################### 14 | 15 | begin KEYWORD2 16 | init KEYWORD2 17 | checkPowerUp KEYWORD2 18 | powerUpDown KEYWORD2 19 | powerReset KEYWORD2 20 | sendSMS KEYWORD2 21 | isSMSunread KEYWORD2 22 | readSMS KEYWORD2 23 | deleteSMS KEYWORD2 24 | callUp KEYWORD2 25 | answer KEYWORD2 26 | hangup KEYWORD2 27 | disableCLIPring KEYWORD2 28 | getSubscriberNumber KEYWORD2 29 | isCallActive KEYWORD2 30 | getDateTime KEYWORD2 31 | getSignalStrength KEYWORD2 32 | sendUSSDSynchronous KEYWORD2 33 | cancelUSSDSession KEYWORD2 34 | join KEYWORD2 35 | disconnect KEYWORD2 36 | connect KEYWORD2 37 | is_connected KEYWORD2 38 | close KEYWORD2 39 | readable KEYWORD2 40 | wait_readable KEYWORD2 41 | wait_writeable KEYWORD2 42 | send KEYWORD2 43 | recv KEYWORD2 44 | listen KEYWORD2 45 | isListening KEYWORD2 46 | gethostbyname KEYWORD2 47 | getIPAddress KEYWORD2 48 | getIPnumber KEYWORD2 49 | getLocation KEYWORD2 50 | attachGPS KEYWORD2 51 | detachGPS KEYWORD2 52 | getTime KEYWORD2 53 | getDate KEYWORD2 54 | parseDecimal KEYWORD2 55 | latitudeConverToDMS KEYWORD2 56 | LongitudeConverToDMS KEYWORD2 57 | parseGPRMC KEYWORD2 58 | getGPRMC KEYWORD2 59 | getGPS KEYWORD2 60 | 61 | ####################################### 62 | # Instances (KEYWORD3) 63 | ####################################### 64 | 65 | GPSdata KEYWORD3 66 | latDMS KEYWORD3 67 | longDMS KEYWORD3 68 | 69 | ####################################### 70 | # Constants (LITERAL1) 71 | ####################################### 72 | 73 | CLOSED LITERAL1 74 | TCP LITERAL1 75 | UDP LITERAL1 -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=DFRobot_SIM808 2 | version=1.0.1 3 | author=DFRobot 4 | maintainer=qsjhyy 5 | sentence=This is a Library for SIM808 GPS/GPRS/GSM Arduino Shield V1.0(SKU: TEL0097). 6 | paragraph= SIM808 module is a complete Quad-Band GSM/GPRS module which combines GPS technology for satellite navigation. 7 | category=Communication 8 | url=https://github.com/DFRobot/DFRobot_SIM808 9 | architectures=* 10 | -------------------------------------------------------------------------------- /resources/images/SIM808.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DFRobot/DFRobot_SIM808/a1e5d362b2de32f9db6c360e14ec1866c6fe8130/resources/images/SIM808.png -------------------------------------------------------------------------------- /src/DFRobot_SIM808.cpp: -------------------------------------------------------------------------------- 1 | /*! 2 | * @file DFRobot_SIM808.cpp 3 | * @brief Define infrastructure of DFRobot_SIM808 class 4 | * @details A library for DFRobot's SIM808 GPS/DFRobot_SIM808/GSM Shield 5 | * @copyright Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com) 6 | * @license The MIT License (MIT) 7 | * @author [Jason](jason.ling@dfrobot.com) 8 | * @maintainer [qsjhyy](yihuan.huang@dfrobot.com) 9 | * @version V1.0 10 | * @date 2022-02-07 11 | * @url https://github.com/DFRobot/DFRobot_SIM808 12 | */ 13 | 14 | 15 | #include 16 | #include "DFRobot_SIM808.h" 17 | 18 | extern Stream *serialSIM808; 19 | 20 | DFRobot_SIM808* DFRobot_SIM808::inst; 21 | char receivedStackIndex = 0; 22 | char receivedStack[130]; 23 | const char *des = "$GPRMC"; 24 | 25 | //char *receivedStack="$GPRMC,165445.000,A,3110.8635,N,12133.4627,E,0.58,70.26,220916,,,A*57"; 26 | 27 | DFRobot_SIM808::DFRobot_SIM808(HardwareSerial *mySerial) 28 | { 29 | inst = this; 30 | serialFlag = 1; 31 | hgprsSerial = mySerial; 32 | sim808_init(mySerial, 1); 33 | } 34 | 35 | #if !defined(ESP32) 36 | DFRobot_SIM808::DFRobot_SIM808(SoftwareSerial *mySerial) 37 | { 38 | inst = this; 39 | serialFlag = 0; 40 | gprsSerial = mySerial; 41 | sim808_init(mySerial, 0); 42 | } 43 | #endif 44 | 45 | bool DFRobot_SIM808::init(void) 46 | { 47 | if(!sim808_check_with_cmd("AT\r\n","OK\r\n",CMD)){ 48 | 49 | // Serial.println("-------"); 50 | return false; 51 | 52 | } 53 | // 1 : OK 54 | if(!sim808_check_with_cmd("AT+CFUN=1\r\n","OK\r\n",CMD)){ 55 | return false; 56 | } 57 | 58 | if(!checkSIMStatus()) { 59 | return false; 60 | } 61 | return true; 62 | } 63 | 64 | bool DFRobot_SIM808::checkPowerUp(void) 65 | { 66 | return sim808_check_with_cmd("AT\r\n","OK\r\n",CMD); 67 | } 68 | 69 | void DFRobot_SIM808::powerUpDown(uint8_t pin) 70 | { 71 | // power on pulse for SIM900 Shield 72 | digitalWrite(pin,LOW); 73 | delay(1000); 74 | digitalWrite(pin,HIGH); 75 | delay(2000); 76 | digitalWrite(pin,LOW); 77 | delay(3000); 78 | } 79 | 80 | void DFRobot_SIM808::powerReset(uint8_t pin) 81 | { 82 | // reset for SIM800L board. 83 | // RST pin has to be OUTPUT, HIGH 84 | digitalWrite(pin,LOW); 85 | delay(1000); 86 | digitalWrite(pin,HIGH); 87 | delay(3000); 88 | } 89 | 90 | 91 | bool DFRobot_SIM808::checkSIMStatus(void) 92 | { 93 | char gprsBuffer[32]; 94 | int count = 0; 95 | sim808_clean_buffer(gprsBuffer,32); 96 | while(count < 3) { 97 | sim808_send_cmd("AT+CPIN?\r\n"); 98 | sim808_read_buffer(gprsBuffer,32,DEFAULT_TIMEOUT); 99 | if((NULL != strstr(gprsBuffer,"+CPIN: READY"))) { 100 | break; 101 | } 102 | count++; 103 | delay(300); 104 | } 105 | if(count == 3) { 106 | return false; 107 | } 108 | return true; 109 | } 110 | 111 | bool DFRobot_SIM808::sendSMS(char *number, char *data) 112 | { 113 | //char cmd[32]; 114 | if(!sim808_check_with_cmd("AT+CMGF=1\r\n", "OK\r\n", CMD)) { // Set message mode to ASCII 115 | return false; 116 | } 117 | delay(500); 118 | sim808_flush_serial(); 119 | sim808_send_cmd("AT+CMGS=\""); 120 | sim808_send_cmd(number); 121 | //sprintf(cmd,"AT+CMGS=\"%s\"\r\n", number); 122 | //snprintf(cmd, sizeof(cmd),"AT+CMGS=\"%s\"\r\n", number); 123 | // if(!sim808_check_with_cmd(cmd,">",CMD)) { 124 | if(!sim808_check_with_cmd("\"\r\n",">",CMD)) { 125 | return false; 126 | } 127 | delay(1000); 128 | sim808_send_cmd(data); 129 | delay(500); 130 | sim808_send_End_Mark(); 131 | return sim808_wait_for_resp("OK\r\n", CMD); 132 | } 133 | 134 | char DFRobot_SIM808::isSMSunread() 135 | { 136 | char gprsBuffer[48]; //48 is enough to see +CMGL: 137 | char *s; 138 | 139 | sim808_check_with_cmd("AT+CMGF=1\r\n","OK\r\n",CMD); 140 | delay(1000); 141 | 142 | //List of all UNREAD SMS and DON'T change the SMS UNREAD STATUS 143 | sim808_send_cmd(F("AT+CMGL=\"REC UNREAD\",1\r\n")); 144 | /*If you want to change SMS status to READ you will need to send: 145 | AT+CMGL=\"REC UNREAD\"\r\n 146 | This command will list all UNREAD SMS and change all of them to READ 147 | 148 | If there is not SMS, response is (30 chars) 149 | AT+CMGL="REC UNREAD",1 --> 22 + 2 150 | --> 2 151 | OK --> 2 + 2 152 | 153 | If there is SMS, response is like (>64 chars) 154 | AT+CMGL="REC UNREAD",1 155 | +CMGL: 9,"REC UNREAD","XXXXXXXXX","","14/10/16,21:40:08+08" 156 | Here SMS text. 157 | OK 158 | 159 | or 160 | 161 | AT+CMGL="REC UNREAD",1 162 | +CMGL: 9,"REC UNREAD","XXXXXXXXX","","14/10/16,21:40:08+08" 163 | Here SMS text. 164 | +CMGL: 10,"REC UNREAD","YYYYYYYYY","","14/10/16,21:40:08+08" 165 | Here second SMS 166 | OK 167 | */ 168 | 169 | sim808_clean_buffer(gprsBuffer,31); 170 | sim808_read_buffer(gprsBuffer,30,DEFAULT_TIMEOUT); 171 | //Serial.print("Buffer isSMSunread: ");Serial.println(gprsBuffer); 172 | 173 | if(NULL != ( s = strstr(gprsBuffer,"OK"))) { 174 | //In 30 bytes "doesn't" fit whole +CMGL: response, if recieve only "OK" 175 | // means you don't have any UNREAD SMS 176 | delay(50); 177 | return 0; 178 | } else { 179 | //More buffer to read 180 | //We are going to flush serial data until OK is recieved 181 | sim808_wait_for_resp("OK\r\n", CMD); 182 | //sim808_flush_serial(); 183 | //We have to call command again 184 | sim808_send_cmd("AT+CMGL=\"REC UNREAD\",1\r\n"); 185 | sim808_clean_buffer(gprsBuffer,48); 186 | sim808_read_buffer(gprsBuffer,47,DEFAULT_TIMEOUT); 187 | //Serial.print("Buffer isSMSunread 2: ");Serial.println(gprsBuffer); 188 | if(NULL != ( s = strstr(gprsBuffer,"+CMGL:"))) { 189 | //There is at least one UNREAD SMS, get index/position 190 | s = strstr(gprsBuffer,":"); 191 | if (s != NULL) { 192 | //We are going to flush serial data until OK is recieved 193 | sim808_wait_for_resp("OK\r\n", CMD); 194 | return atoi(s+1); 195 | } 196 | } else { 197 | return -1; 198 | 199 | } 200 | } 201 | return -1; 202 | } 203 | 204 | bool DFRobot_SIM808::readSMS(int messageIndex, char *message, int length, char *phone, char *datetime) 205 | { 206 | /* Response is like: 207 | AT+CMGR=2 208 | 209 | +CMGR: "REC READ","XXXXXXXXXXX","","14/10/09,17:30:17+08" 210 | SMS text here 211 | 212 | So we need (more or lees), 80 chars plus expected message length in buffer. CAUTION FREE MEMORY 213 | */ 214 | 215 | int i = 0; 216 | char gprsBuffer[80 + length]; 217 | //char cmd[16]; 218 | char num[4]; 219 | char *p,*p2,*s; 220 | 221 | sim808_check_with_cmd("AT+CMGF=1\r\n","OK\r\n",CMD); 222 | delay(1000); 223 | //sprintf(cmd,"AT+CMGR=%d\r\n",messageIndex); 224 | //sim808_send_cmd(cmd); 225 | sim808_send_cmd("AT+CMGR="); 226 | itoa(messageIndex, num, 10); 227 | sim808_send_cmd(num); 228 | sim808_send_cmd("\r\n"); 229 | sim808_clean_buffer(gprsBuffer,sizeof(gprsBuffer)); 230 | sim808_read_buffer(gprsBuffer,sizeof(gprsBuffer)); 231 | 232 | if(NULL != ( s = strstr(gprsBuffer,"+CMGR:"))){ 233 | // Extract phone number string 234 | p = strstr(s,","); 235 | p2 = p + 2; //We are in the first phone number character 236 | p = strstr((char *)(p2), "\""); 237 | if (NULL != p) { 238 | i = 0; 239 | while (p2 < p) { 240 | phone[i++] = *(p2++); 241 | } 242 | phone[i] = '\0'; 243 | } 244 | // Extract date time string 245 | p = strstr((char *)(p2),","); 246 | p2 = p + 1; 247 | p = strstr((char *)(p2), ","); 248 | p2 = p + 2; //We are in the first date time character 249 | p = strstr((char *)(p2), "\""); 250 | if (NULL != p) { 251 | i = 0; 252 | while (p2 < p) { 253 | datetime[i++] = *(p2++); 254 | } 255 | datetime[i] = '\0'; 256 | } 257 | if(NULL != ( s = strstr(s,"\r\n"))){ 258 | i = 0; 259 | p = s + 2; 260 | while((*p != '\r')&&(i < length-1)) { 261 | message[i++] = *(p++); 262 | } 263 | message[i] = '\0'; 264 | } 265 | return true; 266 | } 267 | return false; 268 | } 269 | 270 | bool DFRobot_SIM808::readSMS(int messageIndex, char *message,int length) 271 | { 272 | int i = 0; 273 | char gprsBuffer[100]; 274 | //char cmd[16]; 275 | char num[4]; 276 | char *p,*s; 277 | 278 | sim808_check_with_cmd("AT+CMGF=1\r\n","OK\r\n",CMD); 279 | delay(1000); 280 | sim808_send_cmd("AT+CMGR="); 281 | itoa(messageIndex, num, 10); 282 | sim808_send_cmd(num); 283 | sim808_send_cmd("\r\n"); 284 | // sprintf(cmd,"AT+CMGR=%d\r\n",messageIndex); 285 | // sim808_send_cmd(cmd); 286 | sim808_clean_buffer(gprsBuffer,sizeof(gprsBuffer)); 287 | sim808_read_buffer(gprsBuffer,sizeof(gprsBuffer),DEFAULT_TIMEOUT); 288 | if(NULL != ( s = strstr(gprsBuffer,"+CMGR:"))){ 289 | if(NULL != ( s = strstr(s,"\r\n"))){ 290 | p = s + 2; 291 | while((*p != '\r')&&(i < length-1)) { 292 | message[i++] = *(p++); 293 | } 294 | message[i] = '\0'; 295 | return true; 296 | } 297 | } 298 | return false; 299 | } 300 | 301 | bool DFRobot_SIM808::deleteSMS(int index) 302 | { 303 | //char cmd[16]; 304 | char num[4]; 305 | //sprintf(cmd,"AT+CMGD=%d\r\n",index); 306 | sim808_send_cmd("AT+CMGD="); 307 | itoa(index, num, 10); 308 | sim808_send_cmd(num); 309 | //snprintf(cmd,sizeof(cmd),"AT+CMGD=%d\r\n",index); 310 | //sim808_send_cmd(cmd); 311 | //return 0; 312 | // We have to wait OK response 313 | //return sim808_check_with_cmd(cmd,"OK\r\n",CMD); 314 | return sim808_check_with_cmd("\r","OK\r\n",CMD); 315 | } 316 | 317 | bool DFRobot_SIM808::callUp(char *number) 318 | { 319 | //char cmd[24]; 320 | if(!sim808_check_with_cmd("AT+COLP=1\r\n","OK\r\n",CMD)) { 321 | return false; 322 | } 323 | delay(1000); 324 | //HACERR quitar SPRINTF para ahorar memoria ??? 325 | //sprintf(cmd,"ATD%s;\r\n", number); 326 | //sim808_send_cmd(cmd); 327 | sim808_send_cmd("ATD"); 328 | sim808_send_cmd(number); 329 | sim808_send_cmd(";\r\n"); 330 | return true; 331 | } 332 | 333 | void DFRobot_SIM808::answer(void) 334 | { 335 | sim808_send_cmd("ATA\r\n"); //TO CHECK: ATA doesnt return "OK" ???? 336 | } 337 | 338 | bool DFRobot_SIM808::hangup(void) 339 | { 340 | return sim808_check_with_cmd("ATH\r\n","OK\r\n",CMD); 341 | } 342 | 343 | bool DFRobot_SIM808::disableCLIPring(void) 344 | { 345 | return sim808_check_with_cmd("AT+CLIP=0\r\n","OK\r\n",CMD); 346 | } 347 | 348 | bool DFRobot_SIM808::getSubscriberNumber(char *number) 349 | { 350 | //AT+CNUM --> 7 + CR = 8 351 | //+CNUM: "","+628157933874",145,7,4 --> CRLF + 45 + CRLF = 49 352 | // --> 353 | //OK --> CRLF + 2 + CRLF = 6 354 | 355 | byte i = 0; 356 | char gprsBuffer[65]; 357 | char *p,*s; 358 | sim808_flush_serial(); 359 | sim808_send_cmd("AT+CNUM\r\n"); 360 | sim808_clean_buffer(gprsBuffer,65); 361 | sim808_read_buffer(gprsBuffer,65,DEFAULT_TIMEOUT); 362 | //Serial.print(gprsBuffer); 363 | if(NULL != ( s = strstr(gprsBuffer,"+CNUM:"))) { 364 | s = strstr((char *)(s),","); 365 | s = s + 2; //We are in the first phone number character 366 | p = strstr((char *)(s),"\""); //p is last character """ 367 | if (NULL != s) { 368 | i = 0; 369 | while (s < p) { 370 | number[i++] = *(s++); 371 | } 372 | number[i] = '\0'; 373 | } 374 | return true; 375 | } 376 | return false; 377 | } 378 | 379 | bool DFRobot_SIM808::isCallActive(char *number) 380 | { 381 | char gprsBuffer[46]; //46 is enough to see +CPAS: and CLCC: 382 | char *p, *s; 383 | int i = 0; 384 | 385 | sim808_send_cmd("AT+CPAS\r\n"); 386 | /*Result code: 387 | 0: ready 388 | 2: unknown 389 | 3: ringing 390 | 4: call in progress 391 | 392 | AT+CPAS --> 7 + 2 = 9 chars 393 | --> 2 char 394 | +CPAS: 3 --> 8 + 2 = 10 chars 395 | --> 2 char 396 | OK --> 2 + 2 = 4 chars 397 | 398 | AT+CPAS 399 | 400 | +CPAS: 0 401 | 402 | OK 403 | */ 404 | 405 | sim808_clean_buffer(gprsBuffer,29); 406 | sim808_read_buffer(gprsBuffer,27); 407 | //We are going to flush serial data until OK is recieved 408 | sim808_wait_for_resp("OK\r\n", CMD); 409 | //Serial.print("Buffer isCallActive 1: ");Serial.println(gprsBuffer); 410 | if(NULL != ( s = strstr(gprsBuffer,"+CPAS:"))) { 411 | s = s + 7; 412 | if (*s != '0') { 413 | //There is something "running" (but number 2 that is unknow) 414 | if (*s != '2') { 415 | //3 or 4, let's go to check for the number 416 | sim808_send_cmd("AT+CLCC\r\n"); 417 | /* 418 | AT+CLCC --> 9 419 | 420 | +CLCC: 1,1,4,0,0,"656783741",161,"" 421 | 422 | OK 423 | 424 | Without ringing: 425 | AT+CLCC 426 | OK 427 | */ 428 | 429 | sim808_clean_buffer(gprsBuffer,46); 430 | sim808_read_buffer(gprsBuffer,45); 431 | //Serial.print("Buffer isCallActive 2: ");Serial.println(gprsBuffer); 432 | if(NULL != ( s = strstr(gprsBuffer,"+CLCC:"))) { 433 | //There is at least one CALL ACTIVE, get number 434 | s = strstr((char *)(s),"\""); 435 | s = s + 1; //We are in the first phone number character 436 | p = strstr((char *)(s),"\""); //p is last character """ 437 | if (NULL != s) { 438 | i = 0; 439 | while (s < p) { 440 | number[i++] = *(s++); 441 | } 442 | number[i] = '\0'; 443 | } 444 | //I need to read more buffer 445 | //We are going to flush serial data until OK is recieved 446 | return sim808_wait_for_resp("OK\r\n", CMD); 447 | } 448 | } 449 | } 450 | } 451 | return false; 452 | } 453 | 454 | bool DFRobot_SIM808::getDateTime(char *buffer) 455 | { 456 | //If it doesn't work may be for two reasons: 457 | // 1. Your carrier doesn't give that information 458 | // 2. You have to configurate the SIM808 IC. 459 | // - First with SIM808_Serial_Debug example try this AT command: AT+CLTS? 460 | // - If response is 0, then it is disabled. 461 | // - Enable it by: AT+CLTS=1 462 | // - Now you have to save this config to EEPROM memory of SIM808 IC by: AT&W 463 | // - Now, you have to power down and power up again the SIM808 464 | // - Try now again: AT+CCLK? 465 | // - It should work 466 | 467 | //AT+CCLK? --> 8 + CR = 9 468 | //+CCLK: "14/11/13,21:14:41+04" --> CRLF + 29+ CRLF = 33 469 | // 470 | //OK --> CRLF + 2 + CRLF = 6 471 | 472 | byte i = 0; 473 | char gprsBuffer[50]; 474 | char *p,*s; 475 | sim808_flush_serial(); 476 | sim808_send_cmd("AT+CCLK?\r"); 477 | sim808_clean_buffer(gprsBuffer,50); 478 | sim808_read_buffer(gprsBuffer,50,DEFAULT_TIMEOUT); 479 | if(NULL != ( s = strstr(gprsBuffer,"+CCLK:"))) { 480 | s = strstr((char *)(s),"\""); 481 | s = s + 1; //We are in the first phone number character 482 | p = strstr((char *)(s),"\""); //p is last character """ 483 | if (NULL != s) { 484 | i = 0; 485 | while (s < p) { 486 | buffer[i++] = *(s++); 487 | } 488 | buffer[i] = '\0'; 489 | } 490 | return true; 491 | } 492 | return false; 493 | } 494 | 495 | bool DFRobot_SIM808::getSignalStrength(int *buffer) 496 | { 497 | //AT+CSQ --> 6 + CR = 10 498 | //+CSQ: , --> CRLF + 5 + CRLF = 9 499 | //OK --> CRLF + 2 + CRLF = 6 500 | 501 | byte i = 0; 502 | char gprsBuffer[26]; 503 | char *p, *s; 504 | char buffers[4]; 505 | sim808_flush_serial(); 506 | sim808_send_cmd("AT+CSQ\r"); 507 | sim808_clean_buffer(gprsBuffer, 26); 508 | sim808_read_buffer(gprsBuffer, 26, DEFAULT_TIMEOUT); 509 | if (NULL != (s = strstr(gprsBuffer, "+CSQ:"))) { 510 | s = strstr((char *)(s), " "); 511 | s = s + 1; //We are in the first phone number character 512 | p = strstr((char *)(s), ","); //p is last character """ 513 | if (NULL != s) { 514 | i = 0; 515 | while (s < p) { 516 | buffers[i++] = *(s++); 517 | } 518 | buffers[i] = '\0'; 519 | } 520 | *buffer = atoi(buffers); 521 | return true; 522 | } 523 | return false; 524 | } 525 | 526 | bool DFRobot_SIM808::sendUSSDSynchronous(char *ussdCommand, char *resultcode, char *response) 527 | { 528 | //AT+CUSD=1,"{command}" 529 | //OK 530 | // 531 | //+CUSD:1,"{response}",{int} 532 | 533 | byte i = 0; 534 | char gprsBuffer[200]; 535 | char *p,*s; 536 | sim808_clean_buffer(response, sizeof(response)); 537 | 538 | sim808_flush_serial(); 539 | sim808_send_cmd("AT+CUSD=1,\""); 540 | sim808_send_cmd(ussdCommand); 541 | sim808_send_cmd("\"\r"); 542 | if(!sim808_wait_for_resp("OK\r\n", CMD)) 543 | return false; 544 | sim808_clean_buffer(gprsBuffer,200); 545 | sim808_read_buffer(gprsBuffer,200,DEFAULT_TIMEOUT); 546 | if(NULL != ( s = strstr(gprsBuffer,"+CUSD: "))) { 547 | *resultcode = *(s+7); 548 | resultcode[1] = '\0'; 549 | if(!('0' <= *resultcode && *resultcode <= '2')) 550 | return false; 551 | s = strstr(s,"\""); 552 | s = s + 1; //We are in the first phone number character 553 | p = strstr(s,"\""); //p is last character """ 554 | if (NULL != s) { 555 | i = 0; 556 | while (s < p) { 557 | response[i++] = *(s++); 558 | } 559 | response[i] = '\0'; 560 | } 561 | return true; 562 | } 563 | return false; 564 | } 565 | 566 | bool DFRobot_SIM808::cancelUSSDSession(void) 567 | { 568 | return sim808_check_with_cmd("AT+CUSD=2\r\n","OK\r\n",CMD); 569 | } 570 | 571 | //Here is where we ask for APN configuration, with F() so we can save MEMORY 572 | bool DFRobot_SIM808::join(const __FlashStringHelper *apn, const __FlashStringHelper *userName, const __FlashStringHelper *passWord) 573 | { 574 | byte i; 575 | char *p, *s; 576 | char ipAddr[32]; 577 | //Select multiple connection 578 | //sim808_check_with_cmd("AT+CIPMUX=1\r\n","OK",DEFAULT_TIMEOUT,CMD); 579 | 580 | //set APN. OLD VERSION 581 | //snprintf(cmd,sizeof(cmd),"AT+CSTT=\"%s\",\"%s\",\"%s\"\r\n",_apn,_userName,_passWord); 582 | //sim808_check_with_cmd(cmd, "OK\r\n", DEFAULT_TIMEOUT,CMD); 583 | sim808_send_cmd("AT+CSTT=\""); 584 | if (apn) { 585 | sim808_send_cmd(apn); 586 | } 587 | sim808_send_cmd("\",\""); 588 | if (userName) { 589 | sim808_send_cmd(userName); 590 | } 591 | sim808_send_cmd("\",\""); 592 | if (passWord) { 593 | sim808_send_cmd(passWord); 594 | } 595 | sim808_check_with_cmd("\"\r\n", "OK\r\n", CMD); 596 | 597 | 598 | //Brings up wireless connection 599 | sim808_check_with_cmd("AT+CIICR\r\n","OK\r\n", CMD); 600 | 601 | //Get local IP address 602 | sim808_send_cmd("AT+CIFSR\r\n"); 603 | sim808_clean_buffer(ipAddr,32); 604 | sim808_read_buffer(ipAddr,32); 605 | //Response: 606 | //AT+CIFSR\r\n --> 8 + 2 607 | //\r\n --> 0 + 2 608 | //10.160.57.120\r\n --> 15 + 2 (max) : TOTAL: 29 609 | //Response error: 610 | //AT+CIFSR\r\n 611 | //\r\n 612 | //ERROR\r\n 613 | if (NULL != strstr(ipAddr,"ERROR")) { 614 | return false; 615 | } 616 | s = ipAddr + 11; 617 | p = strstr((char *)(s),"\r\n"); //p is last character \r\n 618 | if (NULL != s) { 619 | i = 0; 620 | while (s < p) { 621 | ip_string[i++] = *(s++); 622 | } 623 | ip_string[i] = '\0'; 624 | } 625 | _ip = str_to_ip(ip_string); 626 | if(_ip != 0) { 627 | return true; 628 | } 629 | return false; 630 | } 631 | 632 | void DFRobot_SIM808::disconnect() 633 | { 634 | sim808_send_cmd("AT+CIPSHUT\r\n"); 635 | } 636 | 637 | bool DFRobot_SIM808::connect(Protocol ptl,const char * host, int port, int timeout, int chartimeout) 638 | { 639 | //char cmd[64]; 640 | char num[4]; 641 | char resp[96]; 642 | 643 | //sim808_clean_buffer(cmd,64); 644 | if(ptl == TCP) { 645 | sim808_send_cmd("AT+CIPSTART=\"TCP\",\""); 646 | sim808_send_cmd(host); 647 | sim808_send_cmd("\","); 648 | itoa(port, num, 10); 649 | sim808_send_cmd(num); 650 | sim808_send_cmd("\r\n"); 651 | // sprintf(cmd, "AT+CIPSTART=\"TCP\",\"%s\",%d\r\n",host, port); 652 | } else if(ptl == UDP) { 653 | sim808_send_cmd("AT+CIPSTART=\"UDP\",\""); 654 | sim808_send_cmd(host); 655 | sim808_send_cmd("\","); 656 | itoa(port, num, 10); 657 | sim808_send_cmd(num); 658 | sim808_send_cmd("\r\n"); 659 | 660 | // sprintf(cmd, "AT+CIPSTART=\"UDP\",\"%s\",%d\r\n",host, port); 661 | } else { 662 | return false; 663 | } 664 | 665 | 666 | //sim808_send_cmd(cmd); 667 | sim808_read_buffer(resp, 96, timeout, chartimeout); 668 | //Serial.print("Connect resp: "); Serial.println(resp); 669 | if(NULL != strstr(resp,"CONNECT")) { //ALREADY CONNECT or CONNECT OK 670 | return true; 671 | } 672 | return false; 673 | } 674 | 675 | //Overload with F() macro to SAVE memory 676 | bool DFRobot_SIM808::connect(Protocol ptl,const __FlashStringHelper *host, const __FlashStringHelper *port, int timeout, int chartimeout) 677 | { 678 | //char cmd[64]; 679 | char resp[96]; 680 | 681 | //sim808_clean_buffer(cmd,64); 682 | if(ptl == TCP) { 683 | sim808_send_cmd(F("AT+CIPSTART=\"TCP\",\"")); //%s\",%d\r\n",host, port); 684 | } else if(ptl == UDP) { 685 | sim808_send_cmd(F("AT+CIPSTART=\"UDP\",\"")); //%s\",%d\r\n",host, port); 686 | } else { 687 | return false; 688 | } 689 | sim808_send_cmd(host); 690 | sim808_send_cmd(F("\",")); 691 | sim808_send_cmd(port); 692 | sim808_send_cmd(F("\r\n")); 693 | // Serial.print("Connect: "); Serial.println(cmd); 694 | sim808_read_buffer(resp, 96, timeout, chartimeout); 695 | // Serial.print("Connect resp: "); Serial.println(resp); 696 | if(NULL != strstr(resp,"CONNECT")) { //ALREADY CONNECT or CONNECT OK 697 | return true; 698 | } 699 | return false; 700 | } 701 | 702 | bool DFRobot_SIM808::is_connected(void) 703 | { 704 | char resp[96]; 705 | sim808_send_cmd("AT+CIPSTATUS\r\n"); 706 | sim808_read_buffer(resp,sizeof(resp),DEFAULT_TIMEOUT); 707 | if(NULL != strstr(resp,"CONNECTED")) { 708 | //+CIPSTATUS: 1,0,"TCP","216.52.233.120","80","CONNECTED" 709 | return true; 710 | } else { 711 | //+CIPSTATUS: 1,0,"TCP","216.52.233.120","80","CLOSED" 712 | //+CIPSTATUS: 0,,"","","","INITIAL" 713 | return false; 714 | } 715 | } 716 | 717 | bool DFRobot_SIM808::close() 718 | { 719 | // if not connected, return 720 | if (!is_connected()) { 721 | return true; 722 | } 723 | return sim808_check_with_cmd("AT+CIPCLOSE\r\n", "CLOSE OK\r\n", CMD); 724 | } 725 | 726 | int DFRobot_SIM808::readable(void) 727 | { 728 | return sim808_check_readable(); 729 | } 730 | 731 | int DFRobot_SIM808::wait_readable(int wait_time) 732 | { 733 | return sim808_wait_readable(wait_time); 734 | } 735 | 736 | int DFRobot_SIM808::wait_writeable(int req_size) 737 | { 738 | return req_size+1; 739 | } 740 | 741 | int DFRobot_SIM808::send(const char * str, int len) 742 | { 743 | //char cmd[32]; 744 | char num[4]; 745 | if(len > 0){ 746 | //snprintf(cmd,sizeof(cmd),"AT+CIPSEND=%d\r\n",len); 747 | //sprintf(cmd,"AT+CIPSEND=%d\r\n",len); 748 | sim808_send_cmd("AT+CIPSEND="); 749 | itoa(len, num, 10); 750 | sim808_send_cmd(num); 751 | if(!sim808_check_with_cmd("\r\n",">",CMD)) { 752 | //if(!sim808_check_with_cmd(cmd,">",CMD)) { 753 | return 0; 754 | } 755 | /*if(0 != sim808_check_with_cmd(str,"SEND OK\r\n", DEFAULT_TIMEOUT * 10 ,DATA)) { 756 | return 0; 757 | }*/ 758 | delay(500); 759 | sim808_send_cmd(str); 760 | delay(500); 761 | sim808_send_End_Mark(); 762 | if(!sim808_wait_for_resp("SEND OK\r\n", DATA, DEFAULT_TIMEOUT * 10, DEFAULT_INTERCHAR_TIMEOUT * 10)) { 763 | return 0; 764 | } 765 | } 766 | return len; 767 | } 768 | 769 | 770 | int DFRobot_SIM808::recv(char* buf, int len) 771 | { 772 | sim808_clean_buffer(buf,len); 773 | sim808_read_buffer(buf,len); //Ya he llamado a la funcion con la longitud del buffer - 1 y luego le estoy a diendo el 0 774 | return strlen(buf); 775 | } 776 | 777 | void DFRobot_SIM808::listen(void) 778 | { 779 | if(serialFlag) 780 | ; //hgprsSerial->listen(); 781 | else{ 782 | #if !defined(ESP32) 783 | gprsSerial->listen(); 784 | #endif 785 | } 786 | 787 | } 788 | 789 | bool DFRobot_SIM808::isListening(void) 790 | { 791 | return false; 792 | // if(serialFlag) 793 | // return hgprsSerial.isListening(); 794 | // else 795 | // return gprsSerial.isListening(); 796 | } 797 | 798 | uint32_t DFRobot_SIM808::str_to_ip(const char* str) 799 | { 800 | uint32_t ip = 0; 801 | char* p = (char*)str; 802 | for(int i = 0; i < 4; i++) { 803 | ip |= atoi(p); 804 | p = strchr(p, '.'); 805 | if (p == NULL) { 806 | break; 807 | } 808 | ip <<= 8; 809 | p++; 810 | } 811 | return ip; 812 | } 813 | 814 | char* DFRobot_SIM808::getIPAddress() 815 | { 816 | //I have already a buffer with ip_string: snprintf(ip_string, sizeof(ip_string), "%d.%d.%d.%d", (_ip>>24)&0xff,(_ip>>16)&0xff,(_ip>>8)&0xff,_ip&0xff); 817 | return ip_string; 818 | } 819 | 820 | unsigned long DFRobot_SIM808::getIPnumber() 821 | { 822 | return _ip; 823 | } 824 | /* NOT USED bool DFRobot_SIM808::gethostbyname(const char* host, uint32_t* ip) 825 | { 826 | uint32_t addr = str_to_ip(host); 827 | char buf[17]; 828 | //snprintf(buf, sizeof(buf), "%d.%d.%d.%d", (addr>>24)&0xff, (addr>>16)&0xff, (addr>>8)&0xff, addr&0xff); 829 | if (strcmp(buf, host) == 0) { 830 | *ip = addr; 831 | return true; 832 | } 833 | return false; 834 | } 835 | */ 836 | 837 | bool DFRobot_SIM808::getLocation(const __FlashStringHelper *apn, float *longitude, float *latitude) 838 | { 839 | int i = 0; 840 | char gprsBuffer[80]; 841 | char buffer[20]; 842 | char *s; 843 | 844 | //send AT+SAPBR=3,1,"Contype","DFRobot_SIM808" 845 | sim808_check_with_cmd("AT+SAPBR=3,1,\"Contype\",\"DFRobot_SIM808\"\r","OK\r\n",CMD); 846 | //sen AT+SAPBR=3,1,"APN","DFRobot_SIM808_APN" 847 | sim808_send_cmd("AT+SAPBR=3,1,\"APN\",\""); 848 | if (apn) { 849 | sim808_send_cmd(apn); 850 | } 851 | sim808_check_with_cmd("\"\r","OK\r\n",CMD); 852 | //send AT+SAPBR =1,1 853 | sim808_check_with_cmd("AT+SAPBR=1,1\r","OK\r\n",CMD); 854 | 855 | //AT+CIPGSMLOC=1,1 856 | sim808_flush_serial(); 857 | sim808_send_cmd("AT+CIPGSMLOC=1,1\r"); 858 | sim808_clean_buffer(gprsBuffer,sizeof(gprsBuffer)); 859 | sim808_read_buffer(gprsBuffer,sizeof(gprsBuffer),2*DEFAULT_TIMEOUT,6*DEFAULT_INTERCHAR_TIMEOUT); 860 | //Serial.println(gprsBuffer); 861 | 862 | if(NULL != ( s = strstr(gprsBuffer,"+CIPGSMLOC:"))) 863 | { 864 | s = strstr((char *)s, ","); 865 | s = s+1; 866 | //Serial.println(*s); 867 | i=0; 868 | while(*(++s) != ',') 869 | buffer[i++]=*s; 870 | buffer[i] = 0; 871 | *longitude = atof(buffer); 872 | 873 | i=0; 874 | while(*(++s) != ',') 875 | buffer[i++]=*s; 876 | buffer[i] = 0; 877 | *latitude = atof(buffer); 878 | return true; 879 | } 880 | return false; 881 | } 882 | 883 | bool DFRobot_SIM808::attachGPS() 884 | { 885 | if(!sim808_check_with_cmd("AT+CGNSPWR=1\r\n", "OK\r\n", CMD)) { 886 | return false; 887 | } 888 | if(!sim808_check_with_cmd("AT+CGNSTST=1\r\n", "OK\r\n", CMD)) { 889 | return false; 890 | } 891 | return true; 892 | } 893 | 894 | bool DFRobot_SIM808::detachGPS() 895 | { 896 | if(!sim808_check_with_cmd("AT+CGNSPWR=0\r\n", "OK\r\n", CMD)) { 897 | return false; 898 | } 899 | return true; 900 | } 901 | 902 | bool DFRobot_SIM808::getGPRMC() 903 | { 904 | char c; 905 | static bool endflag = false; 906 | static char count; 907 | 908 | while(serialSIM808->available()) 909 | { c = serialSIM808->read(); 910 | if(endflag) 911 | { 912 | if(count--) 913 | { 914 | receivedStack[receivedStackIndex++] = c; 915 | } 916 | else{ 917 | endflag = false; 918 | receivedStack[receivedStackIndex] = '\0'; 919 | return true; 920 | } 921 | } 922 | else 923 | { 924 | switch(c) 925 | { 926 | 927 | case '$': 928 | receivedStackIndex = 0; 929 | receivedStack[receivedStackIndex++] = c; 930 | break; 931 | case '*': 932 | endflag = true; 933 | count = 2; 934 | receivedStack[receivedStackIndex++] = c; 935 | break; 936 | default: 937 | if(receivedStackIndex < 120) 938 | receivedStack[receivedStackIndex++] = c; 939 | break; 940 | 941 | } 942 | return false; 943 | } 944 | return false; 945 | } 946 | return false; 947 | } 948 | 949 | bool DFRobot_SIM808::parseGPRMC(char *gpsbuffer) 950 | { 951 | if(strstr(gpsbuffer,des) == NULL) 952 | { 953 | receivedStackIndex = 0; 954 | return false; 955 | } 956 | else 957 | { 958 | if(gpsbuffer[18] == 'A') 959 | return true; 960 | else 961 | { 962 | //Serial.print("NO :"); 963 | //Serial.println(gpsbuffer[18]); 964 | return false; 965 | } 966 | 967 | } 968 | 969 | } 970 | 971 | // Parse a (potentially negative) number with up to 2 decimal digits -xxxx.yy 972 | int32_t DFRobot_SIM808::parseDecimal(const char *term) 973 | { 974 | bool negative = *term == '-'; 975 | if (negative) ++term; 976 | int32_t ret = 100 * (int32_t)atol(term); 977 | while (isdigit(*term)) ++term; 978 | if (*term == '.' && isdigit(term[1])) 979 | { 980 | ret += 10 * (term[1] - '0'); 981 | if (isdigit(term[2])) 982 | ret += term[2] - '0'; 983 | } 984 | return negative ? -ret : ret; 985 | } 986 | 987 | void DFRobot_SIM808::getTime(uint32_t time){ 988 | GPSdata.hour = time / 1000000; 989 | GPSdata.minute = (time / 10000) % 100; 990 | GPSdata.second = (time / 100) % 100; 991 | GPSdata.centisecond = time % 100; 992 | } 993 | 994 | void DFRobot_SIM808::getDate(uint32_t date){ 995 | uint16_t year = date % 100; 996 | GPSdata. year = year + 2000; 997 | GPSdata.month = (date / 100) % 100; 998 | GPSdata.day = date / 10000; 999 | } 1000 | 1001 | bool DFRobot_SIM808::getGPS() 1002 | { 1003 | if(!getGPRMC()) //没有得到$GPRMC字符串开头的GPS信息 1004 | return false; 1005 | // Serial.println(receivedStack); 1006 | if(!parseGPRMC(receivedStack)) //不是$GPRMC字符串开头的GPS信息 1007 | return false; 1008 | 1009 | // skip mode 1010 | char *tok = strtok(receivedStack, ","); //起始引导符 1011 | if (! tok) return false; 1012 | 1013 | // grab time //<1> UTC时间,格式为hhmmss.sss; 1014 | // tok = strtok(NULL, ","); 1015 | char *time = strtok(NULL, ","); 1016 | if (! time) return false; 1017 | uint32_t newTime = (uint32_t)parseDecimal(time); 1018 | getTime(newTime); 1019 | 1020 | // skip fix 1021 | tok = strtok(NULL, ","); //<2> 定位状态,A=有效定位,V=无效定位 1022 | if (! tok) return false; 1023 | 1024 | // grab the latitude 1025 | char *latp = strtok(NULL, ","); //<3> 纬度ddmm.mmmm(度分)格式(前面的0也将被传输) 1026 | if (! latp) return false; 1027 | 1028 | // grab latitude direction // <4> 纬度半球N(北半球)或S(南半球) 1029 | char *latdir = strtok(NULL, ","); 1030 | if (! latdir) return false; 1031 | 1032 | // grab longitude //<5> 经度dddmm.mmmm(度分)格式(前面的0也将被传输) 1033 | char *longp = strtok(NULL, ","); 1034 | if (! longp) return false; 1035 | 1036 | // grab longitude direction //<6> 经度半球E(东经)或W(西经) 1037 | char *longdir = strtok(NULL, ","); 1038 | if (! longdir) return false; 1039 | 1040 | float latitude = atof(latp); 1041 | float longitude = atof(longp); 1042 | 1043 | GPSdata.lat = (int)(latitude / 100) + (latitude - (int)(latitude / 100) * 100) / 60; 1044 | 1045 | // convert longitude from minutes to decimal 1046 | GPSdata.lon = (int)(longitude / 100) + (longitude - (int)(longitude / 100) * 100) / 60; 1047 | 1048 | // only grab speed if needed //<7> 地面速率(000.0~999.9节,前面的0也将被传输) 1049 | // if (speed_kph != NULL) { 1050 | 1051 | // grab the speed in knots 1052 | char *speedp = strtok(NULL, ","); 1053 | if (! speedp) return false; 1054 | 1055 | // convert to kph 1056 | //*speed_kph = atof(speedp) * 1.852; 1057 | GPSdata.speed_kph= atof(speedp) * 1.852; 1058 | 1059 | // } 1060 | 1061 | // only grab heading if needed 1062 | // if (heading != NULL) { 1063 | 1064 | // grab the speed in knots 1065 | char *coursep = strtok(NULL, ","); 1066 | if (! coursep) return false; 1067 | 1068 | //*heading = atof(coursep); 1069 | GPSdata.heading = atof(coursep); 1070 | // } 1071 | 1072 | // grab date 1073 | char *date = strtok(NULL, ","); 1074 | if (! date) return false; 1075 | uint32_t newDate = atol(date); 1076 | getDate(newDate); 1077 | 1078 | // no need to continue 1079 | // if (altitude == NULL){ 1080 | // return true; 1081 | //} 1082 | return true; 1083 | } 1084 | 1085 | void DFRobot_SIM808::latitudeConverToDMS() 1086 | { 1087 | float temp; 1088 | latDMS.degrees = (int)GPSdata.lat; 1089 | temp = (GPSdata.lat - latDMS.degrees)*60; 1090 | latDMS.minutes = (int)temp; 1091 | latDMS.seconeds = (temp - latDMS.minutes)*60; 1092 | } 1093 | 1094 | void DFRobot_SIM808::LongitudeConverToDMS() 1095 | { 1096 | float temp; 1097 | longDMS.degrees = (int)GPSdata.lon; 1098 | temp = (GPSdata.lon - longDMS.degrees)*60; 1099 | longDMS.minutes = (int)temp; 1100 | longDMS.seconeds = (temp - longDMS.minutes)*60; 1101 | } 1102 | 1103 | -------------------------------------------------------------------------------- /src/DFRobot_SIM808.h: -------------------------------------------------------------------------------- 1 | /*! 2 | * @file DFRobot_SIM808.h 3 | * @brief Define infrastructure of DFRobot_SIM808 class 4 | * @details Header file for DFRobot's SIM808 GPS/DFRobot_SIM808/GSM Shield. 5 | * @copyright Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com) 6 | * @license The MIT License (MIT) 7 | * @author [Jason](jason.ling@dfrobot.com) 8 | * @maintainer [qsjhyy](yihuan.huang@dfrobot.com) 9 | * @version V1.0 10 | * @date 2022-1-18 11 | * @url https://github.com/DFRobot/DFRobot_SIM808 12 | */ 13 | #ifndef __DFRobot_SIM808_H__ 14 | #define __DFRobot_SIM808_H__ 15 | 16 | #include "sim808.h" 17 | 18 | /** 19 | * @enum enum Protocol 20 | * @brief communication protocol 21 | */ 22 | enum Protocol { 23 | CLOSED = 0, 24 | TCP = 1, 25 | UDP = 2, 26 | }; 27 | 28 | class DFRobot_SIM808 29 | { 30 | public: 31 | 32 | #if !defined(ESP32) 33 | SoftwareSerial *gprsSerial; 34 | #endif 35 | HardwareSerial *hgprsSerial; 36 | Stream *sgprsSerial; 37 | 38 | /** 39 | * @struct struct gspdata 40 | * @brief GPS data structure 41 | */ 42 | struct gspdata{ 43 | uint16_t year; 44 | uint8_t month; 45 | uint8_t day; 46 | uint8_t hour; 47 | uint8_t minute; 48 | uint8_t second; 49 | uint8_t centisecond; 50 | float lat; 51 | float lon; 52 | float speed_kph; 53 | float heading; 54 | float altitude; 55 | }GPSdata; 56 | 57 | /** 58 | * @struct struct DMSData 59 | * @brief DMS data structure 60 | */ 61 | struct DMSData{ 62 | int degrees; 63 | int minutes; 64 | float seconeds; 65 | }latDMS,longDMS; 66 | 67 | public: 68 | /** 69 | * @fn DFRobot_SIM808 70 | * @brief Constructor 71 | * @param mySerial serial ports for communication, supporting hard and soft serial ports 72 | * @n Tx, rx, and baudRate can also be passed in this order 73 | * @return None 74 | */ 75 | #if !defined(ESP32) 76 | DFRobot_SIM808(SoftwareSerial *mySerial); 77 | #endif 78 | DFRobot_SIM808(HardwareSerial *mySerial); 79 | DFRobot_SIM808(uint8_t tx, uint8_t rx, uint32_t baudRate = 9600); 80 | 81 | /** 82 | * @fn getInstance 83 | * @brief get instance of DFRobot_SIM808 class 84 | * @return instance of DFRobot_SIM808 class 85 | */ 86 | static DFRobot_SIM808* getInstance() { return inst; }; 87 | 88 | /** 89 | * @fn init 90 | * @brief initialize DFRobot_SIM808 module including SIM card check & signal strength 91 | * @return true if connected, false otherwise 92 | */ 93 | bool init(void); 94 | 95 | /** 96 | * @fn checkPowerUp 97 | * @brief check if DFRobot_SIM808 module is powered on or not 98 | * @return true on success, false on error 99 | */ 100 | bool checkPowerUp(void); 101 | 102 | /** 103 | * @fn powerUpDown 104 | * @brief power Up DFRobot_SIM808 module (JP has to be soldered) 105 | * @param pin pin 9 connected to JP jumper so we can power up and down through software 106 | * @return None 107 | */ 108 | void powerUpDown(uint8_t pin); 109 | 110 | /** 111 | * @fn powerReset 112 | * @brief power reset for SIM800 board 113 | * @param pin (preconfigurated as OUTPUT) 114 | * @return None 115 | */ 116 | void powerReset(uint8_t pin); 117 | 118 | /** 119 | * @fn sendSMS 120 | * @brief send text SMS 121 | * @param number phone number which SMS will be send to 122 | * @param data message that will be send to 123 | * @return true on success, false on error 124 | */ 125 | bool sendSMS(char* number, char* data); 126 | 127 | /** 128 | * @fn isSMSunread 129 | * @brief Check if there is any UNREAD SMS: this function DOESN'T change the UNREAD status of the SMS 130 | * @return returned value 131 | * @retval 1~20 - on success, position/index where SMS is stored, suitable for the function ReadSMS 132 | * @retval -1 - on error 133 | * @retval 0 - there is no SMS with specified status (UNREAD) 134 | */ 135 | char isSMSunread(void); 136 | 137 | /** 138 | * @fn readSMS 139 | * @brief read SMS, phone and date if getting a SMS message. It changes SMS status to READ 140 | * @param messageIndex SIM position to read 141 | * @param message buffer used to get SMS message 142 | * @param length length of message buffer 143 | * @param phone buffer used to get SMS's sender phone number 144 | * @param datetime buffer used to get SMS's send datetime 145 | * @return true on success, false on error 146 | */ 147 | bool readSMS(int messageIndex, char *message, int length, char *phone, char *datetime); 148 | 149 | /** 150 | * @fn readSMS 151 | * @brief read SMS if getting a SMS message 152 | * @param buffer buffer that get from DFRobot_SIM808 module(when getting a SMS, DFRobot_SIM808 module will return a buffer array) 153 | * @param message buffer used to get SMS message 154 | * @param check whether to check phone number(we may only want to read SMS from specified phone number) 155 | * @return true on success, false on error 156 | */ 157 | bool readSMS(int messageIndex, char *message, int length); 158 | 159 | /** 160 | * @fn deleteSMS 161 | * @brief delete SMS message on SIM card 162 | * @param index the index number which SMS message will be delete 163 | * @return true on success, false on error 164 | */ 165 | bool deleteSMS(int index); 166 | 167 | /** 168 | * @fn callUp 169 | * @brief call someone 170 | * @param number the phone number which you want to call 171 | * @return true on success, false on error 172 | */ 173 | bool callUp(char* number); 174 | 175 | /** 176 | * @fn answer 177 | * @brief auto answer if coming a call 178 | * @return None 179 | */ 180 | void answer(void); 181 | 182 | /** 183 | * @fn hangup 184 | * @brief hang up if coming a call 185 | * @return true on success, false on error 186 | */ 187 | bool hangup(void); 188 | 189 | /** 190 | * @fn disableCLIPring 191 | * @brief Disable +CLIP notification when an incoming call is active, RING text is always shown. See isCallActive function 192 | * @note This is done in order no to overload serial outputCheck if there is a call active and get the phone number in that case 193 | * @return true on success, false on error 194 | */ 195 | bool disableCLIPring(void); 196 | 197 | /** 198 | * @fn getSubscriberNumber 199 | * @brief Get Subscriber Number (your number) using AT+CNUM command, but if nothing return, then 200 | * @n you need to command this to your SIM900. (See AT+CPBS, AT+CPBW) 201 | * @n AT+CPBS="ON" 202 | * @n AT+CPBW=1,"+{Your Number}",145 203 | * @n AT+CPBS="SM" 204 | * @param number your phone number 205 | * @return true on success, false on error 206 | */ 207 | bool getSubscriberNumber(char *number); 208 | 209 | /** 210 | * @fn isCallActive 211 | * @brief Check if there is a call active and get the phone number in that case 212 | * @param number Check if there is a call active and get the phone number in that case 213 | * @return true on success, false on error 214 | */ 215 | bool isCallActive(char *number); 216 | 217 | /** 218 | * @fn getDateTime 219 | * @brief get DateTime from SIM900 (see AT command: AT+CLTS=1) as string 220 | * @param buffer DateTime from SIM900 221 | * @return true on success, false on error 222 | * @note If it doesn't work may be for two reasons: 223 | * @n 1. Your carrier doesn't give that information 224 | * @n 2. You have to configurate the SIM900 IC. 225 | * @n - First with SIM900_Serial_Debug example try this AT command: AT+CLTS? 226 | * @n - If response is 0, then it is disabled. 227 | * @n - Enable it by: AT+CLTS=1 228 | * @n - Now you have to save this config to EEPROM memory of SIM900 IC by: AT&W 229 | * @n - Now, you have to power down and power up again the SIM900 230 | * @n - Try now again: AT+CCLK? 231 | * @n - It should work now 232 | * 233 | */ 234 | bool getDateTime(char *buffer); 235 | 236 | /** 237 | * @fn getSignalStrength 238 | * @brief get Signal Strength from SIM900 (see AT command: AT+CSQ) as integer 239 | * @param buffer Signal Strength 240 | * @return true on success, false on error 241 | */ 242 | bool getSignalStrength(int *buffer); 243 | 244 | /** 245 | * @fn sendUSSDSynchronous 246 | * @brief Send USSD Command Synchronously (Blocking call until unsolicited response is received) 247 | * @param ussdCommand command UUSD, ex: *123# 248 | * @param resultCode char Result Code, see AT+CUSD command 249 | * @param response string response 250 | * @return true on success, false on error 251 | */ 252 | bool sendUSSDSynchronous(char *ussdCommand, char *resultcode, char *response); 253 | 254 | /** 255 | * @fn cancelUSSDSession 256 | * @brief Cancel USSD Session 257 | * @return true on success cancel active session, false on error or because no active session 258 | */ 259 | bool cancelUSSDSession(void); 260 | 261 | /*************************** DFRobot_SIM808 ***************************/ 262 | 263 | /** 264 | * @fn join 265 | * @brief Connect the DFRobot_SIM808 module to the network. 266 | * @param apn APN(Access Point Name) 267 | * @param userName user name 268 | * @param passWord pass word 269 | * @return true if connected, false otherwise 270 | */ 271 | bool join(const __FlashStringHelper *apn = 0, const __FlashStringHelper *userName = 0, const __FlashStringHelper *passWord = 0); 272 | 273 | /** 274 | * @fn disconnect 275 | * @brief Disconnect the DFRobot_SIM808 module from the network 276 | * @return None 277 | */ 278 | void disconnect(void); 279 | 280 | /** 281 | * @fn connect 282 | * @brief Open a tcp/udp connection with the specified host on the specified port 283 | * @param ptl protocol for socket, TCP/UDP can be choosen 284 | * @param host host (can be either an ip address or a name. If a name is provided, a dns request will be established) 285 | * @param port port 286 | * @param timeout wait seconds till connected 287 | * @param chartimeout wait milliseconds between characters from DFRobot_SIM808 module 288 | * @return true if successful, false if error 289 | */ 290 | bool connect(Protocol ptl, const char * host, int port, int timeout = 2 * DEFAULT_TIMEOUT, int chartimeout = 2 * DEFAULT_INTERCHAR_TIMEOUT); 291 | bool connect(Protocol ptl, const __FlashStringHelper *host, const __FlashStringHelper *port, int timeout = 2 * DEFAULT_TIMEOUT, int chartimeout = 2 * DEFAULT_INTERCHAR_TIMEOUT); 292 | 293 | /** 294 | * @fn is_connected 295 | * @brief Check if a tcp link is active 296 | * @return true if successful, false if error 297 | */ 298 | bool is_connected(void); 299 | 300 | /** 301 | * @fn close 302 | * @brief Close a tcp connection 303 | * @return true if successful, false if error 304 | */ 305 | bool close(void); 306 | 307 | /** 308 | * @fn readable 309 | * @brief check if DFRobot_SIM808 module is readable or not 310 | * @return true if readable 311 | */ 312 | int readable(void); 313 | 314 | /** 315 | * @fn wait_readable 316 | * @brief wait a few time to check if DFRobot_SIM808 module is readable or not 317 | * @param wait_time time of waiting 318 | * @return Returns the length of readable data 319 | */ 320 | int wait_readable(int wait_time); 321 | 322 | /** 323 | * @fn wait_writeable 324 | * @brief wait a few time to check if DFRobot_SIM808 module is writeable or not 325 | * @param req_size time of waiting 326 | * @return req_size + 1 327 | */ 328 | int wait_writeable(int req_size); 329 | 330 | /** 331 | * @fn send 332 | * @brief send data to socket 333 | * @param str string to be sent 334 | * @param len string length 335 | * @return return bytes that actually been send 336 | */ 337 | int send(const char * str, int len); 338 | 339 | /** 340 | * @fn recv 341 | * @brief read data from socket 342 | * @param buf buffer that will store the data read from socket 343 | * @param len string length need to read from socket 344 | * @return bytes that actually read 345 | */ 346 | int recv(char* buf, int len); 347 | 348 | /** 349 | * @fn listen 350 | * @brief Enables the selected software serial port to listen 351 | * @return None 352 | */ 353 | void listen(void); 354 | 355 | /** 356 | * @fn isListening 357 | * @brief Tests to see if requested software serial port is actively listening. 358 | * @return Now masking enabled, return null 359 | */ 360 | bool isListening(void); 361 | 362 | /** 363 | * @fn gethostbyname 364 | * @brief convert the host to ip 365 | * @param host host ip string, ex. 10.11.12.13 366 | * @param ip long int ip address, ex. 0x11223344 367 | * @return true if successful 368 | */ 369 | //NOT USED bool gethostbyname(const char* host, uint32_t* ip); 370 | 371 | /** 372 | * @fn getIPAddress 373 | * @brief get IP address 374 | * @return IP address, char* 375 | */ 376 | char* getIPAddress(void); 377 | 378 | /** 379 | * @fn getIPnumber 380 | * @brief get IP number 381 | * @return IP number, unsigned long 382 | */ 383 | unsigned long getIPnumber(void); 384 | 385 | /** 386 | * @fn getLocation 387 | * @brief get Location 388 | * @param apn APN(Access Point Name) 389 | * @param longitude longitude 390 | * @param latitude latitude 391 | * @return true if successful, false if error 392 | */ 393 | bool getLocation(const __FlashStringHelper *apn, float *longitude, float *latitude); 394 | 395 | /** 396 | * @fn attachGPS 397 | * @brief Open GPS 398 | * @return true if successful, false if error 399 | */ 400 | bool attachGPS(void); 401 | 402 | /** 403 | * @fn detachGPS 404 | * @brief Close GPS 405 | * @return true if successful, false if error 406 | */ 407 | bool detachGPS(void); 408 | 409 | /** 410 | * @fn getTime 411 | * @brief parse time 412 | * @param time Time data to be parsed 413 | * @return None 414 | */ 415 | void getTime(uint32_t time); 416 | 417 | /** 418 | * @fn getDate 419 | * @brief parse date 420 | * @param date Date data to be parsed 421 | * @return None 422 | */ 423 | void getDate(uint32_t date); 424 | 425 | /** 426 | * @fn parseDecimal 427 | * @brief Parse a (potentially negative) number with up to 2 decimal digits -xxxx.yy 428 | * @param term Data to be parsed 429 | * @return Parsed data 430 | */ 431 | int32_t parseDecimal(const char *term); 432 | 433 | /** 434 | * @fn latitudeConverToDMS 435 | * @brief latitude Conver To DMS 436 | * @return None 437 | */ 438 | void latitudeConverToDMS(void); 439 | 440 | /** 441 | * @fn LongitudeConverToDMS 442 | * @brief Longitude Conver To DMS 443 | * @return None 444 | */ 445 | void LongitudeConverToDMS(void); 446 | 447 | /** 448 | * @fn parseGPRMC 449 | * @brief parser GPRMC, Determine whether gpsbuffer[18] is 'A' 450 | * @param gpsbuffer GPS buffer data to be parsed 451 | * @return true if gpsbuffer[18] is 'A' 452 | */ 453 | bool parseGPRMC(char *gpsbuffer); 454 | 455 | /** 456 | * @fn getGPRMC 457 | * @brief Get the parsed GPRMC 458 | * @return true if successful, false if error 459 | */ 460 | bool getGPRMC(void); 461 | 462 | /** 463 | * @fn getGPS 464 | * @brief get GPS signal 465 | * @return true if successful, false if error 466 | */ 467 | bool getGPS(void); 468 | 469 | private: 470 | /** 471 | * @fn checkSIMStatus 472 | * @brief check SIM status 473 | * @return true if successful, false if error 474 | */ 475 | bool checkSIMStatus(void); 476 | 477 | /** 478 | * @fn str_to_ip 479 | * @brief string ip to uint32_t ip 480 | * @param str IP string to be converted 481 | * @return uint32_t ip 482 | */ 483 | uint32_t str_to_ip(const char* str); 484 | 485 | private: 486 | static DFRobot_SIM808* inst; 487 | byte serialFlag; 488 | uint32_t _ip; 489 | char ip_string[16]; //XXX.YYY.ZZZ.WWW + \0 490 | }; 491 | #endif 492 | -------------------------------------------------------------------------------- /src/sim808.cpp: -------------------------------------------------------------------------------- 1 | /*! 2 | * @file sim808.h 3 | * @brief A library for DFRobot's SIM808 GPS/GPRS/GSM Shield 4 | * @copyright Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com) 5 | * @license The MIT License (MIT) 6 | * @author [Jason](jason.ling@dfrobot.com) 7 | * @maintainer [qsjhyy](yihuan.huang@dfrobot.com) 8 | * @version V1.0 9 | * @date 2022-02-08 10 | * @url https://github.com/DFRobot/DFRobot_SIM808 11 | */ 12 | #include "sim808.h" 13 | 14 | //SoftwareSerial *serialSIM808 = NULL; 15 | 16 | Stream *serialSIM808 = NULL; 17 | 18 | /* 19 | void sim808_init(void * uart_device, uint32_t baud) 20 | { 21 | serialSIM808 = (SoftwareSerial*)uart_device; 22 | serialSIM808->begin(baud); 23 | } 24 | 25 | */ 26 | 27 | void sim808_init(void * uart_device, char num) 28 | { 29 | if(num) 30 | serialSIM808 = (HardwareSerial*)uart_device; 31 | else{ 32 | #if !defined(ESP32) 33 | serialSIM808 = (SoftwareSerial*)uart_device; 34 | #endif 35 | } 36 | } 37 | 38 | 39 | int sim808_check_readable() 40 | { 41 | return serialSIM808->available(); 42 | } 43 | 44 | int sim808_wait_readable (int wait_time) 45 | { 46 | unsigned long timerStart; 47 | int dataLen = 0; 48 | timerStart = millis(); 49 | while((unsigned long) (millis() - timerStart) > wait_time * 1000UL) { 50 | delay(500); 51 | dataLen = sim808_check_readable(); 52 | if(dataLen > 0){ 53 | break; 54 | } 55 | } 56 | return dataLen; 57 | } 58 | 59 | void sim808_flush_serial() 60 | { 61 | while(sim808_check_readable()){ 62 | serialSIM808->read(); 63 | } 64 | } 65 | 66 | void sim808_read_buffer(char *buffer, int count, unsigned int timeout, unsigned int chartimeout) 67 | { 68 | int i = 0; 69 | unsigned long timerStart, prevChar; 70 | timerStart = millis(); 71 | prevChar = 0; 72 | while(1) { 73 | while (sim808_check_readable()) { 74 | char c = serialSIM808->read(); 75 | prevChar = millis(); 76 | buffer[i++] = c; 77 | if(i >= count)break; 78 | } 79 | if(i >= count)break; 80 | if ((unsigned long) (millis() - timerStart) > timeout * 1000UL) { 81 | break; 82 | } 83 | //If interchar Timeout => return FALSE. So we can return sooner from this function. Not DO it if we dont recieve at least one char (prevChar <> 0) 84 | if (((unsigned long) (millis() - prevChar) > chartimeout) && (prevChar != 0)) { 85 | break; 86 | } 87 | } 88 | } 89 | 90 | void sim808_clean_buffer(char *buffer, int count) 91 | { 92 | for(int i=0; i < count; i++) { 93 | buffer[i] = '\0'; 94 | } 95 | } 96 | 97 | //HACERR quitar esta funcion ? 98 | void sim808_send_byte(uint8_t data) 99 | { 100 | serialSIM808->write(data); 101 | } 102 | 103 | void sim808_send_char(const char c) 104 | { 105 | serialSIM808->write(c); 106 | } 107 | 108 | void sim808_send_cmd(const char* cmd) 109 | { 110 | for(uint16_t i=0; iread(); 151 | prevChar = millis(); 152 | sum = (c==resp[sum]) ? sum+1 : 0; 153 | if(sum == len)break; 154 | } 155 | if ((unsigned long) (millis() - timerStart) > timeout * 1000UL) { 156 | return false; 157 | } 158 | //If interchar Timeout => return FALSE. So we can return sooner from this function. 159 | if (((unsigned long) (millis() - prevChar) > chartimeout) && (prevChar != 0)) { 160 | return false; 161 | } 162 | 163 | } 164 | //If is a CMD, we will finish to read buffer. 165 | if(type == CMD) sim808_flush_serial(); 166 | return true; 167 | } 168 | 169 | 170 | boolean sim808_check_with_cmd(const char* cmd, const char *resp, DataType type, unsigned int timeout, unsigned int chartimeout) 171 | { 172 | sim808_send_cmd(cmd); 173 | return sim808_wait_for_resp(resp,type,timeout,chartimeout); 174 | } 175 | 176 | //HACERR que tambien la respuesta pueda ser FLASH STRING 177 | boolean sim808_check_with_cmd(const __FlashStringHelper* cmd, const char *resp, DataType type, unsigned int timeout, unsigned int chartimeout) 178 | { 179 | sim808_send_cmd(cmd); 180 | return sim808_wait_for_resp(resp,type,timeout,chartimeout); 181 | } 182 | -------------------------------------------------------------------------------- /src/sim808.h: -------------------------------------------------------------------------------- 1 | /*! 2 | * @file sim808.h 3 | * @brief A library for DFRobot's SIM808 GPS/GPRS/GSM Shield 4 | * @copyright Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com) 5 | * @license The MIT License (MIT) 6 | * @author [Jason](jason.ling@dfrobot.com) 7 | * @maintainer [qsjhyy](yihuan.huang@dfrobot.com) 8 | * @version V1.0 9 | * @date 2022-02-08 10 | * @url https://github.com/DFRobot/DFRobot_SIM808 11 | */ 12 | #ifndef __SIM808_H__ 13 | #define __SIM808_H__ 14 | 15 | #include 16 | #if !defined(ESP32) 17 | #include 18 | #endif 19 | 20 | #define DEFAULT_TIMEOUT 5 //seconds 21 | #define DEFAULT_INTERCHAR_TIMEOUT 1500 //miliseconds 22 | 23 | /** 24 | * @enum enum DataType 25 | * @brief Data Type, command or data 26 | */ 27 | enum DataType { 28 | CMD = 0, 29 | DATA = 1, 30 | }; 31 | 32 | /** 33 | * @fn sim808_init 34 | * @brief sim808 initialization 35 | * @param uart_device serial ports for communication, supporting hard and soft serial ports 36 | * @param num It is used to determine whether the serial port is hard or soft 37 | * @return None 38 | */ 39 | void sim808_init(void * uart_device, char num ); 40 | //void sim808_init(void * uart_device, uint32_t baud); 41 | 42 | /** 43 | * @fn sim808_check_readable 44 | * @brief Check whether Sim808 is readable 45 | * @return Returns the number of bytes currently readable by the SERIAL port of SIM808 46 | */ 47 | int sim808_check_readable(void); 48 | 49 | /** 50 | * @fn sim808_wait_readable 51 | * @brief Wait until SIM808 becomes readable 52 | * @param wait_time Wait time, in seconds 53 | * @return Returns the number of bytes that SIM808 can read during the wait time, or 0 until the wait time is over 54 | */ 55 | int sim808_wait_readable(int wait_time); 56 | 57 | /** 58 | * @fn sim808_flush_serial 59 | * @brief sim808 flush serial 60 | * @return None 61 | */ 62 | void sim808_flush_serial(void); 63 | 64 | /** 65 | * @fn sim808_read_buffer 66 | * @brief sim808 read buffer 67 | * @param buffer The space in which read data is stored 68 | * @param count The length of data to read 69 | * @param timeout seconds 70 | * @param chartimeout miliseconds 71 | * @return None 72 | */ 73 | void sim808_read_buffer(char* buffer, int count, unsigned int timeout=DEFAULT_TIMEOUT, unsigned int chartimeout = DEFAULT_INTERCHAR_TIMEOUT); 74 | 75 | /** 76 | * @fn sim808_clean_buffer 77 | * @brief clear buffer 78 | * @param buffer data buffer 79 | * @param count Length of data to clear 80 | * @return None 81 | */ 82 | void sim808_clean_buffer(char* buffer, int count); 83 | 84 | /** 85 | * @fn sim808_send_byte 86 | * @brief sim808 send one byte of data 87 | * @param data Data to be sent 88 | * @return None 89 | */ 90 | void sim808_send_byte(uint8_t data); 91 | 92 | /** 93 | * @fn sim808_send_char 94 | * @brief sim808 send a char data 95 | * @param c char data to be sent 96 | * @return None 97 | */ 98 | void sim808_send_char(const char c); 99 | 100 | /** 101 | * @fn sim808_send_cmd 102 | * @brief sim808 send a command 103 | * @param cmd command data to be sent 104 | * @return None 105 | */ 106 | void sim808_send_cmd(const char* cmd); 107 | void sim808_send_cmd(const __FlashStringHelper* cmd); 108 | 109 | /** 110 | * @fn sim808_send_cmd_P 111 | * @brief sim808 send the flash command 112 | * @param cmd flash command data to be sent 113 | * @return None 114 | */ 115 | void sim808_send_cmd_P(const char* cmd); 116 | 117 | /** 118 | * @fn sim808_send_AT 119 | * @brief sim808 send AT 120 | * @return true on success, false on error 121 | */ 122 | boolean sim808_send_AT(void); 123 | 124 | /** 125 | * @fn sim808_send_End_Mark 126 | * @brief sim808 send end mark 127 | * @return None 128 | */ 129 | void sim808_send_End_Mark(void); 130 | 131 | /** 132 | * @fn sim808_wait_for_resp 133 | * @brief sim808 wait for response 134 | * @param resp Required response, typically "OK" 135 | * @param type If is a CMD, we will finish to read buffer. 136 | * @param timeout seconds 137 | * @param chartimeout miliseconds 138 | * @return true on success, false on error 139 | */ 140 | boolean sim808_wait_for_resp(const char* resp, DataType type, unsigned int timeout = DEFAULT_TIMEOUT, unsigned int chartimeout = DEFAULT_INTERCHAR_TIMEOUT); 141 | 142 | /** 143 | * @fn sim808_check_with_cmd 144 | * @brief sim808 send data and wait for a response 145 | * @param cmd command data to be sent 146 | * @param resp Required response, typically "OK" 147 | * @param type If is a CMD, we will finish to read buffer. 148 | * @param timeout seconds 149 | * @param chartimeout miliseconds 150 | * @return true on success, false on error 151 | */ 152 | boolean sim808_check_with_cmd(const char* cmd, const char *resp, DataType type, unsigned int timeout = DEFAULT_TIMEOUT, unsigned int chartimeout = DEFAULT_INTERCHAR_TIMEOUT*5); 153 | boolean sim808_check_with_cmd(const __FlashStringHelper* cmd, const char *resp, DataType type, unsigned int timeout = DEFAULT_TIMEOUT, unsigned int chartimeout = DEFAULT_INTERCHAR_TIMEOUT); 154 | 155 | #endif 156 | --------------------------------------------------------------------------------