├── LICENSE ├── README.md ├── Sim900.cpp ├── Sim900.h └── examples └── GPRSHTTPPost └── GPRSHTTPPost.ino /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Sim900 2 | ===== 3 | This is an Arduino library for the Sim900 GPRS Shield. 4 | It relies on the 2.8v pin from the Sim900 being plugged into one of 5 | the analog pins so that the library can determine the power state 6 | of the modem. 7 | 8 | To work with the Arduino Mega2560 the software serial pins need to be 9 | remapped to pins that support change detect (PCINT). With some Arduino 10 | jumper leads, map pin 7 to pin 10 and pin 8 to pin 11. 11 | 12 | 13 | Example usage: 14 | ```cxx 15 | /* 16 | Sim900 is an Arduino library for working with the Sim900 GRPS Shield 17 | Copyright (C) 2012 Nigel Bajema 18 | 19 | This program is free software; you can redistribute it and/or 20 | modify it under the terms of the GNU General Public License 21 | as published by the Free Software Foundation; either version 2 22 | of the License, or (at your option) any later version. 23 | 24 | This program is distributed in the hope that it will be useful, 25 | but WITHOUT ANY WARRANTY; without even the implied warranty of 26 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27 | GNU General Public License for more details. 28 | 29 | You should have received a copy of the GNU General Public License 30 | along with this program; if not, write to the Free Software 31 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 32 | */ 33 | 34 | #include 35 | #include 36 | 37 | 38 | CONN settings; 39 | // pins 10, and 11 are serial rx and tx pins for the modem 40 | // pin 9 is the power toggle pin 41 | // analog pin 8 is the GRPS power status pin 42 | Sim900 modem(new SoftwareSerial(10, 11), 19200, 9, 8, VARIANT_2); 43 | char url[] = "www.example.com"; 44 | 45 | void setup() 46 | { 47 | Serial.begin(19200); // the Serial port of Arduino baud rate. 48 | delay(2000); 49 | settings.cid = 1; 50 | settings.contype = "GPRS"; 51 | settings.apn = "internet"; 52 | test_modem(); 53 | 54 | } 55 | 56 | 57 | void loop() 58 | { 59 | } 60 | 61 | void test_modem() 62 | { 63 | int cid = 0, code = 0, error_code = 0; 64 | uint32_t length = 0; 65 | 66 | if(modem.powerUp()) 67 | { 68 | Serial.println("Powered Up") ; 69 | Serial.println("================================================="); 70 | int strength = -1, error_rate = -1; 71 | if(modem.getSignalQuality(strength, error_rate)) 72 | { 73 | Serial.print("Strength: "); 74 | Serial.print(strength); 75 | Serial.print(" Error Rate: "); 76 | Serial.println(error_rate); 77 | } 78 | GPRSHTTP* con = modem.createHTTPConnection(settings, url); 79 | if(con == NULL) 80 | { 81 | Serial.println(get_error_message(modem.get_error_condition())); 82 | return; 83 | } 84 | if(con->init() && con->post_init(14)) 85 | { 86 | con->println("Hello World!"); 87 | if(con->post(cid, code, length)) 88 | { 89 | Serial.print("HTTP CODE: "); 90 | Serial.println(code, DEC); 91 | Serial.print("Length: "); 92 | Serial.println(length, DEC); 93 | if(con->init_retrieve()) 94 | { 95 | length = length + 1; //Trigger an error condition. 96 | char data[length + 1]; //Ensure that this is a NULL Terminated String.... 97 | data[length] = '\0'; //.... 98 | if(con->read(data, length)) 99 | { 100 | Serial.println("Retrieved Data:"); 101 | Serial.println(data); 102 | } 103 | if(con->get_error_condition() == SIM900_ERROR_READ_LIMIT_EXCEEDED) 104 | { 105 | Serial.println("We tried to Read more characters from the connection than were available!"); 106 | } 107 | } 108 | } 109 | } 110 | con->terminate(); 111 | delete con; 112 | Serial.println("------------------------------------------------"); 113 | }else 114 | { 115 | Serial.println("Powering up modem failed !"); 116 | } 117 | modem.powerDown(); 118 | } 119 | ``` 120 | -------------------------------------------------------------------------------- /Sim900.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Sim900 is an Arduino library for working with the Sim900 GRPS Shield 3 | Copyright (C) 2012 Nigel Bajema 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License 7 | as published by the Free Software Foundation; either version 2 8 | of the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | */ 19 | 20 | #include "Sim900.h" 21 | 22 | void set_sim900_debug_mode(bool mode) 23 | { 24 | SIM900_DEBUG_OUTPUT = mode; 25 | } 26 | 27 | void set_sim900_debug_stream(Stream* stream) 28 | { 29 | SIM900_DEBUG_OUTPUT_STREAM = stream; 30 | } 31 | 32 | // 33 | //Set the SIM900 input timeout in milliseconds 34 | // 35 | void set_sim900_input_timeout(unsigned long timeout) 36 | { 37 | SIM900_INPUT_TIMEOUT = timeout; 38 | } 39 | 40 | bool is_valid_connection_type(char* to_check) 41 | { 42 | if(to_check == NULL) 43 | { 44 | return false; 45 | } 46 | for(uint32_t i = 0; VALID_CONNECTION_TYPES[i] != NULL; i++) 47 | { 48 | if(strcmp(VALID_CONNECTION_TYPES[i], to_check) == 0) 49 | { 50 | return true; 51 | } 52 | } 53 | return false; 54 | } 55 | 56 | bool is_valid_connection_rate(char* to_check) 57 | { 58 | uint32_t speed = String(to_check).toInt(); 59 | for(uint32_t i = 0; VALID_CONNECTION_SPEEDS[i] != NULL; i++) 60 | { 61 | if(speed == VALID_CONNECTION_SPEEDS[i]) 62 | { 63 | return true; 64 | } 65 | } 66 | return false; 67 | } 68 | 69 | char* get_error_message(int error_code) 70 | { 71 | for(uint32_t i = 0; messages[i].code != SIM900_ERROR_LIST_TERMINATOR; i++) 72 | { 73 | if(messages[i].code == error_code) 74 | { 75 | return messages[i].message; 76 | } 77 | } 78 | return "Could not find error message.\0";//SIM900_UNKNOWN_ERROR_MESSAGE; 79 | } 80 | 81 | Sim900::Sim900(SoftwareSerial* serial, int baud_rate, int powerPin, int statusPin, enum MODEM_VARIANT varient) 82 | { 83 | _serial = serial; 84 | _powerPin = powerPin; 85 | _statusPin = statusPin; 86 | _lock = 0; 87 | _error_condition = SIM900_ERROR_NO_ERROR; 88 | _ser = serial; 89 | handle_varient(varient); 90 | serial->begin(baud_rate); 91 | } 92 | 93 | Sim900::Sim900(HardwareSerial* serial, int baud_rate, int powerPin, int statusPin, enum MODEM_VARIANT varient) 94 | { 95 | _serial = serial; 96 | _powerPin = powerPin; 97 | _statusPin = statusPin; 98 | _lock = 0; 99 | _error_condition = SIM900_ERROR_NO_ERROR; 100 | _ser = NULL; 101 | handle_varient(varient); 102 | serial->begin(baud_rate); 103 | } 104 | 105 | void Sim900::handle_varient(MODEM_VARIANT varient) 106 | { 107 | this->varient = varient; 108 | switch(varient) 109 | { 110 | case VARIANT_1: 111 | max_http_post_size = SIM900_MAX_POST_DATA_V1; 112 | break; 113 | case VARIANT_2: 114 | max_http_post_size = SIM900_MAX_POST_DATA_V2; 115 | break; 116 | } 117 | } 118 | 119 | MODEM_VARIANT Sim900::get_varient() 120 | { 121 | return varient; 122 | } 123 | uint32_t Sim900::get_max_http_post_size() 124 | { 125 | return max_http_post_size; 126 | } 127 | 128 | void Sim900::set_error_condition(int error_value) 129 | { 130 | _error_condition = error_value; 131 | } 132 | 133 | int Sim900::get_error_condition() 134 | { 135 | return _error_condition; 136 | } 137 | 138 | bool Sim900::isPoweredUp() 139 | { 140 | pinMode(_statusPin, INPUT); 141 | return analogRead(_statusPin) > SIM900_POWERUP_THRESHOLD; 142 | 143 | } 144 | 145 | bool Sim900::lock() 146 | { 147 | if(_lock == 0) 148 | { 149 | if(SIM900_DEBUG_OUTPUT){ 150 | SIM900_DEBUG_OUTPUT_STREAM->println("Locked...."); 151 | } 152 | _lock = 1; 153 | return true; 154 | } 155 | set_error_condition(SIM900_ERROR_COULD_NOT_AQUIRE_LOCK); 156 | return false; 157 | } 158 | 159 | bool Sim900::unlock() 160 | { 161 | if(_lock == 1) 162 | { 163 | if(SIM900_DEBUG_OUTPUT){ 164 | SIM900_DEBUG_OUTPUT_STREAM->println("Unlocked...."); 165 | } 166 | _lock = 0; 167 | } 168 | return true; 169 | } 170 | 171 | bool Sim900::compare(char to_test[], char target[], int pos, int length, int test_len) 172 | { 173 | int s = pos - length; 174 | if(s < 0){s = 0;} 175 | for(int i = 0; i < length; i++) 176 | { 177 | if(to_test[(i+s) % test_len] != target[i]) 178 | { 179 | return false; 180 | } 181 | } 182 | return true; 183 | } 184 | 185 | int Sim900::waitFor(char target[], bool dropLastEOL, String* data) 186 | { 187 | return waitFor(target, dropLastEOL, data, SIM900_INPUT_TIMEOUT); 188 | } 189 | 190 | int Sim900::waitFor(char target[], bool dropLastEOL, String* data, unsigned long timeout) 191 | { 192 | set_error_condition(SIM900_ERROR_NO_ERROR); 193 | if(SIM900_DEBUG_OUTPUT){ 194 | SIM900_DEBUG_OUTPUT_STREAM->print("Waiting for: "); 195 | SIM900_DEBUG_OUTPUT_STREAM->println(target); 196 | } 197 | unsigned long time = millis(); 198 | int len = strlen(target); 199 | int test_len = len; 200 | if(test_len < 5) 201 | { 202 | test_len = 5; 203 | } 204 | int pos = 0; 205 | char tmp[test_len + 1]; 206 | tmp[test_len] = NULL; 207 | char _tmp; 208 | bool concat = data != NULL; 209 | while(!compare(tmp, target, pos, len, test_len)) 210 | { 211 | if(compare(tmp, "ERROR", pos, 5, test_len)) 212 | { 213 | if(SIM900_DEBUG_OUTPUT){SIM900_DEBUG_OUTPUT_STREAM->println("");SIM900_DEBUG_OUTPUT_STREAM->println("ERROR");} 214 | set_error_condition(SIM900_ERROR_MODEM_ERROR); 215 | return false; 216 | } 217 | if(_serial->available()) 218 | { 219 | _tmp = _serial->read(); 220 | if(SIM900_DEBUG_OUTPUT){ 221 | SIM900_DEBUG_OUTPUT_STREAM->write(_tmp); 222 | } 223 | if(concat){ 224 | data->concat(_tmp); 225 | } 226 | tmp[pos++ % test_len] = _tmp; 227 | time = millis(); 228 | }else if((millis() - time) > timeout) 229 | { 230 | set_error_condition(SIM900_ERROR_TIMEOUT); 231 | if(SIM900_DEBUG_OUTPUT){ 232 | SIM900_DEBUG_OUTPUT_STREAM->println(""); 233 | SIM900_DEBUG_OUTPUT_STREAM->print("Timed out waiting for: "); 234 | SIM900_DEBUG_OUTPUT_STREAM->println(target); 235 | } 236 | return false; 237 | } 238 | } 239 | if(dropLastEOL) 240 | { 241 | dropEOL(); 242 | } 243 | if(SIM900_DEBUG_OUTPUT){SIM900_DEBUG_OUTPUT_STREAM->println("");SIM900_DEBUG_OUTPUT_STREAM->println("Found it!");} 244 | return true; 245 | 246 | } 247 | 248 | bool Sim900::dropEOL() 249 | { 250 | while(_serial->available() && (_serial->peek() == 10 || _serial->peek() == 13)) 251 | { 252 | _serial->read(); 253 | } 254 | } 255 | 256 | void Sim900::powerToggle() 257 | { 258 | pinMode(_powerPin, OUTPUT); 259 | digitalWrite(_powerPin, LOW); 260 | delay(1000); 261 | digitalWrite(_powerPin, HIGH); 262 | delay(2000); 263 | digitalWrite(_powerPin, LOW); 264 | delay(3000); 265 | } 266 | 267 | bool Sim900::powerUp() 268 | { 269 | if(SIM900_DEBUG_OUTPUT){ 270 | SIM900_DEBUG_OUTPUT_STREAM->println("Powering up Modem!"); 271 | } 272 | if(!isPoweredUp()) 273 | { 274 | //if(_ser != NULL) 275 | //{ 276 | // _ser->listen(); 277 | //} 278 | powerToggle(); 279 | if(waitFor("Call Ready", true, NULL)) 280 | { 281 | return true; 282 | }else 283 | { 284 | if(isPoweredUp()) 285 | { 286 | powerToggle(); 287 | } 288 | } 289 | 290 | } 291 | return false; 292 | } 293 | bool Sim900::powerDown() 294 | { 295 | if(isPoweredUp()) 296 | { 297 | powerToggle(); 298 | return waitFor("NORMAL POWER DOWN", true, NULL); 299 | } 300 | return false; 301 | } 302 | 303 | bool Sim900::getSignalQuality(int &strength, int &error_rate) 304 | { 305 | if(lock()) 306 | { 307 | _serial->write("AT+CSQ\r\n"); 308 | _serial->flush(); 309 | delay(100); 310 | String d; 311 | if(waitFor("OK", true, &d)) 312 | { 313 | int _start = d.lastIndexOf("+CSQ"); 314 | _start = d.indexOf(" ", _start) + 1; 315 | int split = d.indexOf(",", _start); 316 | int _end = d.indexOf("\r", _start); 317 | strength = d.substring(_start, split).toInt(); 318 | error_rate = d.substring(split+1, _end).toInt(); 319 | unlock(); 320 | return true; 321 | }else 322 | { 323 | unlock(); 324 | } 325 | } 326 | return false; 327 | } 328 | 329 | bool Sim900::waitForSignal(int iterations, int wait_time) 330 | { 331 | int strength = -1, error_rate = -1, strength_count = 0; 332 | while(strength <= 0) 333 | { 334 | if(getSignalQuality(strength, error_rate)) 335 | { 336 | if(SIM900_DEBUG_OUTPUT){ 337 | SIM900_DEBUG_OUTPUT_STREAM->print("Strength: "); 338 | SIM900_DEBUG_OUTPUT_STREAM->print(strength); 339 | SIM900_DEBUG_OUTPUT_STREAM->print(" Error Rate: "); 340 | SIM900_DEBUG_OUTPUT_STREAM->println(error_rate); 341 | } 342 | } 343 | if(strength <= 0){ 344 | if(SIM900_DEBUG_OUTPUT){ 345 | SIM900_DEBUG_OUTPUT_STREAM->println("Waiting for modem to establish connection..."); 346 | } 347 | 348 | delay(wait_time); 349 | strength_count++; 350 | } 351 | if(strength_count > iterations) 352 | { 353 | if(SIM900_DEBUG_OUTPUT){ 354 | SIM900_DEBUG_OUTPUT_STREAM->println("Could not establish connection. Not uploading data."); 355 | } 356 | return false; 357 | } 358 | } 359 | return true; 360 | } 361 | 362 | bool Sim900::issueCommand(char command[], char ok[], bool dropLastEOL) 363 | { 364 | _serial->write(command); 365 | waitFor(ok, dropLastEOL, NULL); 366 | 367 | } 368 | 369 | 370 | void Sim900::dumpStream() 371 | { 372 | while(_serial->available()) 373 | { 374 | Serial.write(_serial->read()); 375 | } 376 | } 377 | 378 | bool Sim900::is_valid_connection_settings(CONN settings) 379 | { 380 | if(!(settings.cid >= 0 && settings.cid <= 5)) 381 | { 382 | set_error_condition(SIM900_ERROR_INVALID_CID_VALUE); 383 | return false; 384 | } 385 | if(!is_valid_connection_type(settings.contype)) 386 | { 387 | set_error_condition(SIM900_ERROR_INVALID_CONNECTION_TYPE); 388 | return false; 389 | } 390 | if(settings.apn != NULL && !(strlen(settings.apn) <= SIM900_MAX_CONNECTION_SETTING_CHARACTERS)) 391 | { 392 | set_error_condition(SIM900_ERROR_CHARACTER_LIMIT_EXCEEDED); 393 | return false; 394 | } 395 | if(settings.user!= NULL && !(strlen(settings.user) <= SIM900_MAX_CONNECTION_SETTING_CHARACTERS)) 396 | { 397 | set_error_condition(SIM900_ERROR_CHARACTER_LIMIT_EXCEEDED); 398 | return false; 399 | } 400 | if(settings.pwd != NULL && !(strlen(settings.pwd) <= SIM900_MAX_CONNECTION_SETTING_CHARACTERS)) 401 | { 402 | set_error_condition(SIM900_ERROR_CHARACTER_LIMIT_EXCEEDED); 403 | return false; 404 | } 405 | if(settings.rate != NULL && !is_valid_connection_rate(settings.rate)) 406 | { 407 | set_error_condition(SIM900_ERROR_INVALID_CONNECTION_RATE); 408 | return false; 409 | } 410 | return true; 411 | } 412 | 413 | GPRSHTTP* Sim900::createHTTPConnection(CONN settings, char URL[]) 414 | { 415 | set_error_condition(SIM900_ERROR_NO_ERROR); 416 | if(is_valid_connection_settings(settings) && lock()){ 417 | if(settings.contype != NULL) 418 | { 419 | _serial->write("AT+SAPBR=3,"); 420 | _serial->print(settings.cid, DEC); 421 | _serial->write(",\"CONTYPE\",\""); 422 | _serial->write(settings.contype); 423 | _serial->println("\""); 424 | waitFor("OK", true, NULL); 425 | } 426 | if(settings.apn != NULL) 427 | { 428 | _serial->write("AT+SAPBR=3,"); 429 | _serial->print(settings.cid, DEC); 430 | _serial->write(",\"APN\",\""); 431 | _serial->write(settings.apn); 432 | _serial->println("\""); 433 | waitFor("OK", true, NULL); 434 | } 435 | if(settings.user != NULL) 436 | { 437 | _serial->write("AT+SAPBR=3,"); 438 | _serial->print(settings.cid, DEC); 439 | _serial->write(",\"USER\",\""); 440 | _serial->write(settings.user); 441 | _serial->println("\""); 442 | waitFor("OK", true, NULL); 443 | } 444 | if(settings.pwd != NULL) 445 | { 446 | _serial->write("AT+SAPBR=3,"); 447 | _serial->print(settings.cid, DEC); 448 | _serial->write(",\"PWD\",\""); 449 | _serial->write(settings.pwd); 450 | _serial->println("\""); 451 | waitFor("OK", true, NULL); 452 | } 453 | if(settings.phone != NULL) 454 | { 455 | _serial->write("AT+SAPBR=3,"); 456 | _serial->print(settings.cid, DEC); 457 | _serial->write(",\"PHONENUM\",\""); 458 | _serial->write(settings.phone); 459 | _serial->println("\""); 460 | waitFor("OK", true, NULL); 461 | } 462 | if(settings.rate != NULL) 463 | { 464 | _serial->write("AT+SAPBR=3,"); 465 | _serial->print(settings.cid, DEC); 466 | _serial->write(",\"RATE\",\""); 467 | _serial->write(settings.rate); 468 | _serial->println("\""); 469 | waitFor("OK", true, NULL); 470 | } 471 | 472 | return new GPRSHTTP(this, settings.cid, URL); 473 | } 474 | return NULL; 475 | } 476 | 477 | GPRSHTTP::GPRSHTTP(Sim900* sim, int cid, char URL[]) 478 | { 479 | _sim = sim; 480 | _cid = cid; 481 | url = URL; 482 | initialized = false; 483 | _data_ready = false; 484 | write_count = 0; 485 | write_limit = 0; 486 | read_limit = 0; 487 | read_count = 0; 488 | sequence_bit_map = 0; 489 | } 490 | 491 | bool GPRSHTTP::setParam(char* param, String value) 492 | { 493 | if(!initialized) 494 | { 495 | Serial.println("GPRSHTTP must have been initialized before setParam can be called."); 496 | return false; 497 | } 498 | //Set the PARAM 499 | Serial.print("Setting HTTP Param "); 500 | Serial.print(param); 501 | Serial.print(" to "); 502 | Serial.println(value); 503 | _sim->_serial->write("AT+HTTPPARA=\""); 504 | _sim->_serial->print(param); 505 | _sim->_serial->print("\",\""); 506 | _sim->_serial->print(value); 507 | _sim->_serial->println("\""); 508 | if(!_sim->waitFor("OK", true, NULL)) 509 | { 510 | return false; 511 | } 512 | return true; 513 | } 514 | bool GPRSHTTP::setParam(char* param, uint32_t value) 515 | { 516 | return setParam(param, String(value)); 517 | } 518 | bool GPRSHTTP::setParam(char* param, char* value) 519 | { 520 | return setParam(param, String(value)); 521 | } 522 | int GPRSHTTP::isCGATT() 523 | { 524 | _sim->_serial->println("AT+CGATT?"); 525 | String connected; 526 | if(!_sim->waitFor("OK", true, &connected)) 527 | { 528 | return -1; 529 | } 530 | int pos = connected.indexOf("+CGATT: "); 531 | pos = connected.indexOf(" ", pos); 532 | connected = connected.substring(pos, connected.indexOf("\r", pos)); 533 | connected.trim(); 534 | if(SIM900_DEBUG_OUTPUT) 535 | { 536 | SIM900_DEBUG_OUTPUT_STREAM->print("CGATT result: "); 537 | SIM900_DEBUG_OUTPUT_STREAM->println(connected); 538 | } 539 | return connected.toInt(); 540 | 541 | } 542 | bool GPRSHTTP::HTTPINIT(int retries, int _delay) 543 | { 544 | //Initialize the HTTP Application context. 545 | for(int i = 0; i < retries; i++) 546 | { 547 | _sim->_serial->println("AT+HTTPINIT"); 548 | if(_sim->waitFor("OK", true, NULL)) 549 | { 550 | 551 | SIM900_DEBUG_OUTPUT_STREAM->println("HTTP Initialized!"); 552 | return true; 553 | } 554 | SIM900_DEBUG_OUTPUT_STREAM->println("Failed to initialize HTTP context, waiting to retry."); 555 | delay(_delay); 556 | } 557 | return false; 558 | } 559 | 560 | bool GPRSHTTP::stopBearer(int retries, int _delay) 561 | { 562 | //Shutdown the connection first. 563 | for(int i = 0; i < retries; i++) 564 | { 565 | _sim->_serial->write("AT+SAPBR=0,"); 566 | _sim->_serial->println(_cid, DEC); 567 | if(_sim->waitFor("OK", true, NULL)) 568 | { 569 | return true; 570 | }else 571 | { 572 | if(SIM900_DEBUG_OUTPUT) 573 | { 574 | SIM900_DEBUG_OUTPUT_STREAM->println("Not Shutdown."); 575 | } 576 | } 577 | delay(_delay); 578 | } 579 | return false; 580 | } 581 | bool GPRSHTTP::startBearer(int retries, int _delay) 582 | { 583 | //Start the connection. 584 | for(int i = 0; i < retries; i++) 585 | { 586 | _sim->_serial->write("AT+SAPBR=1,"); 587 | _sim->_serial->println(_cid, DEC); 588 | if(_sim->waitFor("OK", true, NULL)) 589 | { 590 | if(SIM900_DEBUG_OUTPUT) 591 | { 592 | SIM900_DEBUG_OUTPUT_STREAM->println("Connected!"); 593 | } 594 | return true; 595 | } 596 | if(SIM900_DEBUG_OUTPUT) 597 | { 598 | SIM900_DEBUG_OUTPUT_STREAM->println("Failed to connect, waiting to retry."); 599 | } 600 | delay(_delay); 601 | } 602 | return false; 603 | } 604 | 605 | bool GPRSHTTP::init(int timeout) 606 | { 607 | if(timeout > 1000 || timeout < 30) 608 | { 609 | _error_condition = SIM900_ERROR_INVALID_HTTP_TIMEOUT; 610 | if(SIM900_DEBUG_OUTPUT) 611 | { 612 | SIM900_DEBUG_OUTPUT_STREAM->println(get_error_message(SIM900_ERROR_INVALID_HTTP_TIMEOUT)); 613 | } 614 | return false; 615 | } 616 | int connected = isCGATT(); 617 | if(connected == -1) 618 | { 619 | return false; 620 | } 621 | delay(1000); 622 | 623 | if(connected == 1){ 624 | stopBearer(1, 0); 625 | } 626 | 627 | if(!startBearer(5, 2000)) 628 | { 629 | return false; 630 | } 631 | 632 | initialized = HTTPINIT(5, 2000); 633 | if(!initialized) 634 | { 635 | return false; 636 | } 637 | 638 | //Set the CID 639 | if(!setParam("CID", _cid)) 640 | { 641 | return false; 642 | } 643 | 644 | //Set the URL 645 | if(!setParam("URL", url)) 646 | { 647 | return false; 648 | } 649 | 650 | //Set the HTTP Timeout 651 | if(!setParam("TIMEOUT", timeout)) 652 | { 653 | return false; 654 | } 655 | 656 | Serial.print("URL: "); Serial.println(url); 657 | return true; 658 | } 659 | 660 | bool GPRSHTTP::post_init(uint32_t content_length){ 661 | set_error_condition(SIM900_ERROR_NO_ERROR); 662 | if(content_length > _sim->max_http_post_size) 663 | { 664 | if(SIM900_DEBUG_OUTPUT) 665 | { 666 | SIM900_DEBUG_OUTPUT_STREAM->print("Specified Content Length: "); 667 | SIM900_DEBUG_OUTPUT_STREAM->print(content_length); 668 | SIM900_DEBUG_OUTPUT_STREAM->print(" is greater than the maximum allowed post size of "); 669 | SIM900_DEBUG_OUTPUT_STREAM->println(_sim->max_http_post_size); 670 | } 671 | set_error_condition(SIM900_ERROR_MAX_POST_DATA_SIZE_EXCEEDED); 672 | return false; 673 | } 674 | _sim->_serial->write("AT+HTTPDATA="); 675 | _sim->_serial->print(content_length, DEC); 676 | _sim->_serial->write(","); 677 | _sim->_serial->println(SIM900_HTTP_TIMEOUT, DEC); 678 | if(!_sim->waitFor("DOWNLOAD", true, NULL)) 679 | { 680 | return false; 681 | } 682 | write_limit = content_length; 683 | // return _sim->_serial; 684 | return true; 685 | 686 | } 687 | 688 | 689 | //If the response from the server does not have a Content-Length header 690 | //then length will always be zero. 691 | bool GPRSHTTP::post(int &cid, int &HTTP_CODE, int32_t &length){ 692 | unsigned long upload_time_out = SIM900_INPUT_TIMEOUT; 693 | if(SIM900_DEBUG_OUTPUT) 694 | { 695 | SIM900_DEBUG_OUTPUT_STREAM->print("Write Count: "); 696 | SIM900_DEBUG_OUTPUT_STREAM->print(write_count); 697 | SIM900_DEBUG_OUTPUT_STREAM->print(" Write Limit: "); 698 | SIM900_DEBUG_OUTPUT_STREAM->println(write_limit); 699 | } 700 | if(write_limit * 10 > upload_time_out) 701 | { 702 | upload_time_out = write_limit * 10; 703 | } 704 | if(!_sim->waitFor("OK", true, NULL)) 705 | { 706 | return false; 707 | } 708 | _sim->_serial->write("AT+HTTPACTION="); 709 | _sim->_serial->println(POST, DEC); 710 | if(!_sim->waitFor("+HTTPACTION:", true, NULL, upload_time_out)) 711 | { 712 | return false; 713 | } 714 | String* tmp = new String(); 715 | _sim->waitFor("\n", true, tmp); 716 | int _start = tmp->indexOf(","); 717 | cid = tmp->substring(0, _start).toInt(); 718 | int _end = tmp->indexOf(",", _start+1); 719 | HTTP_CODE = tmp->substring(_start + 1, _end).toInt(); 720 | _start = _end + 1; 721 | length = tmp->substring(_start).toInt(); 722 | read_limit = length; 723 | delete tmp; 724 | return true; 725 | 726 | } 727 | 728 | int GPRSHTTP::init_retrieve() 729 | { 730 | Serial.println("Getting Data."); 731 | _sim->_serial->print("AT+HTTPREAD=0,"); 732 | _sim->_serial->println(read_limit, DEC); 733 | if(!_sim->waitFor("+HTTPREAD:", true, NULL)) 734 | { 735 | return false; 736 | } 737 | _sim->waitFor("\n", true, NULL); 738 | _data_ready = true; 739 | return true; 740 | } 741 | 742 | bool GPRSHTTP::terminate() 743 | { 744 | _sim->_serial->println("AT+HTTPTERM"); 745 | _sim->waitFor("OK", true, NULL); 746 | stopBearer(5,1000); 747 | _sim->unlock(); 748 | } 749 | 750 | size_t GPRSHTTP::write(uint8_t byte) 751 | { 752 | if(write_count++ < write_limit) 753 | { 754 | 755 | size_t toRet = _sim->_serial->write(byte); 756 | if(SIM900_DEBUG_OUTPUT && _sim->_serial->available()) 757 | { 758 | SIM900_DEBUG_OUTPUT_STREAM->println(); 759 | while(_sim->_serial->available()) 760 | { 761 | SIM900_DEBUG_OUTPUT_STREAM->print((char)_sim->_serial->read()); 762 | } 763 | SIM900_DEBUG_OUTPUT_STREAM->println(); 764 | } 765 | return toRet; 766 | } 767 | return -1; 768 | } 769 | 770 | 771 | size_t GPRSHTTP::read(char* buf, int length) 772 | { 773 | return read((byte*)buf, length); 774 | } 775 | 776 | size_t GPRSHTTP::read(byte* buf, int length) 777 | { 778 | int tmp = -1; 779 | for(int i = 0; i < length;) 780 | { 781 | tmp = read(); 782 | if(tmp < 0) 783 | { 784 | return i; 785 | } 786 | buf[i] = tmp; 787 | i++; 788 | } 789 | } 790 | 791 | int GPRSHTTP::read() 792 | { 793 | set_error_condition(SIM900_ERROR_NO_ERROR); 794 | unsigned long time = millis(); 795 | int avail = 0; 796 | if(!_data_ready) 797 | { 798 | set_error_condition(SIM900_ERROR_DATA_NOT_READY); 799 | return SIM900_ERROR_DATA_NOT_READY; 800 | } 801 | if(read_count++ <= read_limit) 802 | { 803 | while((avail = available()) == false) 804 | { 805 | if((millis() - time) > SIM900_INPUT_TIMEOUT) 806 | { 807 | if(SIM900_DEBUG_OUTPUT) 808 | { 809 | SIM900_DEBUG_OUTPUT_STREAM->println("The timeout was reached whilst trying to read the HTTP response."); 810 | } 811 | return SIM900_ERROR_TIMEOUT; 812 | } 813 | } 814 | if(avail > 0) 815 | { 816 | return _sim->_serial->read(); 817 | }else 818 | { 819 | set_error_condition(avail); 820 | return avail; 821 | } 822 | } 823 | else 824 | { 825 | if(SIM900_DEBUG_OUTPUT) 826 | { 827 | set_error_condition(SIM900_ERROR_READ_LIMIT_EXCEEDED); 828 | SIM900_DEBUG_OUTPUT_STREAM->print("Read limit: "); 829 | SIM900_DEBUG_OUTPUT_STREAM->print(read_limit); 830 | SIM900_DEBUG_OUTPUT_STREAM->print(" has been exceed by read count: "); 831 | SIM900_DEBUG_OUTPUT_STREAM->println(read_count); 832 | } 833 | } 834 | return -1; 835 | } 836 | 837 | int GPRSHTTP::available() 838 | { 839 | if(read_count <= read_limit) 840 | { 841 | return _sim->_serial->available(); 842 | } 843 | else 844 | { 845 | if(SIM900_DEBUG_OUTPUT) 846 | { 847 | SIM900_DEBUG_OUTPUT_STREAM->print("Read limit: "); 848 | SIM900_DEBUG_OUTPUT_STREAM->print(read_limit); 849 | SIM900_DEBUG_OUTPUT_STREAM->print(" has been exceed by read count: "); 850 | SIM900_DEBUG_OUTPUT_STREAM->println(read_count); 851 | } 852 | return SIM900_ERROR_READ_LIMIT_EXCEEDED; 853 | } 854 | return false; 855 | } 856 | 857 | void GPRSHTTP::flush() 858 | { 859 | _sim->_serial->flush(); 860 | } 861 | 862 | int GPRSHTTP::peek() 863 | { 864 | set_error_condition(SIM900_ERROR_NO_ERROR); 865 | if(read_count <= read_limit) 866 | { 867 | return _sim->_serial->peek(); 868 | } 869 | else 870 | { 871 | if(SIM900_DEBUG_OUTPUT) 872 | { 873 | set_error_condition(SIM900_ERROR_READ_LIMIT_EXCEEDED); 874 | SIM900_DEBUG_OUTPUT_STREAM->print("Read limit: "); 875 | SIM900_DEBUG_OUTPUT_STREAM->print(read_limit); 876 | SIM900_DEBUG_OUTPUT_STREAM->print(" has been exceed by read count: "); 877 | SIM900_DEBUG_OUTPUT_STREAM->print(read_count); 878 | } 879 | } 880 | return -1; 881 | 882 | } 883 | 884 | void GPRSHTTP::set_error_condition(int error_value) 885 | { 886 | _error_condition = error_value; 887 | } 888 | 889 | int GPRSHTTP::get_error_condition() 890 | { 891 | return _error_condition; 892 | } 893 | 894 | -------------------------------------------------------------------------------- /Sim900.h: -------------------------------------------------------------------------------- 1 | /* 2 | Sim900 is an Arduino library for working with the Sim900 GRPS Shield 3 | Copyright (C) 2012 Nigel Bajema 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License 7 | as published by the Free Software Foundation; either version 2 8 | of the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | */ 19 | 20 | #ifndef __SIM_900_H__ 21 | #define __SIM_900_H__ 22 | 23 | #define NULL 0 24 | #define GET 0 25 | #define POST 1 26 | #define HEAD 2 27 | 28 | #ifndef SIM900_POWERUP_THRESHOLD 29 | #define SIM900_POWERUP_THRESHOLD 100 30 | #endif 31 | 32 | #ifndef SIM900_HTTP_TIMEOUT 33 | #define SIM900_HTTP_TIMEOUT 100000 34 | #endif 35 | 36 | 37 | #define SIM900_ERROR_LIST_TERMINATOR 1 38 | #define SIM900_ERROR_NO_ERROR 0 39 | #define SIM900_ERROR_COULD_NOT_AQUIRE_LOCK -1 40 | #define SIM900_ERROR_MODEM_ERROR -10 41 | #define SIM900_ERROR_TIMEOUT -20 42 | #define SIM900_ERROR_DATA_NOT_READY -30 43 | #define SIM900_ERROR_MAX_POST_DATA_SIZE_EXCEEDED -40 44 | #define SIM900_ERROR_READ_LIMIT_EXCEEDED -41 45 | #define SIM900_ERROR_INVALID_CID_VALUE -50 46 | #define SIM900_ERROR_CHARACTER_LIMIT_EXCEEDED -51 47 | #define SIM900_ERROR_INVALID_CONNECTION_TYPE -52 48 | #define SIM900_ERROR_INVALID_CONNECTION_RATE -53 49 | #define SIM900_ERROR_INVALID_HTTP_TIMEOUT -54 50 | 51 | #define SIM900_MAX_POST_DATA_V1 318976 52 | #define SIM900_MAX_POST_DATA_V2 102400 53 | #define SIM900_CONNECTION_INIT = 2; 54 | #define SIM900_MAX_CONNECTION_SETTING_CHARACTERS 50 55 | 56 | 57 | #include 58 | 59 | //#if defined(ARDUINO) && ARDUINO >= 100 60 | #include "Arduino.h" 61 | //#else 62 | //#include "WProgram.h" 63 | //#endif 64 | 65 | #include 66 | 67 | 68 | static bool SIM900_DEBUG_OUTPUT = false; 69 | static Stream* SIM900_DEBUG_OUTPUT_STREAM = &Serial; 70 | static unsigned long SIM900_INPUT_TIMEOUT = 60000l; 71 | 72 | //According to http://www.mt-system.ru/sites/default/files/docs/simcom/docs/sim900/sim900_at_command_manual_v1.06.pdf 73 | //There are multiple varients of the Sim900 modules, which affect things 74 | //like the SIM900_MAX_POST_DATA size. 75 | enum MODEM_VARIANT 76 | { 77 | VARIANT_1, 78 | VARIANT_2 79 | } ; 80 | 81 | struct CONN 82 | { 83 | int cid; // Bearer profile identifier. 84 | char* contype; // Valid Options: GPRS, CSD. 85 | char* apn; // Provided by telco. Sometimes preprogrammed into the SIM card. 86 | char* user; // Username, MAX 50 Characters. 87 | char* pwd; // Password, MAX 50 Charcters. 88 | char* phone; // Phone number for CSD call. 89 | char* rate; // CSD connection rate. 90 | 91 | CONN() : cid(-1), contype(NULL), apn(NULL), user(NULL), pwd(NULL), phone(NULL), rate(NULL) {} 92 | }; 93 | 94 | struct error_message 95 | { 96 | int code; 97 | char* message; 98 | }; 99 | 100 | static error_message messages[] = 101 | { 102 | {SIM900_ERROR_NO_ERROR, "No Error"}, 103 | {SIM900_ERROR_COULD_NOT_AQUIRE_LOCK, "Only one connection at a time can use the modem."}, 104 | {SIM900_ERROR_MODEM_ERROR, "Modem Error"}, 105 | {SIM900_ERROR_TIMEOUT, "Timed out waiting for modem response."}, 106 | {SIM900_ERROR_DATA_NOT_READY, "init_retrieve needs to be called before data can be read."}, 107 | {SIM900_ERROR_MAX_POST_DATA_SIZE_EXCEEDED, "The maximum post data size was exceeded."}, 108 | {SIM900_ERROR_READ_LIMIT_EXCEEDED, "The read limit was exceeded."}, 109 | {SIM900_ERROR_INVALID_CID_VALUE, "Invalid Bearer profile Identifier"}, 110 | {SIM900_ERROR_CHARACTER_LIMIT_EXCEEDED, "The Maximum character limit was exceeded"}, 111 | {SIM900_ERROR_INVALID_CONNECTION_TYPE, "The specified connection type is not valid."}, 112 | {SIM900_ERROR_INVALID_CONNECTION_RATE, "The specified connection rate is not valid."}, 113 | {SIM900_ERROR_INVALID_HTTP_TIMEOUT, "The HTTP Timeout value must be between 30 and 1000 seconds."}, 114 | 115 | 116 | //This needs to be the last element or things will go badly wrong. 117 | {SIM900_ERROR_LIST_TERMINATOR, NULL} 118 | }; 119 | 120 | static const char *VALID_CONNECTION_TYPES[] = { 121 | "GPRS", 122 | "CSD", 123 | NULL 124 | }; 125 | 126 | static const int VALID_CONNECTION_SPEEDS[] = 127 | { 128 | 2400, 129 | 4800, 130 | 9600, 131 | 14400, 132 | NULL 133 | }; 134 | 135 | bool is_valid_connection_type(char* to_check); 136 | bool is_valid_connection_rate(char* to_check); 137 | void set_sim900_debug_mode(bool mode); 138 | void set_sim900_debug_stream(Stream* stream); 139 | void set_sim900_input_timeout(unsigned long timeout); 140 | char* get_error_message(int error_code); 141 | 142 | class GPRSHTTP; 143 | 144 | class Sim900 145 | { 146 | private: 147 | Stream* _serial; 148 | SoftwareSerial* _ser; 149 | int _error_condition; 150 | int _powerPin; 151 | int _statusPin; 152 | int _lock; 153 | enum MODEM_VARIANT varient; 154 | uint32_t max_http_post_size; 155 | 156 | bool lock(); 157 | bool unlock(); 158 | bool dropEOL(); 159 | int waitFor(char target[], bool dropLastEOL, String* data); 160 | int waitFor(char target[], bool dropLastEOL, String* data, unsigned long timeout); 161 | bool compare(char to_test[], char target[], int pos, int length, int test_len); 162 | void powerToggle(); 163 | bool issueCommand(char command[], char ok[], bool dropLastEOL); 164 | void dumpStream(); 165 | void set_error_condition(int error_value); 166 | bool is_valid_connection_settings(CONN settings); 167 | void handle_varient(MODEM_VARIANT varient); 168 | public: 169 | Sim900(SoftwareSerial* serial, int baud_rate, int powerPin, int statusPin, enum MODEM_VARIANT varient); 170 | Sim900(HardwareSerial* serial, int baud_rate, int powerPin, int statusPin, enum MODEM_VARIANT varient); 171 | 172 | MODEM_VARIANT get_varient(); 173 | uint32_t get_max_http_post_size(); 174 | 175 | bool getSignalQuality(int &strength, int &error_rate); 176 | bool waitForSignal(int iterations, int wait_time); 177 | bool isPoweredUp(); 178 | bool powerUp(); 179 | bool powerDown(); 180 | GPRSHTTP* createHTTPConnection(CONN settings, char URL[]); 181 | /*bool startGPRS(); 182 | bool stopGPRS();*/ 183 | int get_error_condition(); 184 | 185 | 186 | friend class GPRSHTTP; 187 | }; 188 | 189 | class GPRSHTTP : public Stream 190 | { 191 | private: 192 | 193 | uint32_t sequence_bit_map; 194 | Sim900* _sim; 195 | int _error_condition; 196 | int _cid; 197 | char* url; 198 | String _data; 199 | uint32_t write_limit, write_count; 200 | uint32_t read_limit, read_count; 201 | bool initialized, _data_ready; 202 | int isCGATT(); 203 | bool HTTPINIT(int retries, int _delay); 204 | bool stopBearer(int retries, int _delay); 205 | bool startBearer(int retries, int _delay); 206 | void set_error_condition(int error_value); 207 | public: 208 | GPRSHTTP(Sim900* sim, int cid, char URL[]); 209 | bool init(int timeout = 120); 210 | bool setParam(char* param, String value); 211 | bool setParam(char* param, char* value); 212 | bool setParam(char* param, uint32_t value); 213 | 214 | 215 | bool post_init(uint32_t content_length); 216 | 217 | //If the response from the server does not have a Content-Length header 218 | //then length will always be zero. 219 | bool post(int &cid, int &HTTP_CODE, int32_t &length); 220 | int init_retrieve(); 221 | int get_error_condition(); 222 | bool terminate(); 223 | 224 | size_t read(char* buf, int length); 225 | size_t read(byte* buf, int length); 226 | virtual size_t write(uint8_t byte); 227 | virtual int read(); 228 | virtual int available(); 229 | virtual void flush(); 230 | virtual int peek(); 231 | using Print::write; 232 | 233 | }; 234 | 235 | #endif 236 | -------------------------------------------------------------------------------- /examples/GPRSHTTPPost/GPRSHTTPPost.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Sim900 is an Arduino library for working with the Sim900 GRPS Shield 3 | Copyright (C) 2012 Nigel Bajema 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License 7 | as published by the Free Software Foundation; either version 2 8 | of the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | */ 19 | 20 | #include 21 | #include 22 | 23 | 24 | CONN settings; 25 | // pins 10, and 11 are serial rx and tx pins for the modem 26 | // pin 9 is the power toggle pin 27 | // analog pin 8 is the GRPS power status pin 28 | Sim900 modem(new SoftwareSerial(10, 11), 19200, 9, 8, VARIANT_2); 29 | char url[] = "www.example.com"; 30 | 31 | void setup() 32 | { 33 | Serial.begin(19200); // the Serial port of Arduino baud rate. 34 | delay(2000); 35 | settings.cid = 1; 36 | settings.contype = "GPRS"; 37 | settings.apn = "internet"; 38 | test_modem(); 39 | 40 | } 41 | 42 | 43 | void loop() 44 | { 45 | } 46 | 47 | void test_modem() 48 | { 49 | int cid = 0, code = 0, error_code = 0; 50 | uint32_t length = 0; 51 | 52 | if(modem.powerUp()) 53 | { 54 | Serial.println("Powered Up") ; 55 | Serial.println("================================================="); 56 | int strength = -1, error_rate = -1; 57 | if(modem.getSignalQuality(strength, error_rate)) 58 | { 59 | Serial.print("Strength: "); 60 | Serial.print(strength); 61 | Serial.print(" Error Rate: "); 62 | Serial.println(error_rate); 63 | } 64 | GPRSHTTP* con = modem.createHTTPConnection(settings, url); 65 | if(con == NULL) 66 | { 67 | Serial.println(get_error_message(modem.get_error_condition())); 68 | return; 69 | } 70 | if(con->init() && con->post_init(14)) 71 | { 72 | con->println("Hello World!"); 73 | if(con->post(cid, code, length)) 74 | { 75 | Serial.print("HTTP CODE: "); 76 | Serial.println(code, DEC); 77 | Serial.print("Length: "); 78 | Serial.println(length, DEC); 79 | if(con->init_retrieve()) 80 | { 81 | length = length + 1; //Trigger an error condition. 82 | char data[length + 1]; //Ensure that this is a NULL Terminated String.... 83 | data[length] = '\0'; //.... 84 | if(con->read(data, length)) 85 | { 86 | Serial.println("Retrieved Data:"); 87 | Serial.println(data); 88 | } 89 | if(con->get_error_condition() == SIM900_ERROR_READ_LIMIT_EXCEEDED) 90 | { 91 | Serial.println("We tried to Read more characters from the connection than were available!"); 92 | } 93 | } 94 | } 95 | } 96 | con->terminate(); 97 | delete con; 98 | Serial.println("------------------------------------------------"); 99 | }else 100 | { 101 | Serial.println("Powering up modem failed !"); 102 | } 103 | modem.powerDown(); 104 | } 105 | --------------------------------------------------------------------------------