for TwitterMbed
Fork of GSwifi_old by
GSwifi.cpp
- Committer:
- gsfan
- Date:
- 2012-12-26
- Revision:
- 22:9b077e2823ce
- Parent:
- 20:151b5a4fdd29
- Child:
- 23:a783c62c36d0
File content as of revision 22:9b077e2823ce:
/** * Gainspan wi-fi module library for mbed * Copyright (c) 2012 gsfan * Released under the MIT License: http://mbed.org/license/mit */ /** @file * @brief Gainspan wi-fi module library for mbed * GS1011MIC, GS1011MIP, GainSpan WiFi Breakout, etc. * module configuration: ATB=115200 */ #include "dbg.h" #include "mbed.h" #include "GSwifi.h" #include <ctype.h> #ifdef GS_UART_DIRECT #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) #define _gs_getc() LPC_UART1->RBR #define _gs_putc(c) while(!(LPC_UART1->LSR & (1<<5))); LPC_UART1->THR = c #elif defined(TARGET_LPC11U24) #define _gs_getc() LPC_USART->RBR #define _gs_putc(c) while(!(LPC_USART->LSR & (1<<5))); LPC_USART->THR = c #endif #else #define _gs_getc() _gs.getc() #define _gs_putc(c) _gs.putc(c) #endif GSwifi::GSwifi (PinName p_tx, PinName p_rx, int baud) : _gs(p_tx, p_rx), _buf_cmd(GS_CMD_SIZE) { _connect = false; _status = GSSTAT_READY; _escape = 0; _response = 1; _gs_mode = GSMODE_COMMAND; _gs.baud(baud); _gs.attach(this, &GSwifi::isr_recv, Serial::RxIrq); _rts = false; } GSwifi::GSwifi (PinName p_tx, PinName p_rx, PinName p_cts, PinName p_rts, int baud) : _gs(p_tx, p_rx), _buf_cmd(GS_CMD_SIZE) { _connect = false; _status = GSSTAT_READY; _escape = 0; _response = 1; _gs_mode = GSMODE_COMMAND; _gs.baud(baud); _gs.attach(this, &GSwifi::isr_recv, Serial::RxIrq); #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) if (p_cts == p12) { // CTS input (P0_17) LPC_UART1->MCR |= (1<<7); // CTSEN LPC_PINCON->PINSEL1 &= ~(3 << 2); LPC_PINCON->PINSEL1 |= (1 << 2); // UART CTS } if (p_rts == P0_22) { // RTS output (P0_22) LPC_UART1->MCR |= (1<<6); // RTSEN LPC_PINCON->PINSEL1 &= ~(3 << 12); LPC_PINCON->PINSEL1 |= (1 << 12); // UART RTS _rts = true; } else { _rts = false; } #elif defined(TARGET_LPC11U24) if (p_cts == p21) { // CTS input (P0_7) LPC_USART->MCR |= (1<<7); // CTSEN LPC_IOCON->PIO0_7 &= ~0x07; LPC_IOCON->PIO0_7 |= 0x01; // UART CTS } if (p_rts == p22) { // RTS output (P0_17) LPC_USART->MCR |= (1<<6); // RTSEN LPC_IOCON->PIO0_17 &= ~0x07; LPC_IOCON->PIO0_17 |= 0x01; // UART RTS _rts = true; } else { _rts = false; } #endif } // uart interrupt void GSwifi::isr_recv () { static int len, mode; static char tmp[20]; char flg, dat; #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) flg = LPC_UART1->LSR; #elif defined(TARGET_LPC11U24) flg = LPC_USART->LSR; #endif dat = _gs_getc(); if (flg & ((1 << 7)|(1 << 3)|(1 << 4))) return; // DBG("%02x_", dat); switch (_gs_mode) { case GSMODE_COMMAND: // command responce if (_escape) { // esc switch (dat) { case 'O': DBG("ok\r\n"); _gs_ok = 1; break; case 'F': DBG("failure\r\n"); _gs_failure = 1; break; case 'S': DBG("GSMODE_DATA_RX\r\n"); _gs_mode = GSMODE_DATA_RX; mode = 0; break; case 'u': DBG("GSMODE_DATA_RXUDP\r\n"); _gs_mode = GSMODE_DATA_RXUDP; mode = 0; break; case 'Z': case 'H': DBG("GSMODE_DATA_RX_BULK\r\n"); _gs_mode = GSMODE_DATA_RX_BULK; mode = 0; break; case 'y': DBG("GSMODE_DATA_RXUDP_BULK\r\n"); _gs_mode = GSMODE_DATA_RXUDP_BULK; mode = 0; break; default: DBG("unknown [ESC] %02x\r\n", dat); break; } _escape = 0; } else { if (dat == 0x1b) { _escape = 1; } else if (dat != '\r') { // command _buf_cmd.put(dat); if (dat == '\n') { _gs_enter ++; if (!_response && _connect) poll_cmd(); } } } break; case GSMODE_DATA_RX: case GSMODE_DATA_RXUDP: if (mode == 0) { // cid _cid = x2i(dat); _gs_sock[_cid].received = 0; mode ++; if (_gs_mode == GSMODE_DATA_RX) { mode = 3; } len = 0; } else if (mode == 1) { // ip if ((dat < '0' || dat > '9') && dat != '.') { int ip1, ip2, ip3, ip4; tmp[len] = 0; sscanf(tmp, "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4); _from.setIp(IpAddr(ip1, ip2, ip3, ip4)); mode ++; len = 0; break; } tmp[len] = dat; len ++; } else if (mode == 2) { // port if (dat < '0' || dat > '9') { tmp[len] = 0; _from.setPort(atoi(tmp)); mode ++; len = 0; break; } tmp[len] = dat; len ++; } else if (_escape) { // esc switch (dat) { case 'E': DBG("recv ascii %d\r\n", _cid); _gs_sock[_cid].received = 1; _gs_mode = GSMODE_COMMAND; // recv interrupt if (_gs_sock[_cid].protocol == GSPROT_HTTPGET && _gs_sock[_cid].onGsReceive != NULL) { _gs_sock[_cid].onGsReceive(_cid, _gs_sock[_cid].data->use()); _gs_sock[_cid].received = 0; } break; default: DBG("unknown <ESC> %02x\r\n", dat); break; } _escape = 0; } else { if (dat == 0x1b) { _escape = 1; } else { // data _gs_sock[_cid].data->put(dat); len ++; if (len < GS_DATA_SIZE && _gs_sock[_cid].data->available() == 0) { // buffer full if (_gs_sock[_cid].onGsReceive != NULL) { _gs_sock[_cid].onGsReceive(_cid, _gs_sock[_cid].data->use()); } } } } break; case GSMODE_DATA_RX_BULK: case GSMODE_DATA_RXUDP_BULK: // DBG("%c", dat); if (mode == 0) { // cid _cid = x2i(dat); _gs_sock[_cid].received = 0; mode ++; if (_gs_mode == GSMODE_DATA_RX_BULK) { mode = 3; } len = 0; } else if (mode == 1) { // ip if ((dat < '0' || dat > '9') && dat != '.') { int ip1, ip2, ip3, ip4; tmp[len] = 0; sscanf(tmp, "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4); _from.setIp(IpAddr(ip1, ip2, ip3, ip4)); mode ++; len = 0; break; } tmp[len] = dat; len ++; } else if (mode == 2) { // port if (dat < '0' || dat > '9') { tmp[len] = 0; _from.setPort(atoi(tmp)); mode ++; len = 0; break; } tmp[len] = dat; len ++; } else if (mode == 3) { // length tmp[len] = dat; len ++; if (len >= 4) { tmp[len] = 0; len = atoi(tmp); mode ++; break; } } else if (mode == 4) { // data if (_gs_sock[_cid].data != NULL) { _gs_sock[_cid].data->put(dat); } len --; if (len && _gs_sock[_cid].data->available() == 0) { // buffer full if (_gs_sock[_cid].onGsReceive != NULL) { _gs_sock[_cid].onGsReceive(_cid, _gs_sock[_cid].data->use()); } } if (len == 0) { DBG("recv binary %d\r\n", _cid); _gs_sock[_cid].received = 1; _escape = 0; _gs_mode = GSMODE_COMMAND; // recv interrupt if (_gs_sock[_cid].protocol == GSPROT_HTTPGET && _gs_sock[_cid].onGsReceive != NULL) { _gs_sock[_cid].onGsReceive(_cid, _gs_sock[_cid].data->use()); _gs_sock[_cid].received = 0; } } } break; } } int GSwifi::command (const char *cmd, GSRESPONCE res, int timeout) { int i, r = 0; if (! cmd) { // dummy CR+LF _gs.printf("\r\n"); for (i = 0; i < 10; i ++) { wait_ms(10); poll_cmd(); _buf_cmd.clear(); } return 0; } _response = 1; _buf_cmd.clear(); _gs_ok = 0; _gs_failure = 0; _gs_enter = 0; for (i = 0; i < strlen(cmd); i ++) { _gs_putc(cmd[i]); } _gs_putc('\r'); _gs_putc('\n'); DBG("command: %s\r\n", cmd); if (strlen(cmd) == 0) return 0; wait_ms(10); if (timeout) { r = cmdResponse(res, timeout); } _response = 0; return r; } int GSwifi::cmdResponse (GSRESPONCE res, int ms) { int i, n = 0, flg = 0; char buf[GS_CMD_SIZE]; Timer timeout; timeout.start(); for (;;) { // recv response i = 0; while (i < sizeof(buf)) { if (_buf_cmd.use()) { _buf_cmd.get(&buf[i]); if (buf[i] == '\n') { break; } i ++; } if (timeout.read_ms() > ms) { timeout.stop(); DBG("timeout\r\n"); return -1; } } _gs_enter = 0; if (i == 0) continue; buf[i] = 0; DBG("response: %s\r\n", buf); timeout.stop(); if (strcmp(buf, "OK") == 0) { _gs_ok = 1; } else if (strncmp(buf, "ERROR", 5) == 0) { _gs_failure = 1; } switch(res) { case GSRES_NORMAL: flg = 1; break; case GSRES_WPS: if (n == 0 && strncmp(buf, "SSID", 4) == 0) { n ++; } else if (n == 1 && strncmp(buf, "CHANNEL", 7) == 0) { n ++; } else if (n == 2 && strncmp(buf, "PASSPHRASE", 10) == 0) { n ++; flg = 1; } break; case GSRES_CONNECT: if (strncmp(buf, "CONNECT", 7) == 0) { _cid = x2i(buf[8]); flg = 1; } break; case GSRES_DHCP: if (n == 0 && strstr(buf, "SubNet") && strstr(buf, "Gateway")) { n ++; } else if (n == 1) { int ip1, ip2, ip3, ip4; char *tmp = buf + 1; sscanf(tmp, "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4); _ipaddr = IpAddr(ip1, ip2, ip3, ip4); tmp = strstr(tmp, ":") + 2; sscanf(tmp, "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4); _netmask = IpAddr(ip1, ip2, ip3, ip4); tmp = strstr(tmp, ":") + 2; sscanf(tmp, "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4); _gateway = IpAddr(ip1, ip2, ip3, ip4); n ++; flg = 1; } break; case GSRES_MACADDRESS: if (buf[2] == ':' && buf[5] == ':') { int mac1, mac2, mac3, mac4, mac5, mac6; sscanf(buf, "%x:%x:%x:%x:%x:%x", &mac1, &mac2, &mac3, &mac4, &mac5, &mac6); _mac[0] = mac1; _mac[1] = mac2; _mac[2] = mac3; _mac[3] = mac4; _mac[4] = mac5; _mac[5] = mac6; flg = 1; } break; case GSRES_DNSLOOKUP: if (strncmp(buf, "IP:", 3) == 0) { int ip1, ip2, ip3, ip4; sscanf(&buf[3], "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4); _resolv = IpAddr(ip1, ip2, ip3, ip4); flg = 1; } break; case GSRES_HTTP: if (buf[0] >= '0' && buf[0] <= 'F') { _cid = x2i(buf[0]); flg = 1; } break; case GSRES_RSSI: if (buf[0] == '-' || (buf[0] >= '0' && buf[0] <= '9')) { _rssi = atoi(buf); flg = 1; } break; case GSRES_TIME: if (buf[0] >= '0' && buf[0] <= '9') { int year, month, day, hour, min, sec; struct tm t; sscanf(buf, "%d/%d/%d,%d:%d:%d", &day, &month, &year, &hour, &min, &sec); t.tm_sec = sec; t.tm_min = min; t.tm_hour = hour; t.tm_mday = day; t.tm_mon = month - 1; t.tm_year = year - 1900; _time = mktime(&t); flg = 1; } break; } if ((flg && _gs_ok) || _gs_failure) break; timeout.reset(); timeout.start(); } if (_gs_failure || flg == 0) { return -1; } else { return 0; } } int GSwifi::connect (GSSECURITY sec, const char *ssid, const char *pass, int dhcp) { int r; char cmd[GS_CMD_SIZE]; if (_connect || _status != GSSTAT_READY) return -1; command(NULL, GSRES_NORMAL); if (command("ATE0", GSRES_NORMAL)) return -1; if (_rts) { command("AT&K0", GSRES_NORMAL); command("AT&R1", GSRES_NORMAL); } command("AT+NMAC=?", GSRES_MACADDRESS); #ifdef GS_BULK command("AT+BDATA=1", GSRES_NORMAL); #endif disconnect(); command("AT+WREGDOMAIN=" GS_WREGDOMAIN, GSRES_NORMAL); command("AT+WM=0", GSRES_NORMAL); // infrastructure wait_ms(100); if (dhcp && sec != GSSEC_WPS_BUTTON) { command("AT+NDHCP=1", GSRES_NORMAL); } else { command("AT+NDHCP=0", GSRES_NORMAL); } switch (sec) { case GSSEC_NONE: case GSSEC_OPEN: case GSSEC_WEP: sprintf(cmd, "AT+WAUTH=%d", sec); command(cmd, GSRES_NORMAL); if (sec != GSSEC_NONE) { sprintf(cmd, "AT+WWEP1=%s", pass); command(cmd, GSRES_NORMAL); wait_ms(100); } sprintf(cmd, "AT+WA=%s", ssid); r = command(cmd, GSRES_DHCP, GS_TIMEOUT2); if (r) { DBG("retry\r\n"); r = command(cmd, GSRES_DHCP, GS_TIMEOUT2); } break; case GSSEC_WPA_PSK: case GSSEC_WPA2_PSK: command("AT+WAUTH=0", GSRES_NORMAL); // sprintf(cmd, "AT+WWPA=%s", pass); // command(cmd, GSRES_NORMAL); sprintf(cmd, "AT+WPAPSK=%s,%s", ssid, pass); command(cmd, GSRES_NORMAL, GS_TIMEOUT2); wait_ms(100); sprintf(cmd, "AT+WA=%s", ssid); r = command(cmd, GSRES_DHCP, GS_TIMEOUT2); if (r) { DBG("retry\r\n"); r = command(cmd, GSRES_DHCP, GS_TIMEOUT2); } break; case GSSEC_WPS_BUTTON: command("AT+WAUTH=0", GSRES_NORMAL); r = command("AT+WWPS=1", GSRES_WPS, GS_TIMEOUT2); if (r) break; if (dhcp) { r = command("AT+NDHCP=1", GSRES_DHCP, GS_TIMEOUT2); } break; default: DBG("Can't use security\r\n"); r = -1; break; } if (r == 0 && !dhcp) { sprintf(cmd, "AT+DNSSET=%d.%d.%d.%d", _gateway[0], _gateway[1], _gateway[2], _gateway[3]); command(cmd, GSRES_NORMAL); } if (r == 0) _connect = true; return r; } int GSwifi::adhock (GSSECURITY sec, const char *ssid, const char *pass, IpAddr ipaddr, IpAddr netmask) { int r; char cmd[GS_CMD_SIZE]; if (_connect || _status != GSSTAT_READY) return -1; command(NULL, GSRES_NORMAL); if (command("ATE0", GSRES_NORMAL)) return -1; if (_rts) { command("AT&K0", GSRES_NORMAL); command("AT&R1", GSRES_NORMAL); } disconnect(); command("AT+NMAC=?", GSRES_MACADDRESS); #ifdef GS_BULK command("AT+BDATA=1", GSRES_NORMAL); #endif command("AT+WREGDOMAIN=" GS_WREGDOMAIN, GSRES_NORMAL); command("AT+WM=1", GSRES_NORMAL); // adhock wait_ms(100); command("AT+NDHCP=0", GSRES_NORMAL); setAddress(ipaddr, netmask, ipaddr, ipaddr); switch (sec) { case GSSEC_NONE: case GSSEC_OPEN: case GSSEC_WEP: sprintf(cmd, "AT+WAUTH=%d", sec); command(cmd, GSRES_NORMAL); if (sec != GSSEC_NONE) { sprintf(cmd, "AT+WWEP1=%s", pass); command(cmd, GSRES_NORMAL); wait_ms(100); } sprintf(cmd, "AT+WA=%s", ssid); r = command(cmd, GSRES_NORMAL, GS_TIMEOUT2); break; default: DBG("Can't use security\r\n"); r = -1; break; } if (r == 0) _connect = true; return r; } int GSwifi::limitedap (GSSECURITY sec, const char *ssid, const char *pass, IpAddr ipaddr, IpAddr netmask, char *dns) { int r; char cmd[GS_CMD_SIZE]; if (_connect || _status != GSSTAT_READY) return -1; command(NULL, GSRES_NORMAL); if (command("ATE0", GSRES_NORMAL)) return -1; if (_rts) { command("AT&K0", GSRES_NORMAL); command("AT&R1", GSRES_NORMAL); } disconnect(); command("AT+NMAC=?", GSRES_MACADDRESS); #ifdef GS_BULK command("AT+BDATA=1", GSRES_NORMAL); #endif command("AT+WREGDOMAIN=" GS_WREGDOMAIN, GSRES_NORMAL); command("AT+WM=2", GSRES_NORMAL); // limited ap wait_ms(1000); command("AT+NDHCP=0", GSRES_NORMAL); setAddress(ipaddr, netmask, ipaddr, ipaddr); if (command("AT+DHCPSRVR=1", GSRES_NORMAL)) return -1; if (dns) { sprintf(cmd, "AT+DNS=1,%s", dns); } else { strcpy(cmd, "AT+DNS=1," GS_DNSNAME); } if (command(cmd, GSRES_NORMAL)) return -1; switch (sec) { case GSSEC_NONE: case GSSEC_OPEN: case GSSEC_WEP: sprintf(cmd, "AT+WAUTH=%d", sec); command(cmd, GSRES_NORMAL); if (sec != GSSEC_NONE) { sprintf(cmd, "AT+WWEP1=%s", pass); command(cmd, GSRES_NORMAL); wait_ms(100); } sprintf(cmd, "AT+WA=%s", ssid); r = command(cmd, GSRES_NORMAL, GS_TIMEOUT2); break; default: DBG("Can't use security\r\n"); r = -1; break; } if (r == 0) _connect = true; return r; } int GSwifi::disconnect () { int i; _connect = false; for (i = 0; i < 16; i ++) { _gs_sock[i].connect = false; } command("AT+NCLOSEALL", GSRES_NORMAL); command("AT+WD", GSRES_NORMAL); command("AT+NDHCP=0", GSRES_NORMAL); wait_ms(100); return 0; } int GSwifi::setAddress () { if (command("AT+NDHCP=1", GSRES_DHCP), GS_TIMEOUT2) return -1; if (_ipaddr.isNull()) return -1; return 0; } int GSwifi::setAddress (IpAddr ipaddr, IpAddr netmask, IpAddr gateway, IpAddr nameserver) { int r; char cmd[GS_CMD_SIZE]; command("AT+NDHCP=0", GSRES_NORMAL); wait_ms(100); sprintf(cmd, "AT+NSET=%d.%d.%d.%d,%d.%d.%d.%d,%d.%d.%d.%d", ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3], netmask[0], netmask[1], netmask[2], netmask[3], gateway[0], gateway[1], gateway[2], gateway[3]); r = command(cmd, GSRES_NORMAL); if (r) return -1; _ipaddr = ipaddr; _netmask = netmask; _gateway = gateway; if (ipaddr != nameserver) { sprintf(cmd, "AT+DNSSET=%d.%d.%d.%d", nameserver[0], nameserver[1], nameserver[2], nameserver[3]); r = command(cmd, GSRES_NORMAL); } return r; } int GSwifi::getAddress (IpAddr &ipaddr, IpAddr &netmask, IpAddr &gateway, IpAddr &nameserver) { ipaddr = _ipaddr; netmask = _netmask; gateway = _gateway; nameserver = _nameserver; return 0; } int GSwifi::getHostByName (const char* name, IpAddr &addr) { char cmd[GS_CMD_SIZE]; if (! _connect || _status != GSSTAT_READY) return -1; sprintf(cmd, "AT+DNSLOOKUP=%s", name); if (command(cmd, GSRES_DNSLOOKUP)) return -1; addr = _resolv; return 0; } int GSwifi::getHostByName (Host &host) { char cmd[GS_CMD_SIZE]; if (! _connect || _status != GSSTAT_READY) return -1; sprintf(cmd, "AT+DNSLOOKUP=%s", host.getName()); if (command(cmd, GSRES_DNSLOOKUP)) return -1; host.setIp(_resolv); return 0; } int GSwifi::setRFPower (int power) { char cmd[GS_CMD_SIZE]; if (power < 0 || power > 7) return -1; sprintf(cmd, "AT+WP=%d", power); return command(cmd, GSRES_NORMAL); } int GSwifi::powerSave (int active, int save) { char cmd[GS_CMD_SIZE]; if (_status != GSSTAT_READY) return -1; sprintf(cmd, "AT+WRXACTIVE=%d", active); command(cmd, GSRES_NORMAL); sprintf(cmd, "AT+WRXPS=%d", save); return command(cmd, GSRES_NORMAL); } int GSwifi::standby (int msec) { char cmd[GS_CMD_SIZE]; if (_status != GSSTAT_READY && _status != GSSTAT_WAKEUP) return -1; if (_status != GSSTAT_WAKEUP) { command("AT+WRXACTIVE=0", GSRES_NORMAL); command("AT+STORENWCONN", GSRES_NORMAL); } else { command("ATE0", GSRES_NORMAL); if (_rts) { command("AT&K0", GSRES_NORMAL); command("AT&R1", GSRES_NORMAL); } } _status = GSSTAT_STANDBY; sprintf(cmd, "AT+PSSTBY=%d,0,0,0", msec); // go standby return command(cmd, GSRES_NORMAL, 0); } int GSwifi::wakeup () { if (_status == GSSTAT_WAKEUP) { _status = GSSTAT_READY; command("ATE0", GSRES_NORMAL); if (_rts) { command("AT&K0", GSRES_NORMAL); command("AT&R1", GSRES_NORMAL); } #ifdef GS_BULK command("AT+BDATA=1", GSRES_NORMAL); #endif command("AT+RESTORENWCONN", GSRES_NORMAL); wait_ms(100); return command("AT+WRXACTIVE=1", GSRES_NORMAL); } else if (_status == GSSTAT_DEEPSLEEP) { _status = GSSTAT_READY; return command("AT", GSRES_NORMAL); } return -1; } int GSwifi::deepSleep () { if (_status != GSSTAT_READY) return -1; _status = GSSTAT_DEEPSLEEP; return command("AT+PSDPSLEEP", GSRES_NORMAL, 0); // go deep sleep } bool GSwifi::isConnected () { return _connect; } GSSTATUS GSwifi::getStatus () { return _status; } int GSwifi::getRssi () { if (command("AT+WRSSI=?", GSRES_RSSI)) { return 0; } return _rssi; } int GSwifi::ntpdate (Host host, int sec) { char cmd[GS_CMD_SIZE]; if (! _connect || _status != GSSTAT_READY) return -1; if (host.getIp().isNull()) { if (getHostByName(host)) { if (getHostByName(host)) return -1; } } if (sec) { sprintf(cmd, "AT+NTIMESYNC=1,%d.%d.%d.%d,%d,1,%d", host.getIp()[0], host.getIp()[1], host.getIp()[2], host.getIp()[3], GS_TIMEOUT / 1000, sec); } else { sprintf(cmd, "AT+NTIMESYNC=1,%d.%d.%d.%d,%d,0", host.getIp()[0], host.getIp()[1], host.getIp()[2], host.getIp()[3], GS_TIMEOUT / 1000); } return command(cmd, GSRES_NORMAL); } int GSwifi::setTime (time_t time) { char cmd[GS_CMD_SIZE]; struct tm *t; if (_status != GSSTAT_READY) return -1; t = localtime(&time); sprintf(cmd, "AT+SETTIME=%d/%d/%d,%d:%d:%d", t->tm_mday, t->tm_mon + 1, t->tm_year + 1900, t->tm_hour, t->tm_min, t->tm_sec); return command(cmd, GSRES_NORMAL); } time_t GSwifi::getTime () { if (command("AT+GETTIME=?", GSRES_TIME)) { return 0; } return _time; } int GSwifi::gpioOut (int port, int out) { char cmd[GS_CMD_SIZE]; if (_status != GSSTAT_READY) return -1; sprintf(cmd, "AT+DGPIO=%d,%d", port, out); return command(cmd, GSRES_NORMAL); } void GSwifi::poll_cmd () { int i; while (_gs_enter) { // received "\n" char buf[GS_CMD_SIZE]; wait_ms(10); _gs_enter --; i = 0; while (_buf_cmd.use() && i < sizeof(buf)) { _buf_cmd.get(&buf[i]); if (buf[i] == '\n') { break; } i ++; } buf[i] = 0; DBG("poll: %s\r\n", buf); if (i == 0) { } else if (strncmp(buf, "CONNECT", 7) == 0 && buf[8] >= '0' && buf[8] <= 'F') { int cid = x2i(buf[8]); if (_gs_sock[cid].type == GSTYPE_SERVER) { int acid, ip1, ip2, ip3, ip4; char *tmp = buf + 12; acid = x2i(buf[10]); DBG("connect %d -> %d\r\n", cid, acid); newSock(acid, _gs_sock[cid].type, _gs_sock[cid].protocol, _gs_sock[cid].onGsReceive); _gs_sock[acid].lcid = cid; sscanf(tmp, "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4); _gs_sock[acid].host.setIp(IpAddr(ip1, ip2, ip3, ip4)); tmp = strstr(tmp, " ") + 1; _gs_sock[acid].host.setPort(atoi(tmp)); #ifdef GS_USE_HTTPD if (_gs_sock[acid].protocol == GSPROT_HTTPD) { poll_httpd(acid, 0); } else #endif if (_gs_sock[acid].onGsReceive != NULL) { _gs_sock[acid].onGsReceive(acid, 0); // event connected } } } else if (strncmp(buf, "DISCONNECT", 10) == 0) { int cid = x2i(buf[11]); DBG("disconnect %d\r\n", cid); _gs_sock[cid].connect = false; #ifdef GS_USE_HTTPD if (_gs_sock[cid].protocol == GSPROT_HTTPD) { poll_httpd(cid, 0); } else #endif if (_gs_sock[cid].onGsReceive != NULL) { _gs_sock[cid].onGsReceive(cid, 0); // event disconnected } } else if (strncmp(buf, "DISASSOCIATED", 13) == 0 || strncmp(buf, "Disassociated", 13) == 0 || strncmp(buf, "Disassociation Event", 20) == 0 || strncmp(buf, "UnExpected Warm Boot", 20) == 0) { _connect = false; for (i = 0; i < 16; i ++) { _gs_sock[i].connect = false; } } else if (strncmp(buf, "Out of StandBy-Timer", 20) == 0 || strncmp(buf, "Out of StandBy-Alarm", 20) == 0) { // if (_status == GSSTAT_STANDBY) { _status = GSSTAT_WAKEUP; // } } else if (strncmp(buf, "Out of Deep Sleep", 17) == 0 ) { // if (_status == GSSTAT_DEEPSLEEP) { _status = GSSTAT_READY; // } } else if (strncmp(buf, "Out of", 6) == 0) { } DBG("status: %d\r\n", _status); } } void GSwifi::poll () { int i, j; poll_cmd(); for (i = 0; i < 16; i ++) { // if (_gs_sock[i].connect && _gs_sock[i].received) { if (_gs_sock[i].received && _gs_sock[i].data->use()) { // recv interrupt _gs_sock[i].received = 0; #ifdef GS_USE_HTTPD if (_gs_sock[i].protocol == GSPROT_HTTPD) { for (j = 0; j < 1500 / GS_DATA_SIZE + 1; j ++) { if (! _gs_sock[i].connect || ! _gs_sock[i].data->use()) break; poll_httpd(i, _gs_sock[i].data->use()); } } else #endif if (_gs_sock[i].onGsReceive != NULL) { for (j = 0; j < 1500 / GS_DATA_SIZE + 1; j ++) { if (! _gs_sock[i].connect || ! _gs_sock[i].data->use()) break; _gs_sock[i].onGsReceive(i, _gs_sock[i].data->use()); } } } } } void GSwifi::newSock (int cid, GSTYPE type, GSPROTOCOL pro, onGsReceiveFunc ponGsReceive) { _gs_sock[cid].type = type; _gs_sock[cid].protocol = pro; _gs_sock[cid].connect = true; if (_gs_sock[cid].data == NULL) { _gs_sock[cid].data = new RingBuffer(GS_DATA_SIZE); } else { _gs_sock[cid].data->clear(); } _gs_sock[cid].lcid = 0; _gs_sock[cid].received = 0; _gs_sock[cid].onGsReceive = ponGsReceive; } int GSwifi::open (Host &host, GSPROTOCOL pro, onGsReceiveFunc ponGsReceive) { char cmd[GS_CMD_SIZE]; if (! _connect || _status != GSSTAT_READY) return -1; if (host.getIp().isNull() || host.getPort() == 0) { return -1; } if (pro == GSPROT_UDP) { sprintf(cmd, "AT+NCUDP=%d.%d.%d.%d,%d", host.getIp()[0], host.getIp()[1], host.getIp()[2], host.getIp()[3], host.getPort()); } else { sprintf(cmd, "AT+NCTCP=%d.%d.%d.%d,%d", host.getIp()[0], host.getIp()[1], host.getIp()[2], host.getIp()[3], host.getPort()); } if (command(cmd, GSRES_CONNECT)) return -1; newSock(_cid, GSTYPE_CLIENT, pro, ponGsReceive); return _cid; } int GSwifi::listen (int port, GSPROTOCOL pro, onGsReceiveFunc ponGsReceive) { char cmd[GS_CMD_SIZE]; if (! _connect || _status != GSSTAT_READY) return -1; if (port == 0) { return -1; } if (pro == GSPROT_UDP) { sprintf(cmd, "AT+NSUDP=%d", port); } else { sprintf(cmd, "AT+NSTCP=%d", port); } if (command(cmd, GSRES_CONNECT)) return -1; newSock(_cid, GSTYPE_SERVER, pro, ponGsReceive); return _cid; } int GSwifi::close (int cid) { char cmd[GS_CMD_SIZE]; if (! _gs_sock[cid].connect) return -1; _gs_sock[cid].connect = false; delete _gs_sock[cid].data; _gs_sock[cid].data = NULL; sprintf(cmd, "AT+NCLOSE=%X", cid); return command(cmd, GSRES_NORMAL); } int GSwifi::send (int cid, const char *buf, int len) { int i; Timer timeout; if (! _gs_sock[cid].connect) return -1; if ((_gs_sock[cid].protocol == GSPROT_TCP) || (_gs_sock[cid].protocol == GSPROT_UDP && _gs_sock[cid].type == GSTYPE_CLIENT) || (_gs_sock[cid].protocol == GSPROT_HTTPD)) { // TCP Client, TCP Server, UDP Client _gs_ok = 0; _gs_failure = 0; #ifdef GS_BULK _gs.printf("\x1bZ%X%04d", cid, len); for (i = 0; i < len; i ++) { _gs_putc(buf[i]); // DBG("%c", buf[i]); } #else _gs.printf("\x1bS%X", cid); for (i = 0; i < len; i ++) { if (buf[i] >= 0x20 && buf[i] < 0x7f) { _gs_putc(buf[i]); // DBG("%c", buf[i]); } } _gs_putc(0x1b); _gs_putc('E'); #endif } else { return -1; } timeout.start(); while (!_gs_ok && !_gs_failure && timeout.read_ms() < GS_TIMEOUT); return _gs_ok == 1 ? 0 : -1; } int GSwifi::send (int cid, const char *buf, int len, Host &host) { int i; Timer timeout; if (! _gs_sock[cid].connect) return -1; if ((_gs_sock[cid].protocol == GSPROT_UDP && _gs_sock[cid].type == GSTYPE_SERVER)) { // UDP Server _gs_ok = 0; _gs_failure = 0; #ifdef GS_BULK _gs.printf("\x1bY%X", cid); _gs.printf("%d.%d.%d.%d:%d:", host.getIp()[0], host.getIp()[1], host.getIp()[2], host.getIp()[3], host.getPort()); _gs.printf("%04d", len); for (i = 0; i < len; i ++) { _gs_putc(buf[i]); // DBG("%c", buf[i]); } #else _gs.printf("\x1bU%X", cid); _gs.printf("%d.%d.%d.%d:%d:", host.getIp()[0], host.getIp()[1], host.getIp()[2], host.getIp()[3], host.getPort()); for (i = 0; i < len; i ++) { if (buf[i] >= 0x20 && buf[i] < 0x7f) { _gs_putc(buf[i]); // DBG("%c", buf[i]); } } _gs_putc(0x1b); _gs_putc('E'); #endif } else { return -1; } timeout.start(); while (!_gs_ok && !_gs_failure && timeout.read_ms() < GS_TIMEOUT); return _gs_ok == 1 ? 0 : -1; } int GSwifi::recv (int cid, char *buf, int len) { int r; Timer timeout; if (_gs_sock[cid].data == NULL) return 0; timeout.start(); while (_gs_sock[cid].data->use() == 0) { if (timeout.read_ms() > GS_TIMEOUT) return 0; } timeout.stop(); r = _gs_sock[cid].data->get(buf, len); return r; } int GSwifi::recv (int cid, char *buf, int len, Host &host) { int r; Timer timeout; if (_gs_sock[cid].data == NULL) return 0; timeout.start(); while (_gs_sock[cid].data->use() == 0) { if (timeout.read_ms() > GS_TIMEOUT) return 0; } timeout.stop(); r = _gs_sock[cid].data->get(buf, len); host = _from; return r; } bool GSwifi::isConnected (int cid) { return _gs_sock[cid].connect; } int GSwifi::httpGet (Host &host, const char *uri, const char *user, const char *pwd, int ssl, onGsReceiveFunc ponGsReceive) { char cmd[GS_CMD_SIZE]; if (! _connect || _status != GSSTAT_READY) return -1; if (host.getIp().isNull()) { if (getHostByName(host)) { if (getHostByName(host)) return -1; } } if (host.getPort() == 0) { if (ssl) { host.setPort(443); } else { host.setPort(80); } } command("AT+HTTPCONF=3,close", GSRES_NORMAL); // Connection: sprintf(cmd, "AT+HTTPCONF=11,%s", host.getName()); // Host: command(cmd, GSRES_NORMAL); if (user && pwd) { char tmp[GS_CMD_SIZE], tmp2[GS_CMD_SIZE]; snprintf(tmp, sizeof(tmp), "%s:%s", user, pwd); base64encode(tmp, strlen(tmp), tmp2, sizeof(tmp2)); sprintf(cmd, "AT+HTTPCONF=2,Basic %s", tmp2); // Authorization: command(cmd, GSRES_NORMAL); } else { command("AT+HTTPCONFDEL=2", GSRES_NORMAL); } command("AT+HTTPCONFDEL=5", GSRES_NORMAL); command("AT+HTTPCONFDEL=7", GSRES_NORMAL); sprintf(cmd, "AT+HTTPOPEN=%d.%d.%d.%d,%d", host.getIp()[0], host.getIp()[1], host.getIp()[2], host.getIp()[3], host.getPort()); if (ssl) { strcat(cmd, ",1"); } if (command(cmd, GSRES_HTTP)) return -1; newSock(_cid, GSTYPE_CLIENT, GSPROT_HTTPGET, ponGsReceive); sprintf(cmd, "AT+HTTPSEND=%d,1,%d,%s", _cid, GS_TIMEOUT / 1000, uri); // GET command(cmd, GSRES_NORMAL); return _cid; } int GSwifi::httpGet (Host &host, const char *uri, int ssl, onGsReceiveFunc ponGsReceive) { return httpGet (host, uri, NULL, NULL, ssl, ponGsReceive); } int GSwifi::httpPost (Host &host, const char *uri, const char *body, const char *user, const char *pwd, int ssl, onGsReceiveFunc ponGsReceive) { char cmd[GS_CMD_SIZE]; int i, len; if (! _connect || _status != GSSTAT_READY) return -1; if (host.getIp().isNull()) { if (getHostByName(host)) { if (getHostByName(host)) return -1; } } if (host.getPort() == 0) { if (ssl) { host.setPort(443); } else { host.setPort(80); } } len = strlen(body); command("AT+HTTPCONF=3,close", GSRES_NORMAL); // Connection: sprintf(cmd, "AT+HTTPCONF=11,%s", host.getName()); // Host: command(cmd, GSRES_NORMAL); sprintf(cmd, "AT+HTTPCONF=5,%d", len); // Content-Length: command(cmd, GSRES_NORMAL); command("AT+HTTPCONF=7,application/x-www-form-urlencoded", GSRES_NORMAL); // Content-type: if (user && pwd) { char tmp[GS_CMD_SIZE], tmp2[GS_CMD_SIZE]; snprintf(tmp, sizeof(tmp), "%s:%s", user, pwd); base64encode(tmp, strlen(tmp), tmp2, sizeof(tmp2)); sprintf(cmd, "AT+HTTPCONF=2,Basic %s", tmp2); // Authorization: command(cmd, GSRES_NORMAL); } else { command("AT+HTTPCONFDEL=2", GSRES_NORMAL); } sprintf(cmd, "AT+HTTPOPEN=%d.%d.%d.%d,%d", host.getIp()[0], host.getIp()[1], host.getIp()[2], host.getIp()[3], host.getPort()); if (ssl) { strcat(cmd, ",1"); } if (command(cmd, GSRES_HTTP)) return -1; newSock(_cid, GSTYPE_CLIENT, GSPROT_HTTPPOST, ponGsReceive); sprintf(cmd, "AT+HTTPSEND=%d,3,%d,%s,%d", _cid, GS_TIMEOUT / 1000, uri, len); // POST command(cmd, GSRES_NORMAL); _gs.printf("\x1bH%X", _cid); for (i = 0; i < len; i ++) { _gs_putc(body[i]); DBG("%c", body[i]); } return _cid; } int GSwifi::httpPost (Host &host, const char *uri, const char *body, int ssl, onGsReceiveFunc ponGsReceive) { return httpPost (host, uri, body, NULL, NULL, ssl, ponGsReceive); } int GSwifi::certAdd (const char *name, const char *cert, int len) { int i; char cmd[GS_CMD_SIZE]; if (! _connect || _status != GSSTAT_READY) return -1; sprintf(cmd, "AT+TCERTADD=%s,1,%d,1", name, len); // Hex, ram command(cmd, GSRES_NORMAL); _gs_putc(0x1b); _gs_putc('W'); for (i = 0; i < len; i ++) { _gs_putc(cert[i]); } return cmdResponse(GSRES_NORMAL, GS_TIMEOUT); } int GSwifi::provisioning (char *user, char *pass) { char cmd[GS_CMD_SIZE]; if (_status != GSSTAT_READY) return -1; sprintf(cmd, "AT+WEBPROV=%s,%s", user, pass); return command(cmd, GSRES_NORMAL); } int GSwifi::setBaud (int baud) { char cmd[GS_CMD_SIZE]; if (_status != GSSTAT_READY) return -1; _gs.printf("ATB=%d\r\n", baud); _gs.baud(baud); for (int i = 0; i < 10; i ++) { wait_ms(10); poll_cmd(); _buf_cmd.clear(); } return 0; } int GSwifi::base64encode (char *input, int length, char *output, int len) { // code from // Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com) static const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; unsigned int c, c1, c2, c3; if (len < ((((length-1)/3)+1)<<2)) return -1; for(unsigned int i = 0, j = 0; i<length; i+=3,j+=4) { c1 = ((((unsigned char)*((unsigned char *)&input[i])))); c2 = (length>i+1)?((((unsigned char)*((unsigned char *)&input[i+1])))):0; c3 = (length>i+2)?((((unsigned char)*((unsigned char *)&input[i+2])))):0; c = ((c1 & 0xFC) >> 2); output[j+0] = base64[c]; c = ((c1 & 0x03) << 4) | ((c2 & 0xF0) >> 4); output[j+1] = base64[c]; c = ((c2 & 0x0F) << 2) | ((c3 & 0xC0) >> 6); output[j+2] = (length>i+1)?base64[c]:'='; c = (c3 & 0x3F); output[j+3] = (length>i+2)?base64[c]:'='; } output[(((length-1)/3)+1)<<2] = '\0'; return 0; } int GSwifi::from_hex (int ch) { return isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10; } int GSwifi::to_hex (int code) { static char hex[] = "0123456789abcdef"; return hex[code & 15]; } int GSwifi::urlencode (char *str, char *buf, int len) { // code from // Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com) // char *pstr = str, *buf = (char*)malloc(strlen(str) * 3 + 1), *pbuf = buf; char *pstr = str, *pbuf = buf; if (len < (strlen(str) * 3 + 1)) return -1; while (*pstr) { if (isalnum(*pstr) || *pstr == '-' || *pstr == '_' || *pstr == '.' || *pstr == '~') *pbuf++ = *pstr; else if (*pstr == ' ') *pbuf++ = '+'; else *pbuf++ = '%', *pbuf++ = to_hex(*pstr >> 4), *pbuf++ = to_hex(*pstr & 15); pstr++; } *pbuf = '\0'; return 0; } int GSwifi::urldecode (char *str, char *buf, int len) { // code from // Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com) // char *pstr = str, *buf = (char*)malloc(strlen(str) + 1), *pbuf = buf; char *pstr = str, *pbuf = buf; if (len < (strlen(str) / 3 - 1)) return -1; while (*pstr) { if (*pstr == '%') { if (pstr[1] && pstr[2]) { *pbuf++ = from_hex(pstr[1]) << 4 | from_hex(pstr[2]); pstr += 2; } } else if (*pstr == '+') { *pbuf++ = ' '; } else { *pbuf++ = *pstr; } pstr++; } *pbuf = '\0'; return 0; } int GSwifi::x2i (char c) { if (c >= '0' && c <= '9') { return c - '0'; } else if (c >= 'A' && c <= 'F') { return c - 'A' + 10; } else if (c >= 'a' && c <= 'f') { return c - 'a' + 10; } return 0; } char GSwifi::i2x (int i) { if (i >= 0 && i <= 9) { return i + '0'; } else if (i >= 10 && i <= 15) { return i - 10 + 'A'; } return 0; } #ifdef DEBUG // for test void GSwifi::test () { /* command(NULL, GSRES_NORMAL); wait_ms(100); command("AT+NCLOSEALL", GSRES_NORMAL); _connect = true; */ command("AT+WRXACTIVE=1", GSRES_NORMAL); } int GSwifi::getc() { char c; if (_buf_cmd.use()) { _buf_cmd.get(&c); } /* } else if (_gs_sock[0].data != NULL) { _gs_sock[0].data->get(&c); } */ return c; } void GSwifi::putc(char c) { _gs_putc(c); } int GSwifi::readable() { return _buf_cmd.use(); // return _buf_cmd.use() || (_gs_sock[0].data != NULL && _gs_sock[0].data->use()); } #endif