├── .gitlab-ci.yml ├── library.properties ├── .travis.yml ├── .gitattributes ├── .github └── workflows │ └── sync_issues.yml ├── examples ├── SIM900_Serial_Debug │ └── SIM900_Serial_Debug.ino ├── GPRS_CallUp │ └── GPRS_CallUp.ino ├── GPRS_SendSMS │ └── GPRS_SendSMS.ino ├── GPRS_TCPConnection │ └── GPRS_TCPConnection.ino ├── GPRS_LoopHandle │ └── GPRS_LoopHandle.ino └── GPRS_SMSread │ └── GPRS_SMSread.ino ├── keywords.txt ├── License.txt ├── sim900_Suli.h ├── README.md ├── .gitignore ├── sim900_Suli.cpp ├── GPRS_Shield_Arduino.h └── GPRS_Shield_Arduino.cpp /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | build: 2 | tags: 3 | - nas 4 | script: 5 | - wget -c https://files.seeedstudio.com/arduino/seeed-arduino-ci.sh 6 | - chmod +x seeed-arduino-ci.sh 7 | - bash $PWD/seeed-arduino-ci.sh test 8 | 9 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=GPRS Shield Suli 2 | version=1.0.0 3 | author=Seeed Studio 4 | maintainer=Seeed Studio 5 | sentence=Arduino library to control GPRS Shield V3.0 with Suli. 6 | paragraph=Arduino library to control GPRS Shield V3.0 with Suli. 7 | category=Device Control 8 | url=https://github.com/Seeed-Studio/GPRS_Shield_Suli 9 | architectures=* 10 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | 2 | language: generic 3 | dist: bionic 4 | sudo: false 5 | cache: 6 | directories: 7 | - ~/arduino_ide 8 | - ~/.arduino15/packages/ 9 | 10 | before_install: 11 | - wget -c https://files.seeedstudio.com/arduino/seeed-arduino-ci.sh 12 | 13 | script: 14 | - chmod +x seeed-arduino-ci.sh 15 | - cat $PWD/seeed-arduino-ci.sh 16 | - bash $PWD/seeed-arduino-ci.sh test 17 | 18 | notifications: 19 | email: 20 | on_success: change 21 | on_failure: change 22 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /.github/workflows/sync_issues.yml: -------------------------------------------------------------------------------- 1 | name: Automate Issue Management 2 | 3 | on: 4 | issues: 5 | types: 6 | - opened 7 | - edited 8 | - assigned 9 | - unassigned 10 | - labeled 11 | - unlabeled 12 | - reopened 13 | 14 | jobs: 15 | add_issue_to_project: 16 | runs-on: ubuntu-latest 17 | steps: 18 | - name: Add issue to GitHub Project 19 | uses: actions/add-to-project@v1.0.2 20 | with: 21 | project-url: https://github.com/orgs/Seeed-Studio/projects/17 22 | github-token: ${{ secrets.ISSUE_ASSEMBLE }} 23 | labeled: bug 24 | label-operator: NOT -------------------------------------------------------------------------------- /examples/SIM900_Serial_Debug/SIM900_Serial_Debug.ino: -------------------------------------------------------------------------------- 1 | /* 2 | SIM900 Serial Debug 3 | 4 | This sketch is used to communicate with SIM900 with AT commands. 5 | 6 | create on 2013/12/5, version: 0.1 7 | by lawliet.zou(lawliet.zou@gmail.com) 8 | */ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | const int pin_tx = 7; 16 | const int pin_rx = 8; 17 | 18 | SoftwareSerial gprs(pin_tx, pin_rx); //TX,RX 19 | 20 | void setup() { 21 | Serial.begin(9600); 22 | sim900_init(&gprs, -1, 9600); 23 | } 24 | 25 | void loop() { 26 | if (gprs.available()) { 27 | Serial.write(gprs.read()); 28 | } 29 | if (Serial.available()) { 30 | gprs.write(Serial.read()); 31 | } 32 | } 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | 2 | ####################################### 3 | # Syntax Coloring Map For GPRS Shield Suli 4 | ####################################### 5 | 6 | ####################################### 7 | # Datatypes (KEYWORD1) 8 | ####################################### 9 | 10 | ####################################### 11 | # Methods and Functions (KEYWORD2) 12 | ####################################### 13 | init KEYWORD2 14 | checkPowerUp KEYWORD2 15 | powerUpDown KEYWORD2 16 | sendSMS KEYWORD2 17 | isSMSunread KEYWORD2 18 | readSMS KEYWORD2 19 | readSMS KEYWORD2 20 | deleteSMS KEYWORD2 21 | callUp KEYWORD2 22 | disableCLIPring KEYWORD2 23 | isCallActive KEYWORD2 24 | answer KEYWORD2 25 | hangup KEYWORD2 26 | getDateTime KEYWORD2 27 | 28 | ####################################### 29 | # Constants (LITERAL1) 30 | ####################################### -------------------------------------------------------------------------------- /examples/GPRS_CallUp/GPRS_CallUp.ino: -------------------------------------------------------------------------------- 1 | /* 2 | GPRS Call Up 3 | 4 | This sketch is used to test seeeduino GPRS_Shield's callUp function. 5 | to make it work, you should insert SIM card to Seeeduino GPRS 6 | and replace the phoneNumber,enjoy it! 7 | 8 | create on 2013/12/5, version: 0.1 9 | by lawliet.zou(lawliet.zou@gmail.com) 10 | */ 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #define PIN_TX 7 17 | #define PIN_RX 8 18 | #define BAUDRATE 9600 19 | #define PHONE_NUMBER "186****2964" 20 | 21 | GPRS gprsTest(PIN_TX, PIN_RX, BAUDRATE); //RX,TX,PWR,BaudRate 22 | 23 | void setup() { 24 | Serial.begin(9600); 25 | while (0 != gprsTest.init()) { //gprs init 26 | delay(1000); 27 | Serial.print("init error\r\n"); 28 | } 29 | Serial.println("gprs init success"); 30 | Serial.println("start to call ..."); 31 | gprsTest.callUp(PHONE_NUMBER); 32 | } 33 | 34 | void loop() { 35 | //nothing to do 36 | } 37 | -------------------------------------------------------------------------------- /examples/GPRS_SendSMS/GPRS_SendSMS.ino: -------------------------------------------------------------------------------- 1 | /* 2 | GPRS Connect TCP 3 | 4 | This sketch is used to test seeeduino GPRS_Shield's send SMS func. 5 | to make it work, you should insert SIM card to Seeeduino GPRS 6 | and replace the phoneNumber,enjoy it! 7 | 8 | create on 2013/12/5, version: 0.1 9 | by lawliet.zou(lawliet.zou@gmail.com) 10 | */ 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #define PIN_TX 7 17 | #define PIN_RX 8 18 | #define BAUDRATE 9600 19 | #define PHONE_NUMBER "186****2964" 20 | #define MESSAGE "hello,world" 21 | 22 | GPRS gprsTest(PIN_TX, PIN_RX, BAUDRATE); //RX,TX,BaudRate 23 | 24 | void setup() { 25 | Serial.begin(9600); 26 | while (0 != gprsTest.init()) { 27 | delay(1000); 28 | Serial.print("init error\r\n"); 29 | } 30 | Serial.println("gprs init success"); 31 | Serial.println("start to send message ..."); 32 | gprsTest.sendSMS(PHONE_NUMBER, MESSAGE); //define phone number and text 33 | } 34 | 35 | void loop() { 36 | //nothing to do 37 | } 38 | -------------------------------------------------------------------------------- /License.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Seeed Technology Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /examples/GPRS_TCPConnection/GPRS_TCPConnection.ino: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #define PIN_TX 7 8 | #define PIN_RX 8 9 | //make sure that the baud rate of SIM900 is 9600! 10 | //you can use the AT Command(AT+IPR=9600) to set it through SerialDebug 11 | #define BAUDRATE 9600 12 | 13 | char http_cmd[] = "GET /media/uploads/mbed_official/hello.txt HTTP/1.0\r\n\r\n"; 14 | char buffer[512]; 15 | GPRS gprs(PIN_TX, PIN_RX, BAUDRATE); 16 | void setup() { 17 | Serial.begin(9600); 18 | // use DHCP 19 | gprs.init(); 20 | // attempt DHCP 21 | while (false == gprs.join(F("cmnet"))) { 22 | Serial.println("gprs join network error"); 23 | delay(2000); 24 | } 25 | 26 | // successful DHCP 27 | Serial.print("IP Address is "); 28 | Serial.println(gprs.getIPAddress()); 29 | 30 | if (false == gprs.connect(TCP, "mbed.org", 80)) { 31 | Serial.println("connect error"); 32 | } else { 33 | Serial.println("connect mbed.org success"); 34 | } 35 | 36 | Serial.println("waiting to fetch..."); 37 | gprs.send(http_cmd, sizeof(http_cmd) - 1); 38 | while (true) { 39 | int ret = gprs.recv(buffer, sizeof(buffer) - 1); 40 | if (ret <= 0) { 41 | Serial.println("fetch over..."); 42 | break; 43 | } 44 | buffer[ret] = '\0'; 45 | Serial.print("Recv: "); 46 | Serial.print(ret); 47 | Serial.print(" bytes: "); 48 | Serial.println(buffer); 49 | } 50 | gprs.close(); 51 | gprs.disconnect(); 52 | } 53 | 54 | void loop() { 55 | 56 | } 57 | -------------------------------------------------------------------------------- /examples/GPRS_LoopHandle/GPRS_LoopHandle.ino: -------------------------------------------------------------------------------- 1 | /* 2 | GPRS Loop Handle 3 | 4 | This sketch is used to test seeeduino GPRS_Shield's call answering and 5 | reading SMS function.To make it work, you should insert SIM card 6 | to Seeeduino GPRS Shield,enjoy it! 7 | 8 | create on 2013/12/5, version: 0.1 9 | by lawliet.zou(lawliet.zou@gmail.com) 10 | */ 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #define PIN_TX 7 17 | #define PIN_RX 8 18 | #define BAUDRATE 9600 19 | 20 | #define MESSAGE_LENGTH 20 21 | 22 | char gprsBuffer[64]; 23 | int i = 0; 24 | char* s = NULL; 25 | int inComing = 0; 26 | 27 | GPRS gprsTest(PIN_TX, PIN_RX, BAUDRATE); //RX,TX,PWR,BaudRate 28 | 29 | void setup() { 30 | Serial.begin(9600); 31 | while (0 != gprsTest.init()) { 32 | delay(1000); 33 | Serial.print("init error\r\n"); 34 | } 35 | delay(3000); 36 | Serial.println("Init Success, please call or send SMS message to me!"); 37 | } 38 | 39 | void loop() { 40 | if (gprsTest.readable()) { 41 | inComing = 1; 42 | } else { 43 | delay(100); 44 | } 45 | 46 | if (inComing) { 47 | sim900_read_buffer(gprsBuffer, 32, DEFAULT_TIMEOUT); 48 | //Serial.print(gprsBuffer); 49 | 50 | if (NULL != strstr(gprsBuffer, "RING")) { 51 | gprsTest.answer(); 52 | } else if (NULL != (s = strstr(gprsBuffer, "+CMTI: \"SM\""))) { //SMS: $$+CMTI: "SM",24$$ 53 | char message[MESSAGE_LENGTH]; 54 | int messageIndex = atoi(s + 12); 55 | gprsTest.readSMS(messageIndex, message, MESSAGE_LENGTH); 56 | Serial.print("Recv Message: "); 57 | Serial.println(message); 58 | } 59 | sim900_clean_buffer(gprsBuffer, 32); 60 | inComing = 0; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /examples/GPRS_SMSread/GPRS_SMSread.ino: -------------------------------------------------------------------------------- 1 | /* 2 | GPRS SMS Read 3 | 4 | This sketch is used to test seeeduino GPRS_Shield's reading SMS 5 | function.To make it work, you should insert SIM card 6 | to Seeeduino GPRS Shield,enjoy it! 7 | 8 | There are two methods to read SMS: 9 | 1. GPRS_LoopHandle.ino -> in order to recieve "+CMTI: "SM"" 10 | may be you need to send this command to your shield: "AT+CNMI=2,2,0,0,0" 11 | 2. GPRS_SMSread.ino -> you have to check if there are any 12 | UNREAD sms, and you don't need to check serial data continuosly 13 | 14 | create on 2014/10/16, version: 0.1 15 | by op2op2op2(op2op2op2@hotmail.com) 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #define PIN_TX 7 24 | #define PIN_RX 8 25 | #define BAUDRATE 9600 26 | 27 | #define MESSAGE_LENGTH 160 28 | char message[MESSAGE_LENGTH]; 29 | int messageIndex = 0; 30 | 31 | char phone[16]; 32 | char datetime[24]; 33 | 34 | GPRS gprsTest(PIN_TX, PIN_RX, BAUDRATE); //RX,TX,PWR,BaudRate 35 | 36 | void setup() { 37 | Serial.begin(9600); 38 | while (0 != gprsTest.init()) { 39 | delay(1000); 40 | Serial.print("init error\r\n"); 41 | } 42 | delay(3000); 43 | Serial.println("Init Success, please send SMS message to me!"); 44 | } 45 | 46 | void loop() { 47 | messageIndex = gprsTest.isSMSunread(); 48 | if (messageIndex > 0) { //At least, there is one UNREAD SMS 49 | gprsTest.readSMS(messageIndex, message, MESSAGE_LENGTH, phone, datetime); 50 | //In order not to full SIM Memory, is better to delete it 51 | gprsTest.deleteSMS(messageIndex); 52 | Serial.print("From number: "); 53 | Serial.println(phone); 54 | Serial.print("Datetime: "); 55 | Serial.println(datetime); 56 | Serial.print("Recieved Message: "); 57 | Serial.println(message); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /sim900_Suli.h: -------------------------------------------------------------------------------- 1 | /* 2 | sim900_Suli.h 3 | A library for SeeedStudio seeeduino GPRS shield 4 | 5 | Copyright (c) 2014 seeed technology inc. 6 | Website : www.seeed.cc 7 | Author : lawliet zou 8 | Create Time: April 2015 9 | Change Log : 10 | 11 | The MIT License (MIT) 12 | 13 | Permission is hereby granted, free of charge, to any person obtaining a copy 14 | of this software and associated documentation files (the "Software"), to deal 15 | in the Software without restriction, including without limitation the rights 16 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 | copies of the Software, and to permit persons to whom the Software is 18 | furnished to do so, subject to the following conditions: 19 | 20 | The above copyright notice and this permission notice shall be included in 21 | all copies or substantial portions of the Software. 22 | 23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 29 | THE SOFTWARE. 30 | */ 31 | 32 | #ifndef __SIM900_SULI_H__ 33 | #define __SIM900_SULI_H__ 34 | 35 | #include "Suli.h" 36 | #include 37 | 38 | // IDE just include this #define TRUE 1 39 | // IDE just include this #define FALSE 0 40 | #define DEFAULT_TIMEOUT 5 //Segundos 41 | #define DEFAULT_INTERCHAR_TIMEOUT 1500 //miliseconds 42 | 43 | enum DataType { 44 | CMD = 0, 45 | DATA = 1, 46 | }; 47 | 48 | void sim900_init(void* uart_device, int16 uart_num, uint32 baud); 49 | int sim900_check_readable(); 50 | int sim900_wait_readable(int wait_time); 51 | void sim900_flush_serial(); 52 | char sim900_read_byte(void); 53 | int sim900_read_buffer(char* buffer, int count, unsigned int timeout = DEFAULT_TIMEOUT, 54 | unsigned int chartimeout = DEFAULT_INTERCHAR_TIMEOUT); 55 | void sim900_clean_buffer(char* buffer, int count); 56 | void sim900_send_cmd(const char* cmd); 57 | void sim900_send_cmd(const __FlashStringHelper* cmd); 58 | void sim900_send_cmd_P(const char* cmd); 59 | void sim900_send_char(const char c); 60 | void sim900_send_AT(void); 61 | void sim900_send_End_Mark(void); 62 | //NOT USED bool sim900_response_cmp(uint8_t* resp, unsigned int len, unsigned int timeout); 63 | int sim900_wait_for_resp(const char* resp, DataType type, unsigned int timeout = DEFAULT_TIMEOUT, 64 | unsigned int chartimeout = DEFAULT_INTERCHAR_TIMEOUT); 65 | int sim900_check_with_cmd(const char* cmd, const char* resp, DataType type, unsigned int timeout = DEFAULT_TIMEOUT, 66 | unsigned int chartimeout = DEFAULT_INTERCHAR_TIMEOUT); 67 | //FUTURE: use with F() macro: int sim900_check_with_cmd(const __FlashStringHelper* cmd, const char *resp, unsigned timeout, DataType type); 68 | 69 | #endif 70 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## GPRS Shield Suli [![Build Status](https://travis-ci.com/Seeed-Studio/GPRS_Shield_Suli.svg?branch=master)](https://travis-ci.com/Seeed-Studio/GPRS_Shield_Suli) 2 | 3 | ![](https://statics3.seeedstudio.com/images/product/113030009%201.jpg) 4 | 5 | 6 | [GPRS Shield V3.0](https://www.seeedstudio.com/GPRS-Shield-V3.0-p-2333.html) 7 | 8 | GPRS Shield provide you a way to DIY your own **mobile phone**. You can use your GRPS Shield to dial a phone number or send a text message to your friend. Besides these, you can use it to access the network and view web pages. For more information, you can visit our [Wiki Page](http://wiki.seeedstudio.com/GPRS_Shield_V3.0/) 9 | ### Features 10 | + Compatible with standard Arduino and Arduino Mega 11 | + Selectable interface between hardware serial port and software serial port 12 | + Selectable interface between hardware serial port and software serial port 13 | + Support TCP/UDP protocols 14 | + Full control via AT commands set: Standard - GSM 07.07 & 07.05 and Enhanced - SIMCOM AT Commands 15 | + 2-in-1 headset jack 16 | + Convenient external SIM card holder 17 | + Low power consumption: 1.5mA(sleep mode) 18 | + 3V CR1220 Battery Holder Connetor 19 | 20 | ### Applications 21 | + Call up and answer Call 22 | + Send SMS and read SMS 23 | + AT Command Test 24 | + TCP Connection Test 25 | 26 | ### Getting Started 27 | Make sure that three libraries ([GPRS_Shield_Suli](https://github.com/Seeed-Studio/GPRS_Shield_Suli) —— GPRS Module Library, [SoftwareSerial](https://github.com/arduino/Arduino/tree/master/libraries/SoftwareSerial) —— we use software serial to communicate with GPRS module, [Suli_Arduino](https://github.com/Seeed-Studio/Suli)—— the Seeed Unified Libray interface) have been in your libraries folder. Then you can have a test with the sketches in example folder. 28 | + GPRS_Serial_Debug —— test GPRS module with AT commands. 29 | + GPRS_CallUp —— give a call to someone. 30 | + GPRS_SendSMS —— send a message to someone. 31 | + GPRS_LoopHandle —— answer the call & read the message. 32 | + GPRS_TCPConnection —— build a TCP connection and read the content from the specified website. 33 | 34 | 35 | ---- 36 | 37 | This software is written by lawliet zou (![](http://www.seeedstudio.com/wiki/images/f/f8/Email-lawliet.zou.jpg)) for [Seeed Technology Inc.](http://www.seeed.cc) and is licensed under [The MIT License](http://opensource.org/licenses/mit-license.php). Check License.txt/LICENSE for the details of MIT license.
38 | 39 | Contributing to this software is warmly welcomed. You can do this basically by
40 | [forking](https://help.github.com/articles/fork-a-repo), committing modifications and then [pulling requests](https://help.github.com/articles/using-pull-requests) (follow the links above
41 | for operating guide). Adding change log and your contact into file header is encouraged.
42 | Thanks for your contribution. 43 | 44 | Seeed is a hardware innovation platform for makers to grow inspirations into differentiating products. By working closely with technology providers of all scale, Seeed provides accessible technologies with quality, speed and supply chain knowledge. When prototypes are ready to iterate, Seeed helps productize 1 to 1,000 pcs using in-house engineering, supply chain management and agile manufacture forces. Seeed also team up with incubators, Chinese tech ecosystem, investors and distribution channels to portal Maker startups beyond. 45 | 46 | 47 | 48 | [![Analytics](https://ga-beacon.appspot.com/UA-46589105-3/GPRS_Shield_Suli)](https://github.com/igrigorik/ga-beacon) 49 | 50 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Eclipse 3 | ################# 4 | 5 | *.pydevproject 6 | .project 7 | .metadata 8 | bin/ 9 | tmp/ 10 | *.tmp 11 | *.bak 12 | *.swp 13 | *~.nib 14 | local.properties 15 | .classpath 16 | .settings/ 17 | .loadpath 18 | 19 | # External tool builders 20 | .externalToolBuilders/ 21 | 22 | # Locally stored "Eclipse launch configurations" 23 | *.launch 24 | 25 | # CDT-specific 26 | .cproject 27 | 28 | # PDT-specific 29 | .buildpath 30 | 31 | 32 | ################# 33 | ## Visual Studio 34 | ################# 35 | 36 | ## Ignore Visual Studio temporary files, build results, and 37 | ## files generated by popular Visual Studio add-ons. 38 | 39 | # User-specific files 40 | *.suo 41 | *.user 42 | *.sln.docstates 43 | 44 | # Build results 45 | 46 | [Dd]ebug/ 47 | [Rr]elease/ 48 | x64/ 49 | build/ 50 | [Bb]in/ 51 | [Oo]bj/ 52 | 53 | # MSTest test Results 54 | [Tt]est[Rr]esult*/ 55 | [Bb]uild[Ll]og.* 56 | 57 | *_i.c 58 | *_p.c 59 | *.ilk 60 | *.meta 61 | *.obj 62 | *.pch 63 | *.pdb 64 | *.pgc 65 | *.pgd 66 | *.rsp 67 | *.sbr 68 | *.tlb 69 | *.tli 70 | *.tlh 71 | *.tmp 72 | *.tmp_proj 73 | *.log 74 | *.vspscc 75 | *.vssscc 76 | .builds 77 | *.pidb 78 | *.log 79 | *.scc 80 | 81 | # Visual C++ cache files 82 | ipch/ 83 | *.aps 84 | *.ncb 85 | *.opensdf 86 | *.sdf 87 | *.cachefile 88 | 89 | # Visual Studio profiler 90 | *.psess 91 | *.vsp 92 | *.vspx 93 | 94 | # Guidance Automation Toolkit 95 | *.gpState 96 | 97 | # ReSharper is a .NET coding add-in 98 | _ReSharper*/ 99 | *.[Rr]e[Ss]harper 100 | 101 | # TeamCity is a build add-in 102 | _TeamCity* 103 | 104 | # DotCover is a Code Coverage Tool 105 | *.dotCover 106 | 107 | # NCrunch 108 | *.ncrunch* 109 | .*crunch*.local.xml 110 | 111 | # Installshield output folder 112 | [Ee]xpress/ 113 | 114 | # DocProject is a documentation generator add-in 115 | DocProject/buildhelp/ 116 | DocProject/Help/*.HxT 117 | DocProject/Help/*.HxC 118 | DocProject/Help/*.hhc 119 | DocProject/Help/*.hhk 120 | DocProject/Help/*.hhp 121 | DocProject/Help/Html2 122 | DocProject/Help/html 123 | 124 | # Click-Once directory 125 | publish/ 126 | 127 | # Publish Web Output 128 | *.Publish.xml 129 | *.pubxml 130 | 131 | # NuGet Packages Directory 132 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line 133 | #packages/ 134 | 135 | # Windows Azure Build Output 136 | csx 137 | *.build.csdef 138 | 139 | # Windows Store app package directory 140 | AppPackages/ 141 | 142 | # Others 143 | sql/ 144 | *.Cache 145 | ClientBin/ 146 | [Ss]tyle[Cc]op.* 147 | ~$* 148 | *~ 149 | *.dbmdl 150 | *.[Pp]ublish.xml 151 | *.pfx 152 | *.publishsettings 153 | 154 | # RIA/Silverlight projects 155 | Generated_Code/ 156 | 157 | # Backup & report files from converting an old project file to a newer 158 | # Visual Studio version. Backup files are not needed, because we have git ;-) 159 | _UpgradeReport_Files/ 160 | Backup*/ 161 | UpgradeLog*.XML 162 | UpgradeLog*.htm 163 | 164 | # SQL Server files 165 | App_Data/*.mdf 166 | App_Data/*.ldf 167 | 168 | ############# 169 | ## Windows detritus 170 | ############# 171 | 172 | # Windows image file caches 173 | Thumbs.db 174 | ehthumbs.db 175 | 176 | # Folder config file 177 | Desktop.ini 178 | 179 | # Recycle Bin used on file shares 180 | $RECYCLE.BIN/ 181 | 182 | # Mac crap 183 | .DS_Store 184 | 185 | 186 | ############# 187 | ## Python 188 | ############# 189 | 190 | *.py[co] 191 | 192 | # Packages 193 | *.egg 194 | *.egg-info 195 | dist/ 196 | build/ 197 | eggs/ 198 | parts/ 199 | var/ 200 | sdist/ 201 | develop-eggs/ 202 | .installed.cfg 203 | 204 | # Installer logs 205 | pip-log.txt 206 | 207 | # Unit test / coverage reports 208 | .coverage 209 | .tox 210 | 211 | #Translations 212 | *.mo 213 | 214 | #Mr Developer 215 | .mr.developer.cfg 216 | -------------------------------------------------------------------------------- /sim900_Suli.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | sim900_Suli.cpp 3 | A library for SeeedStudio seeeduino GPRS shield 4 | 5 | Copyright (c) 2014 seeed technology inc. 6 | Website : www.seeed.cc 7 | Author : lawliet zou 8 | Create Time: April 2015 9 | Change Log : 10 | 11 | The MIT License (MIT) 12 | 13 | Permission is hereby granted, free of charge, to any person obtaining a copy 14 | of this software and associated documentation files (the "Software"), to deal 15 | in the Software without restriction, including without limitation the rights 16 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 | copies of the Software, and to permit persons to whom the Software is 18 | furnished to do so, subject to the following conditions: 19 | 20 | The above copyright notice and this permission notice shall be included in 21 | all copies or substantial portions of the Software. 22 | 23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 29 | THE SOFTWARE. 30 | */ 31 | 32 | #include "sim900_Suli.h" 33 | 34 | SoftwareSerial* serialSIM900 = NULL; 35 | 36 | void sim900_init(void* uart_device, int16 uart_num, uint32 baud) { 37 | serialSIM900 = (SoftwareSerial*)uart_device; 38 | suli_uart_init(uart_device, uart_num, baud); 39 | } 40 | 41 | char sim900_read_byte(void) { 42 | return suli_uart_read_byte(serialSIM900, -1); 43 | } 44 | 45 | int sim900_check_readable() { 46 | return suli_uart_readable(serialSIM900, -1); 47 | } 48 | 49 | int sim900_wait_readable(int wait_time) { 50 | unsigned long timerStart; //,timerEnd; 51 | int dataLen = 0; 52 | timerStart = suli_millis(); 53 | //timerEnd = 1000*wait_time + timerStart; 54 | while ((unsigned long)(suli_millis() - timerStart) < wait_time * 1000UL) { 55 | suli_delay_ms(500); 56 | dataLen = suli_uart_readable(serialSIM900, -1); 57 | if (dataLen > 0) { 58 | break; 59 | } 60 | } 61 | return dataLen; 62 | } 63 | 64 | void sim900_flush_serial() { 65 | while (suli_uart_readable(serialSIM900, -1)) { 66 | char c = suli_uart_read_byte(serialSIM900, -1); 67 | } 68 | } 69 | 70 | int sim900_read_buffer(char* buffer, int count, unsigned int timeout, unsigned int chartimeout) { 71 | int i = 0; 72 | unsigned long timerStart, prevChar; //,timerEnd; 73 | timerStart = suli_millis(); 74 | prevChar = 0; 75 | //timerEnd = 1000*timeOut + timerStart; 76 | while (1) { 77 | #if false 78 | //23/03/2015 WHY CAN YOU USE THIS IF IN sim900_wait_for_resp ARE YOU USING IT ? 79 | while (suli_uart_readable(serialSIM900, -1)) { 80 | char c = suli_uart_read_byte(serialSIM900, -1); 81 | prevChar = suli_millis(); 82 | buffer[i++] = c; 83 | if (i >= count) { 84 | break; 85 | } 86 | } 87 | if (i >= count) { 88 | break; 89 | } 90 | //if(millis() > timerEnd) { 91 | // break; 92 | //} 93 | if ((unsigned long)(suli_millis() - timerStart) > timeout * 1000UL) { 94 | break; 95 | } 96 | //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) 97 | if (((unsigned long)(suli_millis() - prevChar) > chartimeout) && (prevChar != 0)) { 98 | break; 99 | } 100 | #else 101 | /** Anyway, Suli is not quickly enough to fetch data from buffer, so 102 | we have to fetch our data like this.*/ 103 | //23/03/2015 WHY THIS IF IN sim900_wait_for_resp ARE YOU USING IT ? 104 | while (serialSIM900->available()) { 105 | char c = serialSIM900->read(); 106 | prevChar = suli_millis(); 107 | buffer[i++] = c; 108 | if (i >= count) { 109 | break; 110 | } 111 | } 112 | if (i >= count) { 113 | break; 114 | } 115 | //if(millis() > timerEnd) { 116 | // break; 117 | //} 118 | if ((unsigned long)(suli_millis() - timerStart) > timeout * 1000UL) { 119 | break; 120 | } 121 | //If interchar Timeout => return FALSE. So we can return sooner from this function. 122 | if (((unsigned long)(suli_millis() - prevChar) > chartimeout) && (prevChar != 0)) { 123 | break; 124 | } 125 | #endif 126 | } 127 | return 0; 128 | } 129 | 130 | 131 | 132 | void sim900_clean_buffer(char* buffer, int count) { 133 | for (int i = 0; i < count; i++) { 134 | buffer[i] = '\0'; 135 | } 136 | } 137 | 138 | void sim900_send_cmd(const char* cmd) { 139 | suli_uart_send(serialSIM900, -1, (uint8_t*)cmd, strlen(cmd)); 140 | } 141 | 142 | void sim900_send_cmd(const __FlashStringHelper* cmd) { 143 | int i = 0; 144 | const char* ptr = (const char*) cmd; 145 | while (pgm_read_byte(ptr + i) != 0x00) { 146 | suli_uart_send_byte(serialSIM900, -1, pgm_read_byte(ptr + i++)); 147 | } 148 | } 149 | 150 | void sim900_send_cmd_P(const char* cmd) { 151 | while (pgm_read_byte(cmd) != 0x00) { 152 | suli_uart_send_byte(serialSIM900, -1, pgm_read_byte(cmd++)); 153 | } 154 | } 155 | 156 | void sim900_send_char(const char c) { 157 | suli_uart_send_byte(serialSIM900, -1, c); 158 | } 159 | 160 | void sim900_send_AT(void) { 161 | sim900_check_with_cmd("AT\r\n", "OK", CMD); 162 | } 163 | 164 | /* NOT USED 165 | bool sim900_response_cmp(uint8_t* resp, unsigned int len, unsigned int timeout) 166 | { 167 | int sum=0; 168 | unsigned long timerStart,timerEnd; 169 | timerStart = suli_millis(); 170 | timerEnd = 1000*timeout + timerStart; 171 | while(1) { 172 | if(suli_uart_readable(serialSIM900,-1)) { 173 | char c = suli_uart_read_byte(serialSIM900,-1); 174 | sum = (c==resp[sum]) ? sum+1 : 0; 175 | if(sum == len)break; 176 | } 177 | if(suli_millis() > timerEnd) { 178 | return false; 179 | } 180 | } 181 | return true; 182 | } 183 | */ 184 | 185 | int sim900_wait_for_resp(const char* resp, DataType type, unsigned int timeout, unsigned int chartimeout) { 186 | int len = strlen(resp); 187 | int sum = 0; 188 | //unsigned long timerStart,timerEnd, prevChar; //prevChar is the time when the previous Char has been read. 189 | unsigned long timerStart, prevChar; //prevChar is the time when the previous Char has been read. 190 | timerStart = suli_millis(); 191 | prevChar = 0; 192 | // timerEnd = 1000*timeout + timerStart; 193 | while (1) { 194 | if (suli_uart_readable(serialSIM900, -1)) { 195 | char c = suli_uart_read_byte(serialSIM900, -1); 196 | prevChar = suli_millis(); 197 | sum = (c == resp[sum]) ? sum + 1 : 0; 198 | if (sum == len) { 199 | break; 200 | } 201 | } 202 | if ((unsigned long)(suli_millis() - timerStart) > timeout * 1000UL) { 203 | //if(suli_millis() > timerEnd) { 204 | return -1; 205 | } 206 | //If interchar Timeout => return FALSE. So we can return sooner from this function. 207 | if (((unsigned long)(suli_millis() - prevChar) > chartimeout) && (prevChar != 0)) { 208 | return -2; 209 | } 210 | 211 | } 212 | //If is a CMD, we will finish to read buffer. 213 | if (type == CMD) { 214 | sim900_flush_serial(); 215 | } 216 | return 0; 217 | } 218 | 219 | void sim900_send_End_Mark(void) { 220 | suli_uart_send_byte(serialSIM900, -1, (char)26); 221 | } 222 | 223 | int sim900_check_with_cmd(const char* cmd, const char* resp, DataType type, unsigned int timeout, 224 | unsigned int chartimeout) { 225 | sim900_send_cmd(cmd); 226 | return sim900_wait_for_resp(resp, type, timeout, chartimeout); 227 | } 228 | 229 | //FUTURE esto vale para algo en cadenas de texto tan cortas ??? 230 | /* int sim900_check_with_cmd(const __FlashStringHelper* cmd, const char *resp, unsigned timeout, DataType type) 231 | { 232 | sim900_send_cmd(cmd); 233 | return sim900_wait_for_resp(resp,timeout,type); 234 | }*/ 235 | 236 | -------------------------------------------------------------------------------- /GPRS_Shield_Arduino.h: -------------------------------------------------------------------------------- 1 | /* 2 | GPRS_Shield_Arduino.h 3 | A library for SeeedStudio seeeduino GPRS shield 4 | 5 | Copyright (c) 2014 seeed technology inc. 6 | Website : www.seeed.cc 7 | Author : lawliet zou 8 | Create Time: April 2015 9 | Change Log : 10 | 11 | The MIT License (MIT) 12 | 13 | Permission is hereby granted, free of charge, to any person obtaining a copy 14 | of this software and associated documentation files (the "Software"), to deal 15 | in the Software without restriction, including without limitation the rights 16 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 | copies of the Software, and to permit persons to whom the Software is 18 | furnished to do so, subject to the following conditions: 19 | 20 | The above copyright notice and this permission notice shall be included in 21 | all copies or substantial portions of the Software. 22 | 23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 29 | THE SOFTWARE. 30 | */ 31 | 32 | #ifndef __GPRS_SHIELD_ARDUINO_H__ 33 | #define __GPRS_SHIELD_ARDUINO_H__ 34 | 35 | #include "sim900_Suli.h" 36 | 37 | /** GPRS class. 38 | used to realize GPRS communication 39 | */ 40 | 41 | //NOT USED #define MESSAGE_LENGTH 20 42 | 43 | enum Protocol { 44 | CLOSED = 0, 45 | TCP = 1, 46 | UDP = 2, 47 | }; 48 | 49 | class GPRS { 50 | public: 51 | /** Create GPRS instance 52 | @param number default phone number during mobile communication 53 | */ 54 | 55 | // GPRS(int tx, int rx, uint32_t baudRate = 9600, const char* apn = NULL, const char* userName = NULL, const char *passWord = NULL); 56 | GPRS(int tx, int rx, uint32_t baudRate = 9600); 57 | 58 | /** get instance of GPRS class 59 | */ 60 | static GPRS* getInstance() { 61 | return inst; 62 | }; 63 | 64 | /** initialize GPRS module including SIM card check & signal strength 65 | @return true if connected, false otherwise 66 | */ 67 | 68 | int init(void); 69 | 70 | 71 | /** check if GPRS module is powered on or not 72 | @returns 73 | 0 on success 74 | -1 on error 75 | */ 76 | int checkPowerUp(void); 77 | 78 | 79 | /** power Up GPRS module (JP has to be soldered) 80 | @param pin pin 9 connected to JP jumper so we can power up and down through software 81 | @returns 82 | 83 | */ 84 | void powerUpDown(byte pin); 85 | 86 | /** send text SMS 87 | @param *number phone number which SMS will be send to 88 | @param *data message that will be send to 89 | @returns 90 | 0 on success 91 | -1 on error 92 | */ 93 | int sendSMS(char* number, char* data); 94 | 95 | /** Check if there is any UNREAD SMS: this function DOESN'T change the UNREAD status of the SMS 96 | @returns 97 | 1..20 on success, position/index where SMS is stored, suitable for the function ReadSMS 98 | -1 on error 99 | 0 - there is no SMS with specified status (UNREAD) 100 | */ 101 | 102 | char isSMSunread(); 103 | 104 | /** read SMS, phone and date if getting a SMS message. It changes SMS status to READ 105 | @param messageIndex SIM position to read 106 | @param message buffer used to get SMS message 107 | @param length length of message buffer 108 | @param phone buffer used to get SMS's sender phone number 109 | @param datetime buffer used to get SMS's send datetime 110 | @returns 111 | 0 on success 112 | -1 on error 113 | */ 114 | int readSMS(int messageIndex, char* message, int length, char* phone, char* datetime); 115 | 116 | /** read SMS if getting a SMS message 117 | @param buffer buffer that get from GPRS module(when getting a SMS, GPRS module will return a buffer array) 118 | @param message buffer used to get SMS message 119 | @param check whether to check phone number(we may only want to read SMS from specified phone number) 120 | @returns 121 | 0 on success 122 | -1 on error 123 | */ 124 | int readSMS(int messageIndex, char* message, int length); 125 | 126 | /** delete SMS message on SIM card 127 | @param index the index number which SMS message will be delete 128 | @returns 129 | 0 on success 130 | -1 on error 131 | */ 132 | int deleteSMS(int index); 133 | 134 | /** call someone 135 | @param number the phone number which you want to call 136 | @returns 137 | 0 on success 138 | -1 on error 139 | */ 140 | int callUp(char* number); 141 | 142 | /** Disable +CLIP notification when an incoming call is active, RING text is always shown. See isCallActive function 143 | This is done in order no to overload serial outputCheck if there is a call active and get the phone number in that case 144 | @returns 145 | 0 on success 146 | -1 on error 147 | */ 148 | int disableCLIPring(void); 149 | 150 | /** Check if there is a call active and get the phone number in that case 151 | @returns 152 | 0 on success 153 | -1 on error 154 | */ 155 | int isCallActive(char* number); 156 | 157 | /** auto answer if coming a call 158 | @returns 159 | 0 on success 160 | -1 on error 161 | */ 162 | 163 | int answer(void); 164 | 165 | /** hang up if coming a call 166 | @returns 167 | 0 on success 168 | -1 on error 169 | */ 170 | int hangup(void); 171 | 172 | /** get DateTime from SIM900 (see AT command: AT+CLTS=1) as string 173 | @param 174 | @returns 175 | 0 on success 176 | -1 on error 177 | */ 178 | int getDateTime(char* buffer); 179 | 180 | 181 | ////////////////////////////////////////////////////// 182 | /// GPRS 183 | ////////////////////////////////////////////////////// 184 | /** Connect the GPRS module to the network. 185 | @return true if connected, false otherwise 186 | */ 187 | 188 | bool join(const __FlashStringHelper* apn = 0, const __FlashStringHelper* userName = 0, 189 | const __FlashStringHelper* passWord = 0); 190 | 191 | 192 | /** Disconnect the GPRS module from the network 193 | @returns true if successful 194 | */ 195 | bool disconnect(void); 196 | 197 | /** Close a tcp connection 198 | @returns true if successful 199 | */ 200 | bool close(void); 201 | 202 | /** Open a tcp/udp connection with the specified host on the specified port 203 | @param socket an endpoint of an inter-process communication flow of GPRS module,for SIM900 module, it is in [0,6] 204 | @param ptl protocol for socket, TCP/UDP can be choosen 205 | @param host host (can be either an ip address or a name. If a name is provided, a dns request will be established) 206 | @param port port 207 | @param timeout wait seconds till connected 208 | @returns true if successful 209 | */ 210 | bool connect(Protocol ptl, const char* host, int port, int timeout = 2 * DEFAULT_TIMEOUT); 211 | bool connect(Protocol ptl, const __FlashStringHelper* host, const __FlashStringHelper* port, 212 | int timeout = 2 * DEFAULT_TIMEOUT); 213 | 214 | 215 | /** Reset the GPRS module 216 | */ 217 | void reset(); 218 | 219 | /** check if GPRS module is readable or not 220 | @returns true if readable 221 | */ 222 | int readable(void); 223 | 224 | /** wait a few time to check if GPRS module is readable or not 225 | @param socket socket 226 | @param wait_time time of waiting 227 | */ 228 | int wait_readable(int wait_time); 229 | 230 | /** wait a few time to check if GPRS module is writeable or not 231 | @param socket socket 232 | @param wait_time time of waiting 233 | */ 234 | int wait_writeable(int req_size); 235 | 236 | /** Check if a tcp link is active 237 | @returns true if successful 238 | */ 239 | bool is_connected(void); 240 | 241 | /** send data to socket 242 | @param socket socket 243 | @param str string to be sent 244 | @param len string length 245 | @returns return bytes that actually been send 246 | */ 247 | int send(const char* str, int len); 248 | 249 | /** read data from socket 250 | @param socket socket 251 | @param buf buffer that will store the data read from socket 252 | @param len string length need to read from socket 253 | @returns bytes that actually read 254 | */ 255 | int recv(char* buf, int len); 256 | 257 | /** convert the host to ip 258 | @param host host ip string, ex. 10.11.12.13 259 | @param ip long int ip address, ex. 0x11223344 260 | @returns true if successful 261 | */ 262 | bool gethostbyname(const char* host, uint32_t* ip); 263 | 264 | char* getIPAddress(); 265 | 266 | private: 267 | int checkSIMStatus(void); 268 | uint32_t str_to_ip(const char* str); 269 | SoftwareSerial gprsSerial; 270 | static GPRS* inst; 271 | PIN_T _powerPin; 272 | //Why GLOBAL variables? If we put them in JOIN function, is it not necessary 273 | //const char* _apn; 274 | //const char* _userName; 275 | //const char* _passWord; 276 | uint32_t _ip; 277 | char ip_string[20]; 278 | }; 279 | #endif 280 | -------------------------------------------------------------------------------- /GPRS_Shield_Arduino.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | GPRS_Shield_Arduino.cpp 3 | A library for SeeedStudio seeeduino GPRS shield 4 | 5 | Copyright (c) 2014 seeed technology inc. 6 | Website : www.seeed.cc 7 | Author : lawliet zou 8 | Create Time: April 2015 9 | Change Log : 10 | 11 | The MIT License (MIT) 12 | 13 | Permission is hereby granted, free of charge, to any person obtaining a copy 14 | of this software and associated documentation files (the "Software"), to deal 15 | in the Software without restriction, including without limitation the rights 16 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 | copies of the Software, and to permit persons to whom the Software is 18 | furnished to do so, subject to the following conditions: 19 | 20 | The above copyright notice and this permission notice shall be included in 21 | all copies or substantial portions of the Software. 22 | 23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 29 | THE SOFTWARE. 30 | */ 31 | 32 | #include 33 | #include "GPRS_Shield_Arduino.h" 34 | #include 35 | 36 | GPRS* GPRS::inst; 37 | 38 | /* 39 | GPRS::GPRS(PIN_T tx, PIN_T rx, uint32_t baudRate, const char* apn, const char* userName, const char* passWord):gprsSerial(tx,rx) 40 | { 41 | inst = this; 42 | _apn = apn; 43 | _userName = userName; 44 | _passWord = passWord; 45 | sim900_init(&gprsSerial, -1, baudRate); 46 | } 47 | */ 48 | 49 | GPRS::GPRS(PIN_T tx, PIN_T rx, uint32_t baudRate): gprsSerial(tx, rx) { 50 | inst = this; 51 | sim900_init(&gprsSerial, -1, baudRate); 52 | } 53 | 54 | int GPRS::init(void) { 55 | if (0 != sim900_check_with_cmd("AT\r\n", "OK\r\n", CMD)) { 56 | return false; 57 | 58 | } 59 | 60 | if (0 != sim900_check_with_cmd("AT+CFUN=1\r\n", "OK\r\n", CMD)) { 61 | return false; 62 | 63 | } 64 | 65 | if (0 != checkSIMStatus()) { 66 | return false; 67 | 68 | } 69 | 70 | return true; 71 | } 72 | 73 | int GPRS::checkPowerUp(void) { 74 | return sim900_check_with_cmd("AT\r\n", "OK\r\n", CMD); 75 | } 76 | 77 | void GPRS::powerUpDown(byte pin) { 78 | // power on pulse 79 | digitalWrite(pin, LOW); 80 | delay(1000); 81 | digitalWrite(pin, HIGH); 82 | delay(2000); 83 | digitalWrite(pin, LOW); 84 | delay(3000); 85 | } 86 | 87 | 88 | int GPRS::checkSIMStatus(void) { 89 | char gprsBuffer[32]; 90 | int count = 0; 91 | sim900_clean_buffer(gprsBuffer, 32); 92 | while (count < 3) { 93 | sim900_send_cmd("AT+CPIN?\r\n"); 94 | sim900_read_buffer(gprsBuffer, 32, DEFAULT_TIMEOUT); 95 | if ((NULL != strstr(gprsBuffer, "+CPIN: READY"))) { 96 | break; 97 | } 98 | count++; 99 | suli_delay_ms(300); 100 | } 101 | if (count == 3) { 102 | return -1; 103 | } 104 | return 0; 105 | } 106 | 107 | 108 | 109 | int GPRS::sendSMS(char* number, char* data) { 110 | char cmd[32]; 111 | if (0 != sim900_check_with_cmd("AT+CMGF=1\r\n", "OK\r\n", CMD)) { // Set message mode to ASCII 112 | return -1; 113 | } 114 | suli_delay_ms(500); 115 | snprintf(cmd, sizeof(cmd), "AT+CMGS=\"%s\"\r\n", number); 116 | if (0 != sim900_check_with_cmd(cmd, ">", CMD)) { 117 | return -1; 118 | } 119 | suli_delay_ms(1000); 120 | sim900_send_cmd(data); 121 | suli_delay_ms(500); 122 | sim900_send_End_Mark(); 123 | return 0; 124 | } 125 | 126 | char GPRS::isSMSunread() { 127 | char gprsBuffer[48]; //48 is enough to see +CMGL: 128 | char* s; 129 | 130 | 131 | //List of all UNREAD SMS and DON'T change the SMS UNREAD STATUS 132 | sim900_send_cmd(F("AT+CMGL=\"REC UNREAD\",1\r\n")); 133 | /* If you want to change SMS status to READ you will need to send: 134 | AT+CMGL=\"REC UNREAD\"\r\n 135 | This command will list all UNREAD SMS and change all of them to READ 136 | 137 | If there is not SMS, response is (30 chars) 138 | AT+CMGL="REC UNREAD",1 --> 22 + 2 139 | --> 2 140 | OK --> 2 + 2 141 | 142 | If there is SMS, response is like (>64 chars) 143 | AT+CMGL="REC UNREAD",1 144 | +CMGL: 9,"REC UNREAD","XXXXXXXXX","","14/10/16,21:40:08+08" 145 | Here SMS text. 146 | OK 147 | 148 | or 149 | 150 | AT+CMGL="REC UNREAD",1 151 | +CMGL: 9,"REC UNREAD","XXXXXXXXX","","14/10/16,21:40:08+08" 152 | Here SMS text. 153 | +CMGL: 10,"REC UNREAD","YYYYYYYYY","","14/10/16,21:40:08+08" 154 | Here second SMS 155 | OK 156 | */ 157 | 158 | sim900_clean_buffer(gprsBuffer, 31); 159 | sim900_read_buffer(gprsBuffer, 30, DEFAULT_TIMEOUT); 160 | //Serial.print("Buffer isSMSunread: ");Serial.println(gprsBuffer); 161 | 162 | if (NULL != (s = strstr(gprsBuffer, "OK"))) { 163 | //In 30 bytes "doesn't" fit whole +CMGL: response, if recieve only "OK" 164 | // means you don't have any UNREAD SMS 165 | delay(50); 166 | return 0; 167 | } else { 168 | //More buffer to read 169 | //We are going to flush serial data until OK is recieved 170 | sim900_wait_for_resp("OK\r\n", CMD); 171 | //sim900_flush_serial(); 172 | //We have to call command again 173 | sim900_send_cmd("AT+CMGL=\"REC UNREAD\",1\r\n"); 174 | sim900_clean_buffer(gprsBuffer, 48); 175 | sim900_read_buffer(gprsBuffer, 47, DEFAULT_TIMEOUT); 176 | //Serial.print("Buffer isSMSunread 2: ");Serial.println(gprsBuffer); 177 | if (NULL != (s = strstr(gprsBuffer, "+CMGL:"))) { 178 | //There is at least one UNREAD SMS, get index/position 179 | s = strstr(gprsBuffer, ":"); 180 | if (s != NULL) { 181 | //We are going to flush serial data until OK is recieved 182 | sim900_wait_for_resp("OK\r\n", CMD); 183 | return atoi(s + 1); 184 | } 185 | } else { 186 | return -1; 187 | 188 | } 189 | } 190 | return -1; 191 | } 192 | 193 | int GPRS::readSMS(int messageIndex, char* message, int length, char* phone, char* datetime) { 194 | /* Response is like: 195 | AT+CMGR=2 196 | 197 | +CMGR: "REC READ","XXXXXXXXXXX","","14/10/09,17:30:17+08" 198 | SMS text here 199 | 200 | So we need (more or lees), 80 chars plus expected message length in buffer. CAUTION FREE MEMORY 201 | */ 202 | 203 | int i = 0; 204 | char gprsBuffer[80 + length]; 205 | char cmd[16]; 206 | char* p, *p2, *s; 207 | 208 | sim900_check_with_cmd("AT+CMGF=1\r\n", "OK\r\n", CMD); 209 | suli_delay_ms(1000); 210 | sprintf(cmd, "AT+CMGR=%d\r\n", messageIndex); 211 | sim900_send_cmd(cmd); 212 | sim900_clean_buffer(gprsBuffer, sizeof(gprsBuffer)); 213 | sim900_read_buffer(gprsBuffer, sizeof(gprsBuffer), DEFAULT_TIMEOUT); 214 | 215 | if (NULL != (s = strstr(gprsBuffer, "+CMGR:"))) { 216 | // Extract phone number string 217 | p = strstr(s, ","); 218 | p2 = p + 2; //We are in the first phone number character 219 | p = strstr((char*)(p2), "\""); 220 | if (NULL != p) { 221 | i = 0; 222 | while (p2 < p) { 223 | phone[i++] = *(p2++); 224 | } 225 | phone[i] = '\0'; 226 | } 227 | // Extract date time string 228 | p = strstr((char*)(p2), ","); 229 | p2 = p + 1; 230 | p = strstr((char*)(p2), ","); 231 | p2 = p + 2; //We are in the first date time character 232 | p = strstr((char*)(p2), "\""); 233 | if (NULL != p) { 234 | i = 0; 235 | while (p2 < p) { 236 | datetime[i++] = *(p2++); 237 | } 238 | datetime[i] = '\0'; 239 | } 240 | if (NULL != (s = strstr(s, "\r\n"))) { 241 | i = 0; 242 | p = s + 2; 243 | while ((*p != '\r') && (i < length - 1)) { 244 | message[i++] = *(p++); 245 | } 246 | message[i] = '\0'; 247 | } 248 | return 0; 249 | } 250 | return -1; 251 | } 252 | 253 | int GPRS::readSMS(int messageIndex, char* message, int length) { 254 | int i = 0; 255 | char gprsBuffer[100]; 256 | char cmd[16]; 257 | char* p, *s; 258 | 259 | sim900_check_with_cmd("AT+CMGF=1\r\n", "OK\r\n", CMD); 260 | suli_delay_ms(1000); 261 | sprintf(cmd, "AT+CMGR=%d\r\n", messageIndex); 262 | sim900_send_cmd(cmd); 263 | sim900_clean_buffer(gprsBuffer, sizeof(gprsBuffer)); 264 | sim900_read_buffer(gprsBuffer, sizeof(gprsBuffer), DEFAULT_TIMEOUT); 265 | if (NULL != (s = strstr(gprsBuffer, "+CMGR:"))) { 266 | if (NULL != (s = strstr(s, "\r\n"))) { 267 | p = s + 2; 268 | while ((*p != '\r') && (i < length - 1)) { 269 | message[i++] = *(p++); 270 | } 271 | message[i] = '\0'; 272 | return 0; 273 | } 274 | } 275 | return -1; 276 | } 277 | 278 | int GPRS::deleteSMS(int index) { 279 | char cmd[16]; 280 | snprintf(cmd, sizeof(cmd), "AT+CMGD=%d\r\n", index); 281 | //sim900_send_cmd(cmd); 282 | //return 0; 283 | // We have to wait OK response 284 | if (0 != sim900_check_with_cmd(cmd, "OK\r\n", CMD)) { 285 | return -1; 286 | } 287 | return 0; 288 | } 289 | 290 | int GPRS::callUp(char* number) { 291 | char cmd[24]; 292 | if (0 != sim900_check_with_cmd("AT+COLP=1\r\n", "OK\r\n", CMD)) { 293 | return -1; 294 | } 295 | suli_delay_ms(1000); 296 | sprintf(cmd, "ATD%s;\r\n", number); 297 | sim900_send_cmd(cmd); 298 | return 0; 299 | } 300 | 301 | int GPRS::answer(void) { 302 | sim900_send_cmd("ATA\r\n"); //TO CHECK: ATA doesnt return "OK" ???? 303 | return 0; 304 | } 305 | 306 | int GPRS::hangup(void) { 307 | return sim900_check_with_cmd("ATH\r\n", "OK\r\n", CMD); 308 | } 309 | 310 | int GPRS::disableCLIPring(void) { 311 | return sim900_check_with_cmd("AT+CLIP=0\r\n", "OK\r\n", CMD); 312 | } 313 | 314 | int GPRS::isCallActive(char* number) { 315 | char gprsBuffer[46]; //46 is enough to see +CPAS: and CLCC: 316 | char* p, *s; 317 | int i = 0; 318 | 319 | sim900_send_cmd("AT+CPAS\r\n"); 320 | /* Result code: 321 | 0: ready 322 | 2: unknown 323 | 3: ringing 324 | 4: call in progress 325 | 326 | AT+CPAS --> 7 + 2 = 9 chars 327 | --> 2 char 328 | +CPAS: 3 --> 8 + 2 = 10 chars 329 | --> 2 char 330 | OK --> 2 + 2 = 4 chars 331 | 332 | AT+CPAS 333 | 334 | +CPAS: 0 335 | 336 | OK 337 | */ 338 | 339 | sim900_clean_buffer(gprsBuffer, 29); 340 | sim900_read_buffer(gprsBuffer, 27); 341 | //HACERR cuando haga lo de esperar a OK no me haría falta esto 342 | //We are going to flush serial data until OK is recieved 343 | sim900_wait_for_resp("OK", CMD); 344 | //Serial.print("Buffer isCallActive 1: ");Serial.println(gprsBuffer); 345 | if (NULL != (s = strstr(gprsBuffer, "+CPAS:"))) { 346 | s = s + 7; 347 | if (*s != '0') { 348 | //There is something "running" (but number 2 that is unknow) 349 | if (*s != '2') { 350 | //3 or 4, let's go to check for the number 351 | sim900_send_cmd("AT+CLCC\r\n"); 352 | /* 353 | AT+CLCC --> 9 354 | 355 | +CLCC: 1,1,4,0,0,"656783741",161,"" 356 | 357 | OK 358 | 359 | Without ringing: 360 | AT+CLCC 361 | OK 362 | */ 363 | 364 | sim900_clean_buffer(gprsBuffer, 46); 365 | sim900_read_buffer(gprsBuffer, 45); 366 | //Serial.print("Buffer isCallActive 2: ");Serial.println(gprsBuffer); 367 | if (NULL != (s = strstr(gprsBuffer, "+CLCC:"))) { 368 | //There is at least one CALL ACTIVE, get number 369 | s = strstr((char*)(s), "\""); 370 | s = s + 1; //We are in the first phone number character 371 | p = strstr((char*)(s), "\""); //p is last character """ 372 | if (NULL != s) { 373 | i = 0; 374 | while (s < p) { 375 | number[i++] = *(s++); 376 | } 377 | number[i] = '\0'; 378 | } 379 | //I need to read more buffer 380 | //We are going to flush serial data until OK is recieved 381 | sim900_wait_for_resp("OK\r\n", CMD); 382 | return 0; 383 | } 384 | } 385 | } 386 | } 387 | return -1; 388 | } 389 | 390 | int GPRS::getDateTime(char* buffer) { 391 | //AT+CCLK? 392 | //+CCLK: "14/11/13,21:14:41+04" 393 | // 394 | //OK 395 | 396 | int i = 0; 397 | char gprsBuffer[46]; 398 | char* p, *s; 399 | sim900_send_cmd("AT+CCLK?\r\n"); 400 | sim900_clean_buffer(gprsBuffer, 43); 401 | sim900_read_buffer(gprsBuffer, 43, DEFAULT_TIMEOUT); 402 | if (NULL != (s = strstr(gprsBuffer, "+CCLK:"))) { 403 | s = strstr((char*)(s), "\""); 404 | s = s + 1; //We are in the first phone number character 405 | p = strstr((char*)(s), "\""); //p is last character """ 406 | if (NULL != s) { 407 | i = 0; 408 | while (s < p) { 409 | buffer[i++] = *(s++); 410 | } 411 | buffer[i] = '\0'; 412 | } 413 | //We are going to flush serial data until OK is recieved 414 | sim900_wait_for_resp("OK", CMD); 415 | return 0; 416 | } 417 | return -1; 418 | } 419 | 420 | //Here is where we ask for APN configuration, with F() so we can save MEMORY 421 | bool GPRS::join(const __FlashStringHelper* apn, const __FlashStringHelper* userName, 422 | const __FlashStringHelper* passWord) 423 | 424 | { 425 | char cmd[64]; 426 | char ipAddr[32]; 427 | //Select multiple connection 428 | //sim900_check_with_cmd("AT+CIPMUX=1\r\n","OK",DEFAULT_TIMEOUT,CMD); 429 | 430 | //set APN. OLD VERSION 431 | /* snprintf(cmd,sizeof(cmd),"AT+CSTT=\"%s\",\"%s\",\"%s\"\r\n",_apn,_userName,_passWord); 432 | sim900_check_with_cmd(cmd, "OK\r\n", DEFAULT_TIMEOUT,CMD); 433 | */ 434 | sim900_send_cmd("AT+CSTT=\""); 435 | sim900_send_cmd(apn); 436 | sim900_send_cmd("\",\""); 437 | sim900_send_cmd(userName); 438 | sim900_send_cmd("\",\""); 439 | sim900_send_cmd(passWord); 440 | sim900_check_with_cmd("\"\r\n", "OK\r\n", CMD); 441 | 442 | 443 | //Brings up wireless connection 444 | sim900_check_with_cmd("AT+CIICR\r\n", "OK\r\n", CMD); 445 | 446 | //Get local IP address 447 | sim900_send_cmd("AT+CIFSR\r\n"); 448 | sim900_clean_buffer(ipAddr, 32); 449 | sim900_read_buffer(ipAddr, 32, 2); 450 | //Serial.print("ipAddr: "); 451 | //Serial.println(ipAddr); 452 | 453 | if (NULL != strstr(ipAddr, "AT+CIFSR")) { 454 | _ip = str_to_ip(ipAddr + 12); 455 | if (_ip != 0) { 456 | return true; 457 | } 458 | } 459 | return false; 460 | } 461 | 462 | bool GPRS::connect(Protocol ptl, const char* host, int port, int timeout) { 463 | char cmd[64]; 464 | char resp[96]; 465 | 466 | sim900_clean_buffer(cmd, 64); 467 | if (ptl == TCP) { 468 | sprintf(cmd, "AT+CIPSTART=\"TCP\",\"%s\",%d\r\n", host, port); 469 | } else if (ptl == UDP) { 470 | sprintf(cmd, "AT+CIPSTART=\"UDP\",\"%s\",%d\r\n", host, port); 471 | } else { 472 | return false; 473 | } 474 | 475 | //Serial.print("Connect: "); Serial.println(cmd); 476 | sim900_send_cmd(cmd); 477 | sim900_read_buffer(resp, 96, timeout); 478 | //Serial.print("Connect resp: "); Serial.println(resp); 479 | if (NULL != strstr(resp, "CONNECT")) { //ALREADY CONNECT or CONNECT OK 480 | return true; 481 | } 482 | return false; 483 | } 484 | 485 | //Overload with F() macro to SAVE memory 486 | bool GPRS::connect(Protocol ptl, const __FlashStringHelper* host, const __FlashStringHelper* port, int timeout) { 487 | //char cmd[64]; 488 | char resp[96]; 489 | 490 | //sim900_clean_buffer(cmd,64); 491 | if (ptl == TCP) { 492 | sim900_send_cmd(F("AT+CIPSTART=\"TCP\",\"")); //%s\",%d\r\n",host, port); 493 | } else if (ptl == UDP) { 494 | sim900_send_cmd(F("AT+CIPSTART=\"UDP\",\"")); //%s\",%d\r\n",host, port); 495 | } else { 496 | return false; 497 | } 498 | sim900_send_cmd(host); 499 | sim900_send_cmd(F("\",")); 500 | sim900_send_cmd(port); 501 | sim900_send_cmd(F("\r\n")); 502 | //Serial.print("Connect: "); Serial.println(cmd); 503 | sim900_read_buffer(resp, 96, timeout); 504 | //Serial.print("Connect resp: "); Serial.println(resp); 505 | if (NULL != strstr(resp, "CONNECT")) { //ALREADY CONNECT or CONNECT OK 506 | return true; 507 | } 508 | return false; 509 | } 510 | 511 | 512 | bool GPRS::gethostbyname(const char* host, uint32_t* ip) { 513 | uint32_t addr = str_to_ip(host); 514 | char buf[17]; 515 | snprintf(buf, sizeof(buf), "%d.%d.%d.%d", (addr >> 24) & 0xff, (addr >> 16) & 0xff, (addr >> 8) & 0xff, addr & 0xff); 516 | if (strcmp(buf, host) == 0) { 517 | *ip = addr; 518 | return true; 519 | } 520 | return false; 521 | } 522 | 523 | bool GPRS::disconnect() { 524 | sim900_send_cmd("AT+CIPSHUT\r\n"); 525 | return true; 526 | } 527 | 528 | bool GPRS::is_connected(void) { 529 | char resp[96]; 530 | sim900_send_cmd("AT+CIPSTATUS\r\n"); 531 | sim900_read_buffer(resp, sizeof(resp), DEFAULT_TIMEOUT); 532 | if (NULL != strstr(resp, "CONNECTED")) { 533 | //+CIPSTATUS: 1,0,"TCP","216.52.233.120","80","CONNECTED" 534 | return true; 535 | } else { 536 | //+CIPSTATUS: 1,0,"TCP","216.52.233.120","80","CLOSED" 537 | //+CIPSTATUS: 0,,"","","","INITIAL" 538 | return false; 539 | } 540 | } 541 | 542 | bool GPRS::close() { 543 | // if not connected, return 544 | if (is_connected() == false) { 545 | return true; 546 | } 547 | if (0 != sim900_check_with_cmd("AT+CIPCLOSE\r\n", "CLOSE OK\r\n", CMD)) { 548 | return false; 549 | } 550 | return true; 551 | } 552 | 553 | int GPRS::readable(void) { 554 | return sim900_check_readable(); 555 | } 556 | 557 | int GPRS::wait_readable(int wait_time) { 558 | return sim900_wait_readable(wait_time); 559 | } 560 | 561 | int GPRS::wait_writeable(int req_size) { 562 | return req_size + 1; 563 | } 564 | 565 | int GPRS::send(const char* str, int len) { 566 | char cmd[32]; 567 | 568 | //suli_delay_ms(1000); 569 | if (len > 0) { 570 | snprintf(cmd, sizeof(cmd), "AT+CIPSEND=%d\r\n", len); 571 | if (0 != sim900_check_with_cmd(cmd, ">", CMD)) { 572 | return false; 573 | } 574 | /* if(0 != sim900_check_with_cmd(str,"SEND OK\r\n", DEFAULT_TIMEOUT * 10 ,DATA)) { 575 | return false; 576 | }*/ 577 | suli_delay_ms(500); 578 | sim900_send_cmd(str); 579 | suli_delay_ms(500); 580 | sim900_send_End_Mark(); 581 | if (0 != sim900_wait_for_resp("SEND OK\r\n", DATA, DEFAULT_TIMEOUT * 10, DEFAULT_INTERCHAR_TIMEOUT * 10)) { 582 | return false; 583 | } 584 | 585 | } 586 | return len; 587 | } 588 | 589 | 590 | int GPRS::recv(char* buf, int len) { 591 | sim900_clean_buffer(buf, len); 592 | sim900_read_buffer(buf, 593 | len); //Ya he llamado a la funcion con la longitud del buffer - 1 y luego le estoy añadiendo el 0 594 | return strlen(buf); 595 | } 596 | 597 | uint32_t GPRS::str_to_ip(const char* str) { 598 | uint32_t ip = 0; 599 | char* p = (char*)str; 600 | for (int i = 0; i < 4; i++) { 601 | ip |= atoi(p); 602 | p = strchr(p, '.'); 603 | if (p == NULL) { 604 | break; 605 | } 606 | ip <<= 8; 607 | p++; 608 | } 609 | return ip; 610 | } 611 | 612 | char* GPRS::getIPAddress() { 613 | snprintf(ip_string, sizeof(ip_string), "%d.%d.%d.%d", (_ip >> 24) & 0xff, (_ip >> 16) & 0xff, (_ip >> 8) & 0xff, 614 | _ip & 0xff); 615 | return ip_string; 616 | } 617 | 618 | --------------------------------------------------------------------------------