Added battery status, SMS are sent/received in Text format instead of PDU

This commit is contained in:
Pavel Brychta 2019-06-01 11:09:49 +02:00
parent 83e50daf36
commit a5ad4c4e1d
5 changed files with 998 additions and 0 deletions

129
DTE.h Normal file
View File

@ -0,0 +1,129 @@
/*
* DTE.h
*
* Created: 20/09/2016 15:40:51
* Author: Neta Yahav
*/
#ifndef __DTE_H__
#define __DTE_H__
#include <Arduino.h>
class DTE
{
//variables
public:
enum CommandResult
{
EXPECT_BUSY,
EXPECT_TIMEOUT,
EXPECT_DELAY,
EXPECT_RESULT
};
protected:
private:
String buffer;
Stream& stream;
unsigned int bufferIndex;
unsigned int bufferSize;
String response[3];
unsigned long timeout;
unsigned long tick;
unsigned int match;
CommandResult result;
//functions
public:
DTE(Stream& stream, unsigned int size) : stream(stream), bufferSize(size), result(EXPECT_RESULT) { buffer.reserve(size); }
~DTE() {};
void SendCommand(const char* command, unsigned long timeout, const char* response1, const char* response2 = 0, const char* response3 = 0)
{
match = 0;
result = EXPECT_BUSY;
response[0] = response1;
response[1] = response2;
response[2] = response3;
this->timeout = timeout;
// clear rx buffer
while (stream.available())
{
stream.read();
}
// send command
stream.print(command);
buffer = "";
tick = millis();
proccess();
}
void Delay(unsigned long delay)
{
timeout = delay;
result = EXPECT_DELAY;
tick = millis();
proccess();
}
bool getIsBusy()
{
proccess();
return (result == EXPECT_BUSY) || (result == EXPECT_DELAY);
}
CommandResult getResult() { return result ; }
unsigned int getMatch() { return match; }
String& getBuffer() { return buffer; }
protected:
private:
void proccess()
{
if(result == EXPECT_DELAY)
{
if(millis() - tick >= timeout)
result = EXPECT_RESULT;
return;
}
if(result != EXPECT_BUSY) return;
char c;
unsigned long now = millis();
while(millis() - tick < timeout)
{
while(stream.available() && (buffer.length() < (bufferSize)))
{
c = stream.read();
buffer += c;
if(buffer.endsWith(response[0]))
{
match = 0;
result = EXPECT_RESULT;
return;
}else if(response[1].length() != 0)
{
if(buffer.endsWith(response[1]))
{
match = 1;
result = EXPECT_RESULT;
return;
}
}else if(response[2].length() != 0)
{
if(buffer.endsWith(response[2]))
{
match = 2;
result = EXPECT_RESULT;
return;
}
}
}
if(millis() - now > 5)
return;
}
// time out
result = EXPECT_TIMEOUT;
}
}; //DTE
#endif //__DTE_H__

79
README_original.md Normal file
View File

@ -0,0 +1,79 @@
# ArduinoThreadedGSM
Use this library to:
* Send/Read SMS
* Read Network Time
* Read GSM signal level
### Quick-start
Initialize modem:
```c++
ThreadedGSM modem(Serial1);
...
void setup()
{
modem.begin();
}
```
Set automatic intervals for syncing clock and signal levels:
```c++
modem.setInterval(ThreadedGSM::INTERVAL_CLOCK, 60000);
modem.setInterval(ThreadedGSM::INTERVAL_SIGNAL, 60000);
modem.setInterval(ThreadedGSM::INTERVAL_INBOX, 30000);
```
Create your event handlers
```c++
void clock(ThreadedGSM& modem, ThreadedGSM::NetworkTime& Time)
{
/* Network time */
}
void signal(ThreadedGSM& modem, ThreadedGSM::SignalLevel& Signal)
{
/* Signal */
}
void sms(ThreadedGSM& modem, String& Msg)
{
/* Message received in PDU */
}
void startup(ThreadedGSM& modem)
{
/* READY */
}
```
Set event handlers for modem events as you like:
```c++
modem.setHandlers({
.signal = signal,
.clock = clock,
.incoming = sms,
.ready = startup,
.outgoing = NULL,
.power = NULL
});
```
and finally, let the modem loop as a thread in your Arduino loop()
```c++
void loop()
{
// "Non-blocking" loop
modem.loop();
}
```
To send SMS messages, request to send them using sendSMS:
```c++
modem.sendSMS(PDU); // PDU as String, hexadecimal
```
*Don't forget to check whether your messages were sent successfuly, before sending more.*
*Use power event callbacks to set modem pins (EN/RST) on power on/off when needed*
Project hosted on GitHub: [https://github.com/neta540/ArduinoThreadedGSM](https://github.com/neta540/ArduinoThreadedGSM).

690
ThreadedGSM.h Normal file
View File

@ -0,0 +1,690 @@
/*
* ThreadedGSM.h
*
* Created: 20/09/2016 11:14:02
* Author: Neta Yahav
*/
#ifndef __THREADEDGSM_H__
#define __THREADEDGSM_H__
#include <Arduino.h>
#include "DTE.h"
// Defaults
#define THREADEDGSM_DEF_DTE_BUF_SIZ 512
#define THREADEDGSM_DEF_AT_TIMEOUT 5000
#define THREADEDGSM_DEF_STA_PON 10000
#define THREADEDGSM_DEF_STA_POF 1000
// Use custom values or default ones
#ifndef THREADEDGSM_DTE_BUFFER_SIZE
#define THREADEDGSM_DTE_BUFFER_SIZE THREADEDGSM_DEF_DTE_BUF_SIZ
#endif
#ifndef THREADEDGSM_AT_TIMEOUT
#define THREADEDGSM_AT_TIMEOUT THREADEDGSM_DEF_AT_TIMEOUT
#endif
#ifndef THREADEDGSM_STARTUP_DELAY
#define THREADEDGSM_STARTUP_DELAY THREADEDGSM_DEF_STA_PON
#endif
#ifndef THREADEDGSM_STARTUP_POWER_OFF_DELAY
#define THREADEDGSM_STARTUP_POWER_OFF_DELAY THREADEDGSM_DEF_STA_POF
#endif
#define THREADEDGSM_INTERVAL_COUNT 4
#ifdef THREADEDGSM_DEBUG
#define DEBUG_PRINT(x) THREADEDGSM_DEBUG.print (x)
#define DEBUG_PRINTLN(x) THREADEDGSM_DEBUG.println (x)
#else
#define DEBUG_PRINT(x)
#define DEBUG_PRINTLN(x)
#endif
class ThreadedGSM
{
//variables
public:
struct NetworkTime
{
int year;
int month;
int day;
int hour;
int minute;
int second;
};
enum ReadMessagesListTypeE {
READ_TYPE_UNREAD = 0,
READ_TYPE_READ = 1,
READ_TYPE_UNSENT = 2,
READ_TYPE_SENT = 3,
READ_TYPE_ALL = 4
};
enum IntervalSourceE
{
INTERVAL_CLOCK,
INTERVAL_INBOX,
INTERVAL_SIGNAL,
INTERVAL_BATTERY
};
struct SignalLevel
{
int Dbm;
int Value;
};
struct BatteryInfo
{
int Percent;
int Voltage;
};
struct SMSInfo
{
String Number;
String Text;
};
typedef void (*ThreadedGSMCallbackSignal)(ThreadedGSM&, SignalLevel&);
typedef void (*ThreadedGSMCallbackClock)(ThreadedGSM&, NetworkTime&);
typedef void (*ThreadedGSMCallbackBattery)(ThreadedGSM&, BatteryInfo&);
typedef void (*ThreadedGSMCallbackIncomingSMS)(ThreadedGSM&, SMSInfo&);
typedef void (*ThreadedGSMCallbackBool)(ThreadedGSM&, bool);
typedef void (*ThreadedGSMCallback)(ThreadedGSM&);
struct conf
{
ThreadedGSMCallbackSignal signal;
ThreadedGSMCallbackClock clock;
ThreadedGSMCallbackIncomingSMS incoming;
ThreadedGSMCallback ready;
ThreadedGSMCallback outgoing;
ThreadedGSMCallbackBool power;
ThreadedGSMCallbackBattery battery;
};
protected:
private:
enum StatesStartup
{
STARTUP_POWER_OFF,
STARTUP_POWER_OFF_DELAY,
STARTUP_POWER_ON,
STARTUP_DELAY,
STARTUP_ENTER_AT,
STARTUP_CHK_CPIN,
STARTUP_CHK_CREG,
STARTUP_CHK_CLTS,
STARTUP_CHK_CENG
};
enum StatesClock
{
CLOCK_REQ,
CLOCK_VERIFY
};
enum StatesSignal
{
SIGNAL_REQ,
SIGNAL_VERIFY
};
enum StatesBattry
{
BATTERY_REQ,
BATTERY_VERIFY
};
enum StatesInbox
{
READ_REQ,
READ_CHK_CMGF,
READ_CHK_CPMS,
READ_CHK_CMGL,
READ_DELAY_CLEAR_BUFF,
READ_TEXT_CMGR,
READ_CHK_CMGR,
READ_CHK_CMGD
};
enum StatesOutbox
{
SEND_REQ,
SEND_CHK_CMGF,
SEND_CHK_RDY,
SEND_CHK_OK
};
unsigned long tick;
struct
{
int Index; // Index of readed message
}Message;
SMSInfo SMSi; // Inbox SMS (incoming)
SMSInfo SMSo; // Outbox SMS (outgoing)
Stream& stream;
DTE dte;
unsigned long tickSync[THREADEDGSM_INTERVAL_COUNT];
unsigned long Intervals[THREADEDGSM_INTERVAL_COUNT];
// callbacks
conf configuration = {NULL, NULL, NULL, NULL, NULL, NULL, NULL};
enum ReqTypes
{
REQ_CLOCK = 1,
REQ_SIG = 2,
REQ_INBOX = 4,
REQ_OUTBOX = 8,
REQ_STARTUP = 16,
REQ_BATTERY = 32,
};
int requests;
int state;
int job;
//functions
public:
ThreadedGSM(Stream& stream) : stream(stream), dte(stream, THREADEDGSM_DTE_BUFFER_SIZE)
{
for(int i=0;i<THREADEDGSM_INTERVAL_COUNT;i++)
Intervals[i] = 0;
job = state = requests = 0;
}
~ThreadedGSM(){};
void nextJob()
{
job = 0;
}
void setHandlers(conf config)
{
this->configuration = config;
}
void setInterval(IntervalSourceE source, unsigned long interval)
{
Intervals[source] = interval;
tickSync[source] = millis();
}
// Initialization
void begin()
{
requests = (REQ_STARTUP);
}
// Call this function for executing thread
void loop()
{
if(dte.getIsBusy()) return;
// intervals
for(int i=0;i<THREADEDGSM_INTERVAL_COUNT;i++)
{
if(Intervals[i])
{
if(millis() - tickSync[i] >= Intervals[i])
{
switch (i) {
case INTERVAL_CLOCK:
requests |= REQ_CLOCK;
break;
case INTERVAL_INBOX:
requests |= REQ_INBOX;
break;
case INTERVAL_SIGNAL:
requests |= REQ_SIG;
break;
case INTERVAL_BATTERY:
requests |= REQ_BATTERY;
break;
}
tickSync[i] = millis();
}
}
}
if(job == 0)
{
// no assigned job, assign it
if(requests & REQ_CLOCK)
job = REQ_CLOCK;
else if(requests & REQ_SIG)
job = REQ_SIG;
else if(requests & REQ_INBOX)
job = REQ_INBOX;
else if(requests & REQ_OUTBOX)
job = REQ_OUTBOX;
else if(requests & REQ_STARTUP)
job = REQ_STARTUP;
else if(requests & REQ_BATTERY)
job = REQ_BATTERY;
if(job)
{
state = 0;
DEBUG_PRINT(F("Job ID: "));
DEBUG_PRINTLN(job);
}
}
// execute current job
if(job == REQ_STARTUP)
Startup();
else if(job == REQ_CLOCK)
Clock();
else if(job == REQ_SIG)
Signal();
else if(job == REQ_INBOX)
Inbox();
else if(job == REQ_OUTBOX)
Outbox();
else if(job == REQ_BATTERY)
Battery();
}
// Requests
void sendSMS(String& Number, String& Text)
{
requests |= (REQ_OUTBOX);
SMSo.Number = Number;
SMSo.Text = Text;
}
protected:
private:
// States
void Startup()
{
int lastState = state;
switch(state)
{
case STARTUP_POWER_OFF:
if(this->configuration.power != NULL)
this->configuration.power(*this, false);
tick = millis();
state = STARTUP_POWER_OFF_DELAY;
break;
case STARTUP_POWER_OFF_DELAY:
if(millis() - tick >= THREADEDGSM_STARTUP_POWER_OFF_DELAY)
state = STARTUP_POWER_ON;
break;
case STARTUP_POWER_ON:
if(this->configuration.power != NULL)
this->configuration.power(*this, true);
// begin delay
tick = millis();
state = STARTUP_DELAY;
break;
case STARTUP_DELAY:
if(millis() - tick >= THREADEDGSM_STARTUP_DELAY)
{
dte.SendCommand("AT\r", THREADEDGSM_AT_TIMEOUT, "OK\r");
state = STARTUP_ENTER_AT;
}
break;
case STARTUP_ENTER_AT:
if(dte.getResult() == DTE::EXPECT_RESULT)
{
dte.SendCommand("AT+CPIN?\r", 10000, "OK\r");
state = STARTUP_CHK_CPIN;
}
else
{
state = STARTUP_POWER_OFF;
}
break;
case STARTUP_CHK_CPIN:
if(dte.getResult() == DTE::EXPECT_RESULT)
{
if(dte.getBuffer().indexOf("+CPIN: READY") != -1)
{
dte.SendCommand("AT+CREG?\r", THREADEDGSM_AT_TIMEOUT, "OK\r");
state = STARTUP_CHK_CREG;
}else
{
state = STARTUP_POWER_OFF;
}
}else
state = STARTUP_POWER_OFF;
break;
case STARTUP_CHK_CREG:
if(dte.getResult() == DTE::EXPECT_RESULT)
{
if((dte.getBuffer().indexOf(",1") >= 0) || (dte.getBuffer().indexOf(",5") >= 0))
{
dte.SendCommand("AT+CLTS=1\r", THREADEDGSM_AT_TIMEOUT, "OK\r");
state = STARTUP_CHK_CLTS;
}else
state = STARTUP_POWER_OFF;
}else
state = STARTUP_POWER_OFF;
break;
case STARTUP_CHK_CLTS:
if(dte.getResult() == DTE::EXPECT_RESULT)
{
dte.SendCommand("AT+CENG=3\r", THREADEDGSM_AT_TIMEOUT, "OK\r");
state = STARTUP_CHK_CENG;
}else
state = STARTUP_POWER_OFF;
break;
case STARTUP_CHK_CENG:
if(dte.getResult() == DTE::EXPECT_RESULT)
{
requests |= ((REQ_CLOCK)|(REQ_SIG)|(REQ_BATTERY));
clearReq(REQ_STARTUP);
for(int i=0;i<THREADEDGSM_INTERVAL_COUNT;i++)
tickSync[i] = millis();
if(this->configuration.ready != NULL)
this->configuration.ready(*this);
}else
state = STARTUP_POWER_OFF;
break;
}
if(state != lastState)
{
DEBUG_PRINT(F("STARTUP_STATE: "));
DEBUG_PRINTLN(state);
}
}
// Threads
void Clock()
{
String clockTime;
int lastState = state;
switch(state)
{
case CLOCK_REQ:
dte.SendCommand("AT+CCLK?\r", THREADEDGSM_AT_TIMEOUT, "OK\r");
state = CLOCK_VERIFY;
break;
case CLOCK_VERIFY:
int index = dte.getBuffer().indexOf("+CCLK: ");
if(index >= 0)
{
// parse clock
index+=8;
int endindex;
endindex = dte.getBuffer().indexOf("+", index);
if(endindex >= 0)
clockTime = dte.getBuffer().substring(index, endindex);
else
{
endindex = dte.getBuffer().indexOf("-", index);
if(endindex >= 0)
clockTime = dte.getBuffer().substring(index, endindex);
}
if(endindex >= 0)
{
NetworkTime ClockTime;
ClockTime.year = 2000+clockTime.substring(0,2).toInt();
ClockTime.month = clockTime.substring(3,5).toInt();
ClockTime.day = clockTime.substring(6,8).toInt();
ClockTime.hour = clockTime.substring(9,11).toInt();
ClockTime.minute = clockTime.substring(12,14).toInt();
ClockTime.second = clockTime.substring(15,17).toInt();
if(this->configuration.clock != NULL)
this->configuration.clock(*this, ClockTime);
}
}
clearReq(REQ_CLOCK);
break;
}
if(state != lastState)
{
DEBUG_PRINT(F("CLOCK_STATE: "));
DEBUG_PRINTLN(state);
}
}
void Signal()
{
int lastState = state;
switch(state)
{
case SIGNAL_REQ:
dte.SendCommand("AT+CSQ\r", THREADEDGSM_AT_TIMEOUT, "OK\r");
state = SIGNAL_VERIFY;
break;
case SIGNAL_VERIFY:
int index = dte.getBuffer().indexOf("+CSQ: ");
if(index >= 0)
{
// parse signal
index+=6;
SignalLevel GsmSignal;
GsmSignal.Value = dte.getBuffer().substring(index,index+2).toInt();
GsmSignal.Dbm = dte.getBuffer().substring(index+3,index+5).toInt();
if(GsmSignal.Value != 0)
{
if(this->configuration.signal != NULL)
this->configuration.signal(*this, GsmSignal);
}
}
clearReq(REQ_SIG);
break;
}
if(state != lastState)
{
DEBUG_PRINT(F("SIGNAL_STATE: "));
DEBUG_PRINTLN(state);
}
}
void Battery()
{
int lastState = state;
switch(state)
{
case BATTERY_REQ:
dte.SendCommand("AT+CBC\r", THREADEDGSM_AT_TIMEOUT, "OK\r");
state = BATTERY_VERIFY;
break;
case BATTERY_VERIFY:
int index = dte.getBuffer().indexOf("+CBC:");
if(index >= 0)
{
BatteryInfo BattInfo;
// parse battery level
String buffer = dte.getBuffer().substring(index);
String buffer2 = buffer.substring(buffer.indexOf(",") + 1);
buffer = buffer2;
BattInfo.Percent = buffer2.substring(0, buffer2.indexOf(",")).toInt(); // converts the result to interger
buffer2 = buffer.substring(buffer.indexOf(",") + 1);
BattInfo.Voltage = buffer2.substring(0, buffer2.indexOf("\r")).toInt(); // converts the result to interger
if(this->configuration.battery != NULL)
this->configuration.battery(*this, BattInfo);
}
clearReq(REQ_BATTERY);
break;
}
if(state != lastState)
{
DEBUG_PRINT(F("BATTERY_STATE: "));
DEBUG_PRINTLN(state);
}
}
void clearReq(int req)
{
requests &= ~(req);
nextJob();
}
void Inbox()
{
String CMD;
int lastState = state;
switch(state)
{
case READ_REQ:
SMSi.Text = "";
SMSi.Number = "";
dte.SendCommand("AT+CMGF=0\r", THREADEDGSM_AT_TIMEOUT, "OK\r"); // SMS Message format set as PDU
state = READ_CHK_CMGF;
break;
case READ_CHK_CMGF:
if(dte.getResult() == DTE::EXPECT_RESULT)
{
dte.SendCommand("AT+CPMS=\"SM\"\r", THREADEDGSM_AT_TIMEOUT, "OK\r"); // SIM Message storage
state = READ_CHK_CPMS;
}
else clearReq(REQ_INBOX);
break;
case READ_CHK_CPMS:
if(dte.getResult() == DTE::EXPECT_RESULT)
{
CMD = F("AT+CMGL="); // Read all SMS messages
CMD += (int) READ_TYPE_ALL;
CMD += "\r";
dte.SendCommand(CMD.c_str(), THREADEDGSM_AT_TIMEOUT, ",");
state = READ_CHK_CMGL;
}
else clearReq(REQ_INBOX);
break;
case READ_CHK_CMGL:
if(dte.getResult() == DTE::EXPECT_RESULT)
{
//fetch index
int indexStart = dte.getBuffer().indexOf("+CMGL: ");
if (indexStart >= 0)
{
Message.Index = dte.getBuffer().substring(indexStart + 7, dte.getBuffer().indexOf(",")).toInt();
if(Message.Index != 0)
{
dte.Delay(2000);
state = READ_DELAY_CLEAR_BUFF;
}
}
}
if(state != READ_DELAY_CLEAR_BUFF)
clearReq(REQ_INBOX);
break;
case READ_DELAY_CLEAR_BUFF:
dte.SendCommand("AT+CMGF=1\r", THREADEDGSM_AT_TIMEOUT, "OK\r"); // SMS Message format set as TEXT
state = READ_TEXT_CMGR;
break;
case READ_TEXT_CMGR:
if (dte.getResult() == DTE::EXPECT_RESULT)
{
CMD = F("AT+CMGR="); // Read the SMS message
CMD += Message.Index;
CMD += "\r";
dte.SendCommand(CMD.c_str(), THREADEDGSM_AT_TIMEOUT, "OK\r");
state = READ_CHK_CMGR;
}else
clearReq(REQ_INBOX);
break;
case READ_CHK_CMGR:
if(dte.getResult() == DTE::EXPECT_RESULT)
{
int indexStart = dte.getBuffer().indexOf("+CMGR: ");
if(indexStart >= 0)
{
int indexStartPDU = dte.getBuffer().indexOf("\r\n", indexStart);
if (indexStartPDU >= 0)
{
indexStartPDU+=2;
int indexEndPDU = dte.getBuffer().indexOf("\r", indexStartPDU);
if(indexEndPDU >= 0)
SMSi.Text = dte.getBuffer().substring(indexStartPDU, indexEndPDU);
}
indexStartPDU = dte.getBuffer().indexOf(",\"", indexStart);
if (indexStartPDU >= 0)
{
indexStartPDU += 2;
int indexEndPDU = dte.getBuffer().indexOf("\",", indexStartPDU);
if (indexEndPDU >= 0)
SMSi.Number = dte.getBuffer().substring(indexStartPDU, indexEndPDU);
}
}
CMD = F("AT+CMGD="); // Delete the SMS message
CMD += Message.Index;
CMD += "\r";
dte.SendCommand(CMD.c_str(), THREADEDGSM_AT_TIMEOUT, "OK\r");
state = READ_CHK_CMGD;
}else
clearReq(REQ_INBOX);
break;
case READ_CHK_CMGD:
//if( (dte.getResult() == DTE::EXPECT_RESULT) && (SMS.InboxMsgContents != ""))
if(dte.getResult() == DTE::EXPECT_RESULT)
{
if(this->configuration.incoming != NULL)
this->configuration.incoming(*this, SMSi);
}
clearReq(REQ_INBOX);
break;
}
if(state != lastState)
{
DEBUG_PRINT(F("INBOX_STATE: "));
DEBUG_PRINTLN(state);
}
}
void Outbox()
{
String CMD;
int lastState = state;
switch(state)
{
case SEND_REQ:
dte.SendCommand("AT+CMGF=1\r", THREADEDGSM_AT_TIMEOUT, "OK\r"); // SMS Text mode
state = SEND_CHK_CMGF;
break;
case SEND_CHK_CMGF:
if(dte.getResult() == DTE::EXPECT_RESULT)
{
CMD = F("AT+CMGS=\"");
CMD += SMSo.Number;
CMD += "\"\r";
dte.SendCommand(CMD.c_str(), 15000, "> ");
state = SEND_CHK_RDY;
}
else clearReq(REQ_OUTBOX);
break;
case SEND_CHK_RDY:
if(dte.getResult() == DTE::EXPECT_RESULT)
{
CMD = SMSo.Text;
CMD += (char)26;
dte.SendCommand(CMD.c_str(), 10000, "OK\r");
state = SEND_CHK_OK;
}else clearReq(REQ_OUTBOX);
break;
case SEND_CHK_OK:
if(dte.getResult() == DTE::EXPECT_RESULT)
{
if(this->configuration.outgoing != NULL)
this->configuration.outgoing(*this);
}
clearReq(REQ_OUTBOX);
break;
}
if(state != lastState)
{
DEBUG_PRINT(F("OUTBOX_STATE: "));
DEBUG_PRINTLN(state);
}
}
}; //ThreadedGSM
#endif //__THREADEDGSM_H__

71
examples/example1.cpp Normal file
View File

@ -0,0 +1,71 @@
/**
* ThreadedGSM Example: Read SMS, Network Time and Signal level
* Reads SMS messages in PDU mode and prints them to debug serial
*/
#include <Arduino.h>
#define SerialDebug Serial1
#define SerialModem Serial
#define THREADEDGSM_DEBUG SerialDebug
#include <ThreadedGSM.h>
ThreadedGSM SIM900(SerialModem);
void clock(ThreadedGSM& modem, ThreadedGSM::NetworkTime& Time)
{
SerialDebug.print("Modem Time: ");
SerialDebug.print(Time.day);
SerialDebug.print("/");
SerialDebug.print(Time.month);
SerialDebug.print("/");
SerialDebug.print(Time.year);
SerialDebug.print(" ");
SerialDebug.print(Time.hour);
SerialDebug.print(":");
SerialDebug.print(Time.minute);
SerialDebug.print(":");
SerialDebug.println(Time.second);
}
void signal(ThreadedGSM& modem, ThreadedGSM::SignalLevel& Signal)
{
SerialDebug.print("Modem signal: Dbm:");
SerialDebug.print(Signal.Dbm);
SerialDebug.print(" value: ");
SerialDebug.println(Signal.Value);
}
void sms(ThreadedGSM& modem, String& Msg)
{
SerialDebug.print("Received SMS: ");
SerialDebug.println(Msg);
}
void startup(ThreadedGSM& modem)
{
SerialDebug.print("Ready");
}
void setup()
{
SerialDebug.begin(115200);
SerialModem.begin(115200);
SerialDebug.println("STARTUP\r\n");
SIM900.begin();
SIM900.setInterval(ThreadedGSM::INTERVAL_CLOCK, 60000);
SIM900.setInterval(ThreadedGSM::INTERVAL_SIGNAL, 60000);
SIM900.setInterval(ThreadedGSM::INTERVAL_INBOX, 30000);
SIM900.setHandlers({
.signal = signal,
.clock = clock,
.incoming = sms,
.ready = startup,
.outgoing = NULL,
.power = NULL
});
}
void loop()
{
SIM900.loop();
}

29
library.json Normal file
View File

@ -0,0 +1,29 @@
{
"name": "ThreadedGSM",
"keywords": "gsm, sim800, sim900, sms, sim800l",
"description": "Non-blocking Arduino GSM Library with SMS support",
"version": "1.0.0",
"repository":
{
"type": "git",
"url": "http://git.xpablo.cz/xPablo.cz/ThreadedGSM.git"
},
"authors":
[
{
"name": "Neta Yahav",
"email": "neta540@gmail.com",
"maintainer": false
},
{
"name": "Pavel Brychta",
"email": "pablo@xpablo.cz",
"maintainer": true
}
],
"frameworks": "arduino",
"platforms": "*",
"examples": [
"[Ee]xamples/*.cpp"
]
}