Merge pull request #98 from EnviroDIY/master

XBee updates, other tweeks
This commit is contained in:
Volodymyr Shymanskyy
2017-11-01 12:55:59 +02:00
committed by GitHub
24 changed files with 962 additions and 834 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -16,7 +16,7 @@
},
"homepage": "https://github.com/vshymanskyy/TinyGSM",
"export": {
"exclude": [ "extras", "tools" ]
"exclude": [ "extras/*", "tools/*" ]
},
"frameworks": [ "arduino", "energia", "wiringpi" ],
"platforms": "*",
File diff suppressed because it is too large Load Diff
@@ -12,7 +12,7 @@
//#define TINY_GSM_DEBUG Serial
#if !defined(TINY_GSM_RX_BUFFER)
#define TINY_GSM_RX_BUFFER 256
#define TINY_GSM_RX_BUFFER 512
#endif
#define TINY_GSM_MUX_COUNT 5
@@ -108,7 +108,7 @@ public:
continue;
}
// TODO: Read directly into user buffer?
if (!rx.size()) {
if (!rx.size() && sock_connected) {
at->maintain();
//break;
}
@@ -185,7 +185,7 @@ public:
if (!testAT()) {
return false;
}
sendAT(GF("E0"));
sendAT(GF("E0")); // Echo Off
if (waitResponse() != 1) {
return false;
}
@@ -209,9 +209,7 @@ public:
}
void maintain() {
//while (stream.available()) {
waitResponse(10, NULL, NULL);
//}
}
bool factoryDefault() {
@@ -270,13 +268,25 @@ public:
streamSkipUntil(','); // Skip BSSID/MAC address
streamSkipUntil(','); // Skip Chanel number
int res2 = stream.parseInt(); // Read RSSI
DBG(res2);
waitResponse();
waitResponse(); // Returns an OK after the value
return res2;
}
bool isNetworkConnected() {
return true; // TODO
sendAT(GF("+CIPSTATUS"));
int res1 = waitResponse(3000, GF("STATUS:"));
int res2 = 0;
if (res1 == 1) {
res2 = waitResponse(GFP(GSM_ERROR), GF("2"), GF("3"), GF("4"), GF("5"));
}
// <stat> status of ESP8266 station interface
// 2 : ESP8266 station connected to an AP and has obtained IP
// 3 : ESP8266 station created a TCP or UDP transmission
// 4 : the TCP or UDP transmission of ESP8266 station disconnected (but AP is connected)
// 5 : ESP8266 station did NOT connect to an AP
waitResponse(); // Returns an OK after the status
if (res2 == 2 || res2 == 3 || res2 == 4) return true;
else return false;
}
bool waitForNetwork(unsigned long timeout = 60000L) {
@@ -285,14 +295,12 @@ public:
int res1 = waitResponse(3000, GF("busy p..."), GF("STATUS:"));
if (res1 == 2) {
int res2 = waitResponse(GFP(GSM_ERROR), GF("2"), GF("3"), GF("4"), GF("5"));
if (res2 == 2 || res2 == 3 || res2 == 4) return true;
}
// <stat> status of ESP8266 station interface
// 2 : ESP8266 station connected to an AP and has obtained IP
// 3 : ESP8266 station created a TCP or UDP transmission
// 4 : the TCP or UDP transmission of ESP8266 station disconnected (but AP is connected)
// 5 : ESP8266 station did NOT connect to an AP
delay(1000);
if (res2 == 2 || res2 == 3 || res2 == 4) {
waitResponse();
return true;
}
}
delay(250);
}
return false;
}
@@ -322,7 +330,9 @@ public:
bool networkDisconnect() {
sendAT(GF("+CWQAP"));
return waitResponse(10000L) == 1;
bool retVal = waitResponse(10000L) == 1;
waitResponse(GF("WIFI DISCONNECT"));
return retVal;
}
String getLocalIP() {
@@ -332,7 +342,6 @@ public:
return "";
}
String res2 = stream.readStringUntil('"');
DBG(res2);
waitResponse();
return res2;
}
@@ -349,11 +358,12 @@ protected:
waitResponse();
}
sendAT(GF("+CIPSTART="), mux, ',', ssl ? GF("\"SSL") : GF("\"TCP"), GF("\",\""), host, GF("\","), port, GF(","), TINY_GSM_TCP_KEEP_ALIVE);
// TODO: Check mux
int rsp = waitResponse(75000L,
GFP(GSM_OK),
GFP(GSM_ERROR),
GF(GSM_NL "ALREADY CONNECT" GSM_NL));
waitResponse(100, GF("1,CONNECT")); // TODO
GF("ALREADY CONNECT"));
// if (rsp == 3) waitResponse(); // May return "ERROR" after the "ALREADY CONNECT"
return (1 == rsp);
}
@@ -364,7 +374,7 @@ protected:
}
stream.write((uint8_t*)buff, len);
stream.flush();
if (waitResponse(GF(GSM_NL "SEND OK" GSM_NL)) != 1) {
if (waitResponse(10000L, GF(GSM_NL "SEND OK" GSM_NL)) != 1) {
return -1;
}
return len;
@@ -372,9 +382,19 @@ protected:
bool modemGetConnected(uint8_t mux) {
sendAT(GF("+CIPSTATUS="), mux);
int res = waitResponse(GF(",\"CONNECTED\""), GF(",\"CLOSED\""), GF(",\"CLOSING\""), GF(",\"INITIAL\""));
waitResponse();
return 1 == res;
int res1 = waitResponse(3000, GF("STATUS:"));
int res2;
if (res1 == 1) {
res2 = waitResponse(GFP(GSM_ERROR), GF("2"), GF("3"), GF("4"), GF("5"));
}
// <stat> status of ESP8266 station interface
// 2 : ESP8266 station connected to an AP and has obtained IP
// 3 : ESP8266 station created a TCP or UDP transmission
// 4 : the TCP or UDP transmission of ESP8266 station disconnected (but AP is connected)
// 5 : ESP8266 station did NOT connect to an AP
waitResponse(); // Returns an OK after the status
if (res2 == 2 || res2 == 3 || res2 == 4) return true;
else return false;
}
public:
@@ -458,12 +478,18 @@ public:
sockets[mux]->rx.put(stream.read());
}
if (len_orig > sockets[mux]->available()) { // TODO
DBG(GSM_NL, "### Fewer characters received than expected: ", sockets[mux]->available(), " vs ", len_orig);
DBG("### Fewer characters received than expected: ", sockets[mux]->available(), " vs ", len_orig);
}
data = "";
return index;
} else if (data.endsWith(GF(GSM_NL "1,CLOSED" GSM_NL))) { //TODO: use mux
sockets[1]->sock_connected = false;
} else if (data.endsWith(GF("CLOSED"))) {
int muxStart = max(0,data.lastIndexOf(GSM_NL, data.length()-8));
int coma = data.indexOf(',', muxStart);
int mux = data.substring(muxStart, coma).toInt();
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->sock_connected = false;
}
data = "";
DBG("### Closed: ", mux);
}
}
} while (millis() - startMillis < timeout);
@@ -123,7 +123,7 @@ public:
continue;
}
// TODO: Read directly into user buffer?
if (!rx.size()) {
if (!rx.size() && sock_connected) {
at->maintain();
//break;
}
@@ -367,7 +367,7 @@ public:
if (isNetworkConnected()) {
return true;
}
delay(500);
delay(250);
}
return false;
}
@@ -655,7 +655,7 @@ public:
sockets[mux]->rx.put(stream.read());
}
if (len_orig > sockets[mux]->available()) { // TODO
DBG(GSM_NL, "### Fewer characters received than expected: ", sockets[mux]->available(), " vs ", len_orig);
DBG("### Fewer characters received than expected: ", sockets[mux]->available(), " vs ", len_orig);
}
data = "";
} else if (data.endsWith(GF("+TCPCLOSE:"))) {
@@ -126,7 +126,7 @@ public:
TINY_GSM_YIELD();
at->maintain();
size_t cnt = 0;
while (cnt < size) {
while (cnt < size && sock_connected) {
size_t chunk = TinyGsmMin(size-cnt, rx.size());
if (chunk > 0) {
rx.get(buf, chunk);
@@ -432,7 +432,7 @@ public:
if (isNetworkConnected()) {
return true;
}
delay(500);
delay(250);
}
return false;
}
@@ -443,71 +443,82 @@ public:
bool gprsConnect(const char* apn, const char* user, const char* pwd) {
gprsDisconnect();
sendAT(GF("+SAPBR=3,1,\"Contype\",\"GPRS\""));
// Set the Bearer for the IP
sendAT(GF("+SAPBR=3,1,\"Contype\",\"GPRS\"")); // Set the connection type to GPRS
waitResponse();
sendAT(GF("+SAPBR=3,1,\"APN\",\""), apn, '"');
sendAT(GF("+SAPBR=3,1,\"APN\",\""), apn, '"'); // Set the APN
waitResponse();
if (user && strlen(user) > 0) {
sendAT(GF("+SAPBR=3,1,\"USER\",\""), user, '"');
sendAT(GF("+SAPBR=3,1,\"USER\",\""), user, '"'); // Set the user name
waitResponse();
}
if (pwd && strlen(pwd) > 0) {
sendAT(GF("+SAPBR=3,1,\"PWD\",\""), pwd, '"');
sendAT(GF("+SAPBR=3,1,\"PWD\",\""), pwd, '"'); // Set the password
waitResponse();
}
// Define the PDP context
sendAT(GF("+CGDCONT=1,\"IP\",\""), apn, '"');
waitResponse();
// Activate the PDP context
sendAT(GF("+CGACT=1,1"));
waitResponse(60000L);
// Open a GPRS context
// Open the definied GPRS bearer context
sendAT(GF("+SAPBR=1,1"));
waitResponse(85000L);
// Query the GPRS context
// Query the GPRS bearer context status
sendAT(GF("+SAPBR=2,1"));
if (waitResponse(30000L) != 1)
return false;
// Attach to GPRS
sendAT(GF("+CGATT=1"));
if (waitResponse(60000L) != 1)
return false;
// TODO: wait AT+CGATT?
// Set to multi-IP
sendAT(GF("+CIPMUX=1"));
if (waitResponse() != 1) {
return false;
}
// Put in "quick send" mode (thus no extra "Send OK")
sendAT(GF("+CIPQSEND=1"));
if (waitResponse() != 1) {
return false;
}
// Set to get data manually
sendAT(GF("+CIPRXGET=1"));
if (waitResponse() != 1) {
return false;
}
// Start Task and Set APN, USER NAME, PASSWORD
sendAT(GF("+CSTT=\""), apn, GF("\",\""), user, GF("\",\""), pwd, GF("\""));
if (waitResponse(60000L) != 1) {
return false;
}
// Bring Up Wireless Connection with GPRS or CSD
sendAT(GF("+CIICR"));
if (waitResponse(60000L) != 1) {
return false;
}
// Get Local IP Address, only assigned after connection
sendAT(GF("+CIFSR;E0"));
if (waitResponse(10000L) != 1) {
return false;
}
// Configure Domain Name Server (DNS)
sendAT(GF("+CDNSCFG=\"8.8.8.8\",\"8.8.4.4\""));
if (waitResponse() != 1) {
return false;
@@ -517,11 +528,11 @@ public:
}
bool gprsDisconnect() {
sendAT(GF("+CIPSHUT"));
sendAT(GF("+CIPSHUT")); // Shut the TCP/IP connection
if (waitResponse(60000L) != 1)
return false;
sendAT(GF("+CGATT=0"));
sendAT(GF("+CGATT=0")); // Deactivate the bearer context
if (waitResponse(60000L) != 1)
return false;
@@ -372,7 +372,7 @@ public:
if (isNetworkConnected()) {
return true;
}
delay(500);
delay(250);
}
return false;
}
+81 -35
View File
@@ -31,7 +31,7 @@ enum SimStatus {
enum XBeeType {
S6B = 0,
LTEC1 = 1,
LTEC1 = 1,
};
enum RegStatus {
@@ -74,7 +74,7 @@ public:
virtual int connect(const char *host, uint16_t port) {
at->streamClear(); // Empty anything remaining in the buffer;
at->commandMode();
sock_connected = at->modemConnect(host, port, mux);
sock_connected = at->modemConnect(host, port, mux, false);
at->writeChanges();
at->exitCommand();
return sock_connected;
@@ -83,7 +83,7 @@ public:
virtual int connect(IPAddress ip, uint16_t port) {
at->streamClear(); // Empty anything remaining in the buffer;
at->commandMode();
sock_connected = at->modemConnect(ip, port, mux);
sock_connected = at->modemConnect(ip, port, mux, false);
at->writeChanges();
at->exitCommand();
return sock_connected;
@@ -92,13 +92,13 @@ public:
// This is a hack to shut the socket by setting the timeout to zero and
// then sending an empty line to the server.
virtual void stop() {
at->streamClear(); // Empty anything remaining in the buffer;
at->commandMode();
at->sendAT(GF("TM0")); // Set socket timeout to 0;
at->waitResponse();
at->writeChanges();
at->exitCommand();
at->modemSend("", 1, mux);
at->streamClear(); // Empty anything remaining in the buffer;
at->commandMode();
at->sendAT(GF("TM64")); // Set socket timeout back to 10seconds;
at->waitResponse();
@@ -124,7 +124,8 @@ public:
}
virtual int read(uint8_t *buf, size_t size) {
return available();
TINY_GSM_YIELD();
return at->stream.readBytes(buf, size);
}
virtual int read() {
@@ -155,6 +156,35 @@ private:
bool sock_connected;
};
class GsmClientSecure : public GsmClient
{
public:
GsmClientSecure() {}
GsmClientSecure(TinyGsm& modem, uint8_t mux = 1)
: GsmClient(modem, mux)
{}
public:
virtual int connect(const char *host, uint16_t port) {
at->streamClear(); // Empty anything remaining in the buffer;
at->commandMode();
sock_connected = at->modemConnect(host, port, mux, true);
at->writeChanges();
at->exitCommand();
return sock_connected;
}
virtual int connect(IPAddress ip, uint16_t port) {
at->streamClear(); // Empty anything remaining in the buffer;
at->commandMode();
sock_connected = at->modemConnect(ip, port, mux, true);
at->writeChanges();
at->exitCommand();
return sock_connected;
}
};
public:
TinyGsm(Stream& stream)
@@ -190,7 +220,18 @@ public:
return true;
}
bool testAT(unsigned long timeout = 10000L) { // not supported
bool testAT(unsigned long timeout = 10000L) {
for (unsigned long start = millis(); millis() - start < timeout; ) {
if (commandMode())
{
sendAT();
if (waitResponse(200) == 1) {
return true;
}
exitCommand();
}
delay(100);
}
return false;
}
@@ -205,6 +246,11 @@ public:
return ret_val;
}
bool hasSSL() {
if (beeType == S6B) return false;
else return true;
}
/*
* Power functions
*/
@@ -230,8 +276,10 @@ public:
commandMode();
sendAT(GF("SM"),1);
waitResponse();
sendAT(GF("SO"),200);
waitResponse();
if (beeType == S6B) {
sendAT(GF("SO"),200);
waitResponse();
}
writeChanges();
exitCommand();
}
@@ -272,8 +320,7 @@ public:
RegStatus getRegistrationStatus() {
commandMode();
if (beeType == S6B) sendAT(GF("AI"));
else sendAT(GF("CI"));
sendAT(GF("AI"));
// wait for the response
unsigned long startMillis = millis();
while (!stream.available() && millis() - startMillis < 1000) {};
@@ -290,7 +337,7 @@ public:
res == GF("40") || res == GF("41") || res == GF("42"))
return REG_SEARCHING;
else if(res == GF("24"))
else if(res == GF("24") || res == GF("25") || res == GF("27"))
return REG_DENIED;
else return REG_UNKNOWN;
@@ -314,34 +361,31 @@ public:
int getSignalQuality() {
commandMode();
if (beeType == S6B) sendAT(GF("LM")); // ask for the "link margin" - the dB above sensitivity
else sendAT(GF("DB")); // ask for the cell strenght in dBm
else sendAT(GF("DB")); // ask for the cell strength in dBm
// wait for the response
unsigned long startMillis = millis();
while (!stream.available() && millis() - startMillis < 1000) {};
char buf[2] = {0}; // Set up buffer for response
buf[0] = streamRead();
buf[1] = streamRead();
DBG(buf[0], buf[1], "\n");
// DBG(buf[0], buf[1], "\n");
exitCommand();
int intr = strtol(buf, 0, 16);
if (beeType == S6B) return -93 + intr; // the maximum sensitivity is -93dBm
else return -1*intr; // need to convert to negative number
}
bool isNetworkConnected() {
RegStatus s = getRegistrationStatus();
return (s == REG_OK_HOME || s == REG_OK_ROAMING);
}
bool waitForNetwork(unsigned long timeout = 60000L) {
for (unsigned long start = millis(); millis() - start < timeout; ) {
commandMode();
if (beeType == S6B) sendAT(GF("AI"));
else sendAT(GF("CI"));
// wait for the response
unsigned long startMillis = millis();
while (!stream.available() && millis() - startMillis < 1000) {};
String res = streamReadUntil('\r'); // Does not send an OK, just the result
exitCommand();
if (res == GF("0")) {
if (isNetworkConnected()) {
return true;
}
delay(1000);
delay(250);
}
return false;
}
@@ -439,7 +483,7 @@ fail:
private:
int modemConnect(const char* host, uint16_t port, uint8_t mux = 0) {
int modemConnect(const char* host, uint16_t port, uint8_t mux = 0, bool ssl = false) {
sendAT(GF("LA"), host);
String strIP; strIP.reserve(16);
// wait for the response
@@ -447,10 +491,10 @@ private:
while (stream.available() < 8 && millis() - startMillis < 30000) {};
strIP = streamReadUntil('\r'); // read result
IPAddress ip = TinyGsmIpFromString(strIP);
return modemConnect(ip, port);
return modemConnect(ip, port, mux, ssl);
}
int modemConnect(IPAddress ip, uint16_t port, uint8_t mux = 0) {
int modemConnect(IPAddress ip, uint16_t port, uint8_t mux = 0, bool ssl = false) {
String host; host.reserve(16);
host += ip[0];
host += ".";
@@ -459,8 +503,13 @@ private:
host += ip[2];
host += ".";
host += ip[3];
sendAT(GF("IP"), 1); // Put in TCP mode
waitResponse();
if (ssl) {
sendAT(GF("IP"), 4); // Put in TCP mode
waitResponse();
} else {
sendAT(GF("IP"), 1); // Put in TCP mode
waitResponse();
}
sendAT(GF("DL"), host); // Set the "Destination Address Low"
waitResponse();
sendAT(GF("DE"), String(port, HEX)); // Set the destination port
@@ -476,8 +525,7 @@ private:
bool modemGetConnected(uint8_t mux = 0) {
commandMode();
if (beeType == S6B) sendAT(GF("AI"));
else sendAT(GF("CI"));
sendAT(GF("AI"));
int res = waitResponse(GF("0"));
exitCommand();
return 1 == res;
@@ -504,9 +552,7 @@ public:
TINY_GSM_YIELD();
String return_string = stream.readStringUntil(c);
return_string.trim();
if (String(c) == GSM_NL) {
DBG(return_string, "\r\n");
} else DBG(return_string, c);
// DBG(return_string, c);
return return_string;
}
@@ -517,7 +563,7 @@ public:
bool commandMode(void) {
delay(guardTime); // cannot send anything for 1 second before entering command mode
streamWrite(GF("+++")); // enter command mode
DBG("\r\n+++\r\n");
// DBG("\r\n+++\r\n");
return 1 == waitResponse(guardTime*2);
}
@@ -594,7 +640,7 @@ finish:
data.replace(GSM_NL GSM_NL, GSM_NL);
data.replace(GSM_NL, "\r\n ");
if (data.length()) {
DBG("<<< ", data, "\r\n");
// DBG("<<< ", data);
}
}
return index;
View File
+45
View File
@@ -0,0 +1,45 @@
/**************************************************************
*
* This script just listens in on the communication between an Arduino and the
* modem.
*
* TinyGSM Getting Started guide:
* http://tiny.cc/tiny-gsm-readme
*
**************************************************************/
// Set the baud rate between the modem and the board
#define BAUD_RATE 9600
// Set serial printing out the communication
#define SPY Serial
// Set serial for input from modem
#define MODEM_TX Serial1
// Set serial for AT commands (to the module)
// Use Hardware Serial on Mega, Leonardo, Micro
// #define BOARD_TX Serial1
// or AltSoftware
#include <AltSoftSerial.h>
AltSoftSerial BOARD_TX;
void setup() {
// Set console baud rate
SPY.begin(57600);
MODEM_TX.begin(BAUD_RATE);
BOARD_TX.begin(BAUD_RATE);
delay(5000);
}
void loop()
{
while (MODEM_TX.available()) {
SPY.write(MODEM_TX.read());
}
while (BOARD_TX.available()) {
SPY.write(BOARD_TX.read());
}
}