|
| 1 | +#include "GSMDevice.hpp" |
| 2 | + |
| 3 | +using namespace std; |
| 4 | + |
| 5 | +GSMDevice::GSMDevice(){ //Instantiates a GSM device controlled using GPIO 4 (default, software pwr control) and /dev/ttyAMA0 for UART |
| 6 | + GSMDevice(DEFAULT_GPIO,DEFAULT_UART); |
| 7 | +} |
| 8 | + |
| 9 | +//WARNING: May take up to six seconds |
| 10 | +GSMDevice::GSMDevice(int gpio, string serial){ //Instantiates a GSM device controlled using a GPIO pin (given by GPIO parameter) and a UART port (given by serial){ |
| 11 | + gpionum = gpio; |
| 12 | + serialPort = serial; |
| 13 | + InitSerial(); |
| 14 | + InitGSMModule(); |
| 15 | + delay(3000); //Allow some time for the GSM module to connect to the network. |
| 16 | +} |
| 17 | + |
| 18 | +void GSMDevice::TogglePWR(){ |
| 19 | + //Toggles the power status of the GSM module. Turns it on if it is off and turns it off if it is on. |
| 20 | + //WARNING: Takes 2500 miliseconds to complete |
| 21 | + |
| 22 | + digitalWrite(gpionum, LOW); //Spec says that the adafruit FONA expects a 2000ms low pulse |
| 23 | + delay(2000); |
| 24 | + digitalWrite(gpionum, HIGH); |
| 25 | + delay(500); //Give the module some time to turn on, ensure that when |
| 26 | + //function returns the module is operational. |
| 27 | +} |
| 28 | + |
| 29 | +bool GSMDevice::Call(string num){ //Establishes a voice connection with a phone number. The function |
| 30 | + char *number = new char[num.length() + 1]; //will return when the voice connection is established. Note that |
| 31 | + strcpy(number, num.c_str()); //having a voice connection does not mean that both parties are |
| 32 | + char send[20]; //ready to exchange data. In fact, the sender should allow for some |
| 33 | + //time before transmitting so that the receiver can answer. |
| 34 | + |
| 35 | + if(strlen(number)>(sizeof(send)/sizeof(char))-(3+1)){ //If the number does not fit into the buffer, reject it, as |
| 36 | + if(OPENSTRATOS_GSM_DEBUG_){ //phone numbers (without C.C.) take 9 chars. |
| 37 | + printf("[!] Number too long. Aborting call\n"); |
| 38 | + } |
| 39 | + return false; |
| 40 | + } |
| 41 | + strncpy(send, "ATD", strlen("ATD")); //AT command preamble: ATD |
| 42 | + strncpy(send+3, number, strlen(number)); //Number to dial |
| 43 | + int length = strlen(send); |
| 44 | + send[length] = (char)0x3b;//ascii for semicolon //Semicolon ending command |
| 45 | + send[length+1] = (char)0x0;//terminate string with null byte |
| 46 | + bool success = SerialSendCompareResponse(send, "OK"); //Modem will reply OK if a voice connection was established. |
| 47 | + if(OPENSTRATOS_GSM_DEBUG_ && !success){ |
| 48 | + printf("[!] ATD+number+; did not reply OK\n"); |
| 49 | + } |
| 50 | + return success; |
| 51 | +} |
| 52 | + |
| 53 | +bool GSMDevice::AbortCall(){ //Aborts a phone call. No effect if not in a call. |
| 54 | + bool success = SerialSendCompareResponse("ATH","OK"); //Returns true if call aborted or if not in a call. |
| 55 | + if(OPENSTRATOS_GSM_DEBUG_ && !success){ //Expecting the modem to return OK. |
| 56 | + printf("[!] ATH did not reply OK\n"); |
| 57 | + } |
| 58 | + return success; |
| 59 | +} |
| 60 | + |
| 61 | +bool GSMDevice::SendSMS(string message, string n){ //Sends a short message to a phone number |
| 62 | + char *destnum = new char[n.length() + 1]; |
| 63 | + strcpy(destnum, n.c_str()); |
| 64 | + char *messagechar = new char[message.length() + 1]; |
| 65 | + strcpy(messagechar, message.c_str()); |
| 66 | + |
| 67 | + if (SerialSendCompareResponse("AT+CMGF=1", "OK")==false){ //Select SMS message format |
| 68 | + if(OPENSTRATOS_GSM_DEBUG_){ //Abort if the modem cannot be set to text mode. |
| 69 | + printf("[!] AT+CMFG=1 did not reply OK to SMS format selection\n"); |
| 70 | + } |
| 71 | + return false; |
| 72 | + } |
| 73 | + |
| 74 | + char send[30] = "AT+CMGS=\""; //SMS command preamble: AT+CMGS=" |
| 75 | + strncpy(send+9 , destnum, 19); //SMS destination (actual phone number) |
| 76 | + send[strlen(send)] = (char)0x22;//ascii for " (double quote) //SMS command termination: " |
| 77 | + |
| 78 | + if (!SerialSendCompareResponse(send, "> ")){ //Input prompt should be open and expecting text input |
| 79 | + if(OPENSTRATOS_GSM_DEBUG_){ |
| 80 | + printf("[!] Failed SMS attempt. SIM800L did not provide input prompt\n"); |
| 81 | + } |
| 82 | + return false; //If there is not any input prompt, abort. |
| 83 | + } |
| 84 | + |
| 85 | + serialPrintf(fdesc,messagechar); //Send message |
| 86 | + serialPrintf(fdesc,"\r\n"); //Return |
| 87 | + FlushSerialInput(); //Module will reply with "+CMGS<length>". Not interested in that, so flush. |
| 88 | + return true; //Message sent. |
| 89 | +} |
| 90 | + |
| 91 | +void GSMDevice::BroadcastGeolocation(string n){ //Tries to perform geolocation and sends coordinates to a phone number via SMS. |
| 92 | + //TODO |
| 93 | +} |
| 94 | + |
| 95 | +bool GSMDevice::CheckGSMModule(){ //Returns true if module is up and running, false if it is not. |
| 96 | + if(SerialSendCompareResponse("AT","OK")){ //Probe the SIM800L, see AT command reference for more info. |
| 97 | + return true; |
| 98 | + } |
| 99 | + return false; |
| 100 | +} |
| 101 | + |
| 102 | +bool GSMDevice::InitSerial(){ |
| 103 | + char *cstr = new char[serialPort.length() + 1]; |
| 104 | + strcpy(cstr, serialPort.c_str()); |
| 105 | + fdesc = serialOpen(cstr, UART_BAUDRATE); |
| 106 | + if(fdesc==-1){ //serialOpen returns a standard linux file descriptor. -1 means failed |
| 107 | + ;/*EXCEPTION: NO SERIAL PORT AVAILABLE*/ |
| 108 | + if(OPENSTRATOS_GSM_DEBUG_){ |
| 109 | + printf("[!] Serial port open error\n"); |
| 110 | + } |
| 111 | + return false; |
| 112 | + } |
| 113 | + return true; |
| 114 | +} |
| 115 | + |
| 116 | +bool GSMDevice::InitGSMModule(){ |
| 117 | + if (wiringPiSetup() == -1){ |
| 118 | + /*EXCEPTION: UNABLE TO ACCESS GPIOS*/; |
| 119 | + return false; |
| 120 | + } |
| 121 | + pinMode(gpionum, OUTPUT); //Set GPIO as digital output |
| 122 | + digitalWrite(gpionum, HIGH); //Set to high so that GSM module stays in standby until TogglePWR is called |
| 123 | + return true; |
| 124 | +} |
| 125 | + |
| 126 | +bool GSMDevice::SerialSendCompareResponse(char *send, char *expected){ |
| 127 | + SerialSendRead(send); //Send a string via serial. |
| 128 | + return (strcmp(serialin, expected) == 0); //Compare what got placed in serialin with the expected answer |
| 129 | +} |
| 130 | + |
| 131 | +uint16_t GSMDevice::SerialSendRead(char *send) { |
| 132 | + FlushSerialInput(); |
| 133 | + if(OPENSTRATOS_GSM_DEBUG_){ |
| 134 | + printf("[i] Sending: %s", send); |
| 135 | + } |
| 136 | + serialPrintf(fdesc, send); |
| 137 | + uint16_t readlength = SerialReadLine(); |
| 138 | + if(OPENSTRATOS_GSM_DEBUG_){ |
| 139 | + printf("[i] Received: %s\n", serialin); |
| 140 | + } |
| 141 | + return readlength; |
| 142 | +} |
| 143 | + |
| 144 | +void GSMDevice::FlushSerialInput() { |
| 145 | + serialFlush(fdesc); |
| 146 | +} |
| 147 | + |
| 148 | +uint16_t GSMDevice::SerialReadLine() { |
| 149 | + uint16_t i = 0; |
| 150 | + while(serialDataAvail(fdesc)&&i<254) { |
| 151 | + char c = serialGetchar(fdesc); |
| 152 | + serialin[i++] = c; |
| 153 | + } |
| 154 | + serialin[i] = 0x0; |
| 155 | + return i; |
| 156 | +} |
0 commit comments