a library to use GPRS like ethernet or wifi, which makes it possible to connect to the internet with your GPRS module

Dependencies:   BufferedSerial

Dependents:   ThinkSpeak_Test roam_v1 roam_v2 finalv3

Fork of GPRSInterface by wei zou

GPRS/GPRS.cpp

Committer:
yihui
Date:
2015-04-03
Revision:
14:3c6454f033ac
Parent:
13:379ce1d51b88

File content as of revision 14:3c6454f033ac:

/*
  GPRS.cpp
  2014 Copyright (c) Seeed Technology Inc.  All right reserved.

  Author:lawliet zou(lawliet.zou@gmail.com)
  2014-2-24

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "mbed.h"
#include "GPRS.h"

#define DEBUG

#ifdef DEBUG
#include "USBSerial.h"
extern USBSerial pc;
#define LOG(args...)        pc.printf(args)
#else
#define LOG(args...)
#endif


GPRS* GPRS::inst;

GPRS::GPRS(PinName tx, PinName rx, const char* apn, const char* userName, const char* passWord) : Modem(tx,rx)
{
    inst = this;
    _apn = apn;
    _userName = userName;
    _passWord = passWord;
    socketID = -1;
    
    connected = false;
    recv_bytes = 0;
}



bool GPRS::join()
{
    char ip_addr_buf[32];
    
    //Select multiple connection
    command("AT+CIPMUX=1\r\n");
    
    // Set APN
    command("AT+CSTT=\"%s\",\"%s\",\"%s\"\r\n",_apn,_userName,_passWord);

    // Brings up wireless connection
    command("AT+CIICR\r\n");

    // Get local IP address
    printf("AT+CIFSR\r\n");
    
    readline(ip_addr_buf, sizeof(ip_addr_buf));   // read echo

    if (readline(ip_addr_buf, sizeof(ip_addr_buf)) <= 0) {
        LOG("failed to join network\r\n");
        return false;
    }
    
    int a, b, c, d;
    if (sscanf(ip_addr_buf, "%d.%d.%d.%d", &a, &b, &c, &d) != 4) {
        LOG("failed to get ip, r(%s)\r\n", ip_addr_buf);
        return false;
    }
    
    _ip = (a << 24) + (b << 16) + (c << 8) + d;

    return true;
}

bool GPRS::setProtocol(int socket, Protocol p)
{
    if (socket < 0 || socket > MAX_SOCK_NUM-1) {
        return false;
    }
    //ToDo: setProtocol
    return true;
}

bool GPRS::connect(int socket, Protocol ptl, const char * host, int port, int timeout)
{
    const char *protocol;
    if (socket < 0 || socket > MAX_SOCK_NUM-1) {
        return false;
    }
    if(ptl == TCP) {
        protocol = "TCP";
    } else if(ptl == UDP) {
        protocol = "UDP";
    } else {
        return false;
    }
    
    command("AT+CIPSTART=%d,\"%s\",\"%s\",%d\r\n", socket, protocol, host, port);
    
    char response[64] = {0,};
    if (readline(response, sizeof(response)) < 0) {
        LOG("wait for connection - timeout\r\n");
        return false;
    }
    
    if (strstr(response, "CONNECT OK") || strstr(response, "ALREADY CONNECT")) {
        connected = true;
        return true;
    } else {
        LOG("failed to connect (r:%s)\r\n", response);
        return false;
    }
}

bool GPRS::gethostbyname(const char* host, uint32_t* ip)
{
    int a, b, c, d;
    if (sscanf(host, "%d.%d.%d.%d", &a, &b, &c, &d) == 4) {
        *ip = (a << 24) + (b << 16) + (c << 8) + d;
        
        return true;
    }
    
    return false;
}

bool GPRS::disconnect()
{
    puts("AT+CIPSHUT\r\n");
    connected = false;
    return true;
}

bool GPRS::is_connected(int socket)
{
    static uint32_t last = 0;
    if (((uint32_t)us_ticker_read() - last) > 60000000) {
        last = us_ticker_read();
        
        flush();
        printf("AT+CIPSTATUS=%d\r\n", socket);
        
        connected = false;
        
        char response[80];
        readline(response, sizeof(response));   // echo, ignore
        if (readline(response, sizeof(response)) > 0) {
            if (strstr(response, "CONNECTED")) {
                connected = true;
            }
            
            readline(response, sizeof(response)); // ok
        }
    }
    
    return connected;
}

void GPRS::reset()
{

}

bool GPRS::close(int socket)
{
    if (socket < 0 || socket > (MAX_SOCK_NUM - 1)) {
        return false;
    }
    
    printf("AT+CIPCLOSE=%d\r\n", socket);
    connected = false;
    return true;
}

int GPRS::sock_send(int socket, const char * data, int len)
{
    if (socket < 0 || socket > MAX_SOCK_NUM-1 || len <= 0) {
        return -1;
    }

    char response[64];

    flush();
    printf("AT+CIPSEND=%d,%d\r\n", socket, len);
    readline(response, sizeof(response));       // echo, ignore
    if (match("> ")) {
        connected = false;
        return -1;
    }
    
    write(data, len);
    
    // read echo data
    for (int i = 0; i < len; i++) {
        while (!readable()) {
        }
        char ch = getc();
    }
    
    readline(response, sizeof(response));
    
    // data received
    int sock;
    int bytes = 0;
    if (sscanf(response, "+RECEIVE,%d,%d:", &sock, &bytes) == 2) {
        while (bytes > 0) {
            if (readable()) {
                recv_buf[recv_bytes] = getc();
                recv_bytes++;
                bytes--;
            }
        }
        
        readline(response, sizeof(response));
    }
    
    if (strstr(response, "SEND OK")) {      // 0, SEND OK
        return len;
    }
    
    if (strstr(response, "CLOSED")) {
        connected = false;
    }
    return -1;
}

int GPRS::sock_recv(int socket, char* buf, int len)
{
    if (recv_bytes > 0) {
        if (len >= recv_bytes) {
            len = recv_bytes;
            memcpy(buf, recv_buf, recv_bytes);
            recv_bytes = 0;
        } else {
            memcpy(buf, recv_buf, len);
            recv_bytes -= len;
            memcpy(recv_buf, recv_buf + len, recv_bytes);
        }
        
        return len;
    }
    
    char response[32];
    if (readline(response, sizeof(response)) <= 0) {
        return -1;
    }
    
    if (strstr(response, "CLOSED")) {
        LOG("socket is closed, r(%s)\r\n", response);
        connected = false;
        
        return -1;
    }
    
    int sock;
    int bytes = 0;
    if (sscanf(response, "+RECEIVE,%d,%d:", &sock, &bytes) != 2) {
        LOG("unknow:%s\r\n", response);
        return -1;
    }
    
    int bytes_read = 0;
    while (bytes_read < bytes) {
        if (readable()) {
            buf[bytes_read] = getc();
            bytes_read++;
        }
    }
    
    return bytes;  
}

int GPRS::new_socket()
{
    socketID = 0; //we only support one socket.
    return socketID; 
}