2023-09-03 12:05:34 +02:00
|
|
|
#include "ThreadedGSM.h"
|
2023-09-03 19:06:43 +02:00
|
|
|
#include <trace.h>
|
2023-09-03 12:05:34 +02:00
|
|
|
|
|
|
|
#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
|
|
|
|
|
|
|
|
ThreadedGSM::ThreadedGSM(Stream & stream)
|
2023-09-03 12:22:16 +02:00
|
|
|
: mStream(stream), mDte(stream, THREADEDGSM_DTE_BUFFER_SIZE), mRingState(RING_WAIT)
|
2023-09-03 12:05:34 +02:00
|
|
|
{
|
|
|
|
|
2023-09-03 12:22:16 +02:00
|
|
|
mSMSo.Text.reserve(150);
|
|
|
|
mSMSi.Text.reserve(150);
|
2023-09-03 12:05:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void ThreadedGSM::nextJob()
|
|
|
|
{
|
2023-09-03 12:22:16 +02:00
|
|
|
|
|
|
|
mJob = 0;
|
2023-09-03 12:05:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void ThreadedGSM::setHandlers(conf config)
|
|
|
|
{
|
|
|
|
|
2023-09-03 12:22:16 +02:00
|
|
|
mConfiguration = config;
|
2023-09-03 12:05:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void ThreadedGSM::setInterval(IntervalSourceE source, unsigned long interval)
|
|
|
|
{
|
2023-09-03 12:22:16 +02:00
|
|
|
|
2023-09-03 12:05:34 +02:00
|
|
|
Intervals[source] = interval;
|
|
|
|
tickSync[source] = millis();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Initialization
|
|
|
|
void ThreadedGSM::begin()
|
|
|
|
{
|
2023-09-03 12:22:16 +02:00
|
|
|
|
|
|
|
mRequests = (REQ_STARTUP);
|
2023-09-03 12:05:34 +02:00
|
|
|
TimeBase.attachLoop(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Call this function for executing thread
|
|
|
|
void ThreadedGSM::exec()
|
|
|
|
{
|
2023-09-03 12:22:16 +02:00
|
|
|
if (mDte.getIsBusy())
|
2023-09-03 12:05:34 +02:00
|
|
|
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:
|
2023-09-03 12:22:16 +02:00
|
|
|
mRequests |= REQ_CLOCK;
|
2023-09-03 12:05:34 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case INTERVAL_INBOX:
|
2023-09-03 12:22:16 +02:00
|
|
|
mRequests |= REQ_INBOX;
|
2023-09-03 12:05:34 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case INTERVAL_SIGNAL:
|
2023-09-03 12:22:16 +02:00
|
|
|
mRequests |= REQ_SIG;
|
2023-09-03 12:05:34 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case INTERVAL_BATTERY:
|
2023-09-03 12:22:16 +02:00
|
|
|
mRequests |= REQ_BATTERY;
|
2023-09-03 12:05:34 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
tickSync[i] = millis();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-09-03 12:22:16 +02:00
|
|
|
if (mJob == 0) {
|
|
|
|
// no assigned mJob, assign it
|
|
|
|
if (mRequests & REQ_CLOCK)
|
|
|
|
mJob = REQ_CLOCK;
|
|
|
|
else if (mRequests & REQ_SIG)
|
|
|
|
mJob = REQ_SIG;
|
|
|
|
else if (mRequests & REQ_INBOX)
|
|
|
|
mJob = REQ_INBOX;
|
|
|
|
else if (mRequests & REQ_OUTBOX)
|
|
|
|
mJob = REQ_OUTBOX;
|
|
|
|
else if (mRequests & REQ_STARTUP)
|
|
|
|
mJob = REQ_STARTUP;
|
|
|
|
else if (mRequests & REQ_BATTERY)
|
|
|
|
mJob = REQ_BATTERY;
|
2023-09-04 17:20:24 +02:00
|
|
|
else if (mRequests & REQ_HANGUP)
|
|
|
|
mJob = REQ_HANGUP;
|
2023-09-03 12:22:16 +02:00
|
|
|
|
|
|
|
if (mJob) {
|
|
|
|
mState = 0;
|
2023-09-03 12:05:34 +02:00
|
|
|
DEBUG_PRINT(F("Job ID: "));
|
2023-09-03 12:22:16 +02:00
|
|
|
DEBUG_PRINTLN(mJob);
|
2023-09-03 12:05:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-09-03 12:22:16 +02:00
|
|
|
// execute current mJob
|
|
|
|
if (mJob == REQ_STARTUP)
|
2023-09-03 12:05:34 +02:00
|
|
|
Startup();
|
2023-09-03 12:22:16 +02:00
|
|
|
else if (mJob == REQ_CLOCK)
|
2023-09-03 12:05:34 +02:00
|
|
|
Clock();
|
2023-09-03 12:22:16 +02:00
|
|
|
else if (mJob == REQ_SIG)
|
2023-09-03 12:05:34 +02:00
|
|
|
Signal();
|
2023-09-03 12:22:16 +02:00
|
|
|
else if (mJob == REQ_INBOX)
|
2023-09-03 12:05:34 +02:00
|
|
|
Inbox();
|
2023-09-03 12:22:16 +02:00
|
|
|
else if (mJob == REQ_OUTBOX)
|
2023-09-03 12:05:34 +02:00
|
|
|
Outbox();
|
2023-09-03 12:22:16 +02:00
|
|
|
else if (mJob == REQ_BATTERY)
|
2023-09-03 12:05:34 +02:00
|
|
|
Battery();
|
2023-09-04 17:20:24 +02:00
|
|
|
else if (mJob == REQ_HANGUP)
|
|
|
|
Hangup();
|
2023-09-03 12:05:34 +02:00
|
|
|
else
|
|
|
|
CheckRing();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Requests
|
|
|
|
void ThreadedGSM::sendSMS(String & Number, String & Text)
|
|
|
|
{
|
2023-09-03 12:22:16 +02:00
|
|
|
mRequests |= (REQ_OUTBOX);
|
|
|
|
mSMSo.Number = Number;
|
|
|
|
mSMSo.Text = Text;
|
2023-09-03 12:05:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void ThreadedGSM::sendSMS(String & Number, const char * Text)
|
|
|
|
{
|
|
|
|
String t = Text;
|
|
|
|
|
|
|
|
sendSMS(Number, t);
|
|
|
|
}
|
|
|
|
|
|
|
|
// States
|
|
|
|
void ThreadedGSM::Startup()
|
|
|
|
{
|
2023-09-03 12:22:16 +02:00
|
|
|
int lastState = mState;
|
|
|
|
switch (mState) {
|
2023-09-03 12:05:34 +02:00
|
|
|
case STARTUP_POWER_OFF:
|
2023-09-03 12:22:16 +02:00
|
|
|
if (mConfiguration.power != nullptr)
|
|
|
|
mConfiguration.power(*this, false);
|
|
|
|
mTick = millis();
|
|
|
|
mState = STARTUP_POWER_OFF_DELAY;
|
2023-09-03 12:05:34 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case STARTUP_POWER_OFF_DELAY:
|
2023-09-03 12:22:16 +02:00
|
|
|
if (millis() - mTick >= THREADEDGSM_STARTUP_POWER_OFF_DELAY)
|
|
|
|
mState = STARTUP_POWER_ON;
|
2023-09-03 12:05:34 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case STARTUP_POWER_ON:
|
2023-09-03 12:22:16 +02:00
|
|
|
if (mConfiguration.power != nullptr)
|
|
|
|
mConfiguration.power(*this, true);
|
2023-09-03 12:05:34 +02:00
|
|
|
// begin delay
|
2023-09-03 12:22:16 +02:00
|
|
|
mTick = millis();
|
|
|
|
mState = STARTUP_DELAY;
|
2023-09-03 12:05:34 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case STARTUP_DELAY:
|
2023-09-03 12:22:16 +02:00
|
|
|
if (millis() - mTick >= THREADEDGSM_STARTUP_DELAY) {
|
|
|
|
mDte.SendCommand(F("AT\r"), THREADEDGSM_AT_TIMEOUT, "OK\r");
|
|
|
|
mState = STARTUP_ENTER_AT;
|
2023-09-03 12:05:34 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case STARTUP_ENTER_AT:
|
2023-09-03 12:22:16 +02:00
|
|
|
if (mDte.getResult() == DTE::EXPECT_RESULT) {
|
|
|
|
mDte.SendCommand(F("AT+CPIN?\r"), 10000, "OK\r");
|
|
|
|
mState = STARTUP_CHK_CPIN;
|
2023-09-03 12:05:34 +02:00
|
|
|
} else {
|
2023-09-03 12:22:16 +02:00
|
|
|
mState = STARTUP_POWER_OFF;
|
2023-09-03 12:05:34 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case STARTUP_CHK_CPIN:
|
2023-09-03 12:22:16 +02:00
|
|
|
if (mDte.getResult() == DTE::EXPECT_RESULT) {
|
|
|
|
if (mDte.getBuffer().indexOf(F("+CPIN: READY")) != -1) {
|
|
|
|
mDte.SendCommand(F("AT+CREG?\r"), THREADEDGSM_AT_TIMEOUT, "OK\r");
|
|
|
|
mState = STARTUP_CHK_CREG;
|
2023-09-03 12:05:34 +02:00
|
|
|
} else {
|
2023-09-03 12:22:16 +02:00
|
|
|
mState = STARTUP_POWER_OFF;
|
2023-09-03 12:05:34 +02:00
|
|
|
}
|
|
|
|
} else
|
2023-09-03 12:22:16 +02:00
|
|
|
mState = STARTUP_POWER_OFF;
|
2023-09-03 12:05:34 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case STARTUP_CHK_CREG:
|
2023-09-03 12:22:16 +02:00
|
|
|
if (mDte.getResult() == DTE::EXPECT_RESULT) {
|
|
|
|
if ((mDte.getBuffer().indexOf(F(",1")) >= 0) || (mDte.getBuffer().indexOf(F(",5")) >= 0)) {
|
|
|
|
mDte.SendCommand(F("AT+CLTS=1\r"), THREADEDGSM_AT_TIMEOUT, "OK\r");
|
|
|
|
mState = STARTUP_CHK_CLTS;
|
2023-09-03 12:05:34 +02:00
|
|
|
} else
|
2023-09-03 12:22:16 +02:00
|
|
|
mState = STARTUP_POWER_OFF;
|
2023-09-03 12:05:34 +02:00
|
|
|
} else
|
2023-09-03 12:22:16 +02:00
|
|
|
mState = STARTUP_POWER_OFF;
|
2023-09-03 12:05:34 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case STARTUP_CHK_CLTS:
|
2023-09-03 12:22:16 +02:00
|
|
|
if (mDte.getResult() == DTE::EXPECT_RESULT) {
|
|
|
|
mDte.SendCommand(F("AT+CENG=3\r"), THREADEDGSM_AT_TIMEOUT, "OK\r");
|
|
|
|
mState = STARTUP_CHK_CENG;
|
2023-09-03 12:05:34 +02:00
|
|
|
} else
|
2023-09-03 12:22:16 +02:00
|
|
|
mState = STARTUP_POWER_OFF;
|
2023-09-03 12:05:34 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case STARTUP_CHK_CENG:
|
2023-09-03 12:22:16 +02:00
|
|
|
if (mDte.getResult() == DTE::EXPECT_RESULT) {
|
2023-09-03 19:06:43 +02:00
|
|
|
mDte.SendCommand(F("AT+CLIP=1\r"), THREADEDGSM_AT_TIMEOUT, "OK\r");
|
|
|
|
mState = STARTUP_CHK_CLIP;
|
2023-09-03 12:05:34 +02:00
|
|
|
} else
|
2023-09-03 12:22:16 +02:00
|
|
|
mState = STARTUP_POWER_OFF;
|
2023-09-03 12:05:34 +02:00
|
|
|
break;
|
2023-09-03 19:06:43 +02:00
|
|
|
|
|
|
|
case STARTUP_CHK_CLIP:
|
|
|
|
if (mDte.getResult() == DTE::EXPECT_RESULT) {
|
|
|
|
startupDone();
|
|
|
|
} else {
|
|
|
|
mState = STARTUP_POWER_OFF;
|
|
|
|
}
|
|
|
|
break;
|
2023-09-03 12:05:34 +02:00
|
|
|
}
|
2023-09-03 12:22:16 +02:00
|
|
|
if (mState != lastState) {
|
2023-09-03 12:05:34 +02:00
|
|
|
DEBUG_PRINT(F("STARTUP_STATE: "));
|
2023-09-03 12:22:16 +02:00
|
|
|
DEBUG_PRINTLN(mState);
|
2023-09-03 12:05:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Threads
|
|
|
|
void ThreadedGSM::Clock()
|
|
|
|
{
|
|
|
|
String clockTime;
|
2023-09-03 12:22:16 +02:00
|
|
|
int lastState = mState;
|
|
|
|
switch (mState) {
|
2023-09-03 12:05:34 +02:00
|
|
|
case CLOCK_REQ:
|
2023-09-03 12:22:16 +02:00
|
|
|
mDte.SendCommand(F("AT+CCLK?\r"), THREADEDGSM_AT_TIMEOUT, "OK\r");
|
|
|
|
mState = CLOCK_VERIFY;
|
2023-09-03 12:05:34 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case CLOCK_VERIFY:
|
2023-09-03 12:22:16 +02:00
|
|
|
int index = mDte.getBuffer().indexOf(F("+CCLK: "));
|
2023-09-03 12:05:34 +02:00
|
|
|
if (index >= 0) {
|
|
|
|
// parse clock
|
|
|
|
index += 8;
|
|
|
|
int endindex;
|
2023-09-03 12:22:16 +02:00
|
|
|
endindex = mDte.getBuffer().indexOf(F("+"), index);
|
2023-09-03 12:05:34 +02:00
|
|
|
if (endindex >= 0)
|
2023-09-03 12:22:16 +02:00
|
|
|
clockTime = mDte.getBuffer().substring(index, endindex);
|
2023-09-03 12:05:34 +02:00
|
|
|
else {
|
2023-09-03 12:22:16 +02:00
|
|
|
endindex = mDte.getBuffer().indexOf(F("-"), index);
|
2023-09-03 12:05:34 +02:00
|
|
|
if (endindex >= 0)
|
2023-09-03 12:22:16 +02:00
|
|
|
clockTime = mDte.getBuffer().substring(index, endindex);
|
2023-09-03 12:05:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
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();
|
2023-09-03 12:22:16 +02:00
|
|
|
if (mConfiguration.clock != nullptr)
|
|
|
|
mConfiguration.clock(*this, ClockTime);
|
2023-09-03 12:05:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
clearReq(REQ_CLOCK);
|
|
|
|
break;
|
|
|
|
}
|
2023-09-03 12:22:16 +02:00
|
|
|
if (mState != lastState) {
|
2023-09-03 12:05:34 +02:00
|
|
|
DEBUG_PRINT(F("CLOCK_STATE: "));
|
2023-09-03 12:22:16 +02:00
|
|
|
DEBUG_PRINTLN(mState);
|
2023-09-03 12:05:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ThreadedGSM::Signal()
|
|
|
|
{
|
2023-09-03 12:22:16 +02:00
|
|
|
int lastState = mState;
|
|
|
|
switch (mState) {
|
2023-09-03 12:05:34 +02:00
|
|
|
case SIGNAL_REQ:
|
2023-09-03 12:22:16 +02:00
|
|
|
mDte.SendCommand(F("AT+CSQ\r"), THREADEDGSM_AT_TIMEOUT, "OK\r");
|
|
|
|
mState = SIGNAL_VERIFY;
|
2023-09-03 12:05:34 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SIGNAL_VERIFY:
|
2023-09-03 12:22:16 +02:00
|
|
|
int index = mDte.getBuffer().indexOf(F("+CSQ: "));
|
2023-09-03 12:05:34 +02:00
|
|
|
if (index >= 0) {
|
|
|
|
// parse signal
|
|
|
|
index += 6;
|
|
|
|
SignalLevel GsmSignal{};
|
2023-09-03 12:22:16 +02:00
|
|
|
GsmSignal.Value = mDte.getBuffer().substring(index, index + 2).toInt();
|
|
|
|
GsmSignal.Dbm = mDte.getBuffer().substring(index + 3, index + 5).toInt();
|
2023-09-03 12:05:34 +02:00
|
|
|
if (GsmSignal.Value != 0) {
|
2023-09-03 12:22:16 +02:00
|
|
|
if (mConfiguration.signal != nullptr)
|
|
|
|
mConfiguration.signal(*this, GsmSignal);
|
2023-09-03 12:05:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
clearReq(REQ_SIG);
|
|
|
|
break;
|
|
|
|
}
|
2023-09-03 12:22:16 +02:00
|
|
|
if (mState != lastState) {
|
2023-09-03 12:05:34 +02:00
|
|
|
DEBUG_PRINT(F("SIGNAL_STATE: "));
|
2023-09-03 12:22:16 +02:00
|
|
|
DEBUG_PRINTLN(mState);
|
2023-09-03 12:05:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ThreadedGSM::Battery()
|
|
|
|
{
|
2023-09-03 12:22:16 +02:00
|
|
|
int lastState = mState;
|
|
|
|
switch (mState) {
|
2023-09-03 12:05:34 +02:00
|
|
|
case BATTERY_REQ:
|
2023-09-03 12:22:16 +02:00
|
|
|
mDte.SendCommand(F("AT+CBC\r"), THREADEDGSM_AT_TIMEOUT, "OK\r");
|
|
|
|
mState = BATTERY_VERIFY;
|
2023-09-03 12:05:34 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case BATTERY_VERIFY:
|
2023-09-03 12:22:16 +02:00
|
|
|
int index = mDte.getBuffer().indexOf(F("+CBC:"));
|
2023-09-03 12:05:34 +02:00
|
|
|
if (index >= 0) {
|
|
|
|
BatteryInfo BattInfo{};
|
|
|
|
// parse battery level
|
2023-09-03 12:22:16 +02:00
|
|
|
String buffer = mDte.getBuffer().substring(index);
|
2023-09-03 12:05:34 +02:00
|
|
|
String buffer2 = buffer.substring(buffer.indexOf(F(",")) + 1);
|
|
|
|
buffer = buffer2;
|
2023-09-03 12:22:16 +02:00
|
|
|
BattInfo.Percent = buffer2.substring(0, buffer2.indexOf(F(","))).toInt(); // converts the mResult to interger
|
2023-09-03 12:05:34 +02:00
|
|
|
buffer2 = buffer.substring(buffer.indexOf(F(",")) + 1);
|
2023-09-03 12:22:16 +02:00
|
|
|
BattInfo.Voltage = buffer2.substring(0, buffer2.indexOf(F("\r"))).toInt(); // converts the mResult to interger
|
|
|
|
if (mConfiguration.battery != nullptr)
|
|
|
|
mConfiguration.battery(*this, BattInfo);
|
2023-09-03 12:05:34 +02:00
|
|
|
}
|
|
|
|
clearReq(REQ_BATTERY);
|
|
|
|
break;
|
|
|
|
}
|
2023-09-03 12:22:16 +02:00
|
|
|
if (mState != lastState) {
|
2023-09-03 12:05:34 +02:00
|
|
|
DEBUG_PRINT(F("BATTERY_STATE: "));
|
2023-09-03 12:22:16 +02:00
|
|
|
DEBUG_PRINTLN(mState);
|
2023-09-03 12:05:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-09-04 17:20:24 +02:00
|
|
|
void ThreadedGSM::Hangup()
|
|
|
|
{
|
|
|
|
int lastState = mState;
|
|
|
|
|
|
|
|
switch (mState) {
|
|
|
|
case HANGUP_REQ:
|
|
|
|
mDte.SendCommand(F("ATH\r"), THREADEDGSM_AT_TIMEOUT, "OK\r");
|
|
|
|
mState = HANGUP_CHK;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case HANGUP_CHK:
|
|
|
|
if (mDte.getResult() == DTE::EXPECT_RESULT) {
|
|
|
|
clearReq(REQ_HANGUP);
|
|
|
|
} else
|
|
|
|
clearReq(REQ_HANGUP);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (mState != lastState) {
|
|
|
|
DEBUG_PRINT(F("HANGUP_STATE: "));
|
|
|
|
DEBUG_PRINTLN(mState);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-09-03 12:05:34 +02:00
|
|
|
void ThreadedGSM::clearReq(int req)
|
|
|
|
{
|
2023-09-03 12:22:16 +02:00
|
|
|
mRequests &= ~(req);
|
2023-09-03 19:06:43 +02:00
|
|
|
mDte.clearBuffer();
|
2023-09-03 12:05:34 +02:00
|
|
|
nextJob();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ThreadedGSM::Inbox()
|
|
|
|
{
|
|
|
|
String CMD;
|
2023-09-03 12:22:16 +02:00
|
|
|
int lastState = mState;
|
|
|
|
switch (mState) {
|
2023-09-03 12:05:34 +02:00
|
|
|
case READ_REQ:
|
2023-09-03 12:22:16 +02:00
|
|
|
mSMSi.Text = "";
|
|
|
|
mSMSi.Number = "";
|
|
|
|
mDte.SendCommand(F("AT+CMGF=0\r"), THREADEDGSM_AT_TIMEOUT, "OK\r"); // SMS Message format set as PDU
|
|
|
|
mState = READ_CHK_CMGF;
|
2023-09-03 12:05:34 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case READ_CHK_CMGF:
|
2023-09-03 12:22:16 +02:00
|
|
|
if (mDte.getResult() == DTE::EXPECT_RESULT) {
|
|
|
|
mDte.SendCommand(F("AT+CPMS=\"SM\"\r"), THREADEDGSM_AT_TIMEOUT, "OK\r"); // SIM Message storage
|
|
|
|
mState = READ_CHK_CPMS;
|
2023-09-03 12:05:34 +02:00
|
|
|
} else
|
|
|
|
clearReq(REQ_INBOX);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case READ_CHK_CPMS:
|
2023-09-03 12:22:16 +02:00
|
|
|
if (mDte.getResult() == DTE::EXPECT_RESULT) {
|
2023-09-03 12:05:34 +02:00
|
|
|
CMD = F("AT+CMGL="); // Read all SMS messages
|
|
|
|
CMD += (int) READ_TYPE_ALL;
|
|
|
|
CMD += "\r";
|
2023-09-03 12:22:16 +02:00
|
|
|
mDte.SendCommand(CMD.c_str(), THREADEDGSM_AT_TIMEOUT, ",");
|
|
|
|
mState = READ_CHK_CMGL;
|
2023-09-03 12:05:34 +02:00
|
|
|
} else
|
|
|
|
clearReq(REQ_INBOX);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case READ_CHK_CMGL:
|
2023-09-03 12:22:16 +02:00
|
|
|
if (mDte.getResult() == DTE::EXPECT_RESULT) {
|
2023-09-03 12:05:34 +02:00
|
|
|
// fetch index
|
2023-09-03 19:06:43 +02:00
|
|
|
String & buffer = mDte.getBuffer();
|
|
|
|
int indexStart = buffer.indexOf(F("+CMGL: "));
|
2023-09-03 12:05:34 +02:00
|
|
|
if (indexStart >= 0) {
|
2023-09-03 19:06:43 +02:00
|
|
|
Message.Index = buffer.substring(indexStart + 7, buffer.indexOf(F(","))).toInt();
|
2023-09-03 12:05:34 +02:00
|
|
|
if (Message.Index != 0) {
|
2023-09-03 12:22:16 +02:00
|
|
|
mDte.Delay(2000);
|
|
|
|
mState = READ_DELAY_CLEAR_BUFF;
|
2023-09-03 12:05:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-09-03 12:22:16 +02:00
|
|
|
if (mState != READ_DELAY_CLEAR_BUFF)
|
2023-09-03 12:05:34 +02:00
|
|
|
clearReq(REQ_INBOX);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case READ_DELAY_CLEAR_BUFF:
|
2023-09-03 12:22:16 +02:00
|
|
|
mDte.SendCommand(F("AT+CMGF=1\r"), THREADEDGSM_AT_TIMEOUT, "OK\r"); // SMS Message format set as TEXT
|
|
|
|
mState = READ_TEXT_CMGR;
|
2023-09-03 12:05:34 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case READ_TEXT_CMGR:
|
2023-09-03 12:22:16 +02:00
|
|
|
if (mDte.getResult() == DTE::EXPECT_RESULT) {
|
2023-09-03 12:05:34 +02:00
|
|
|
CMD = F("AT+CMGR="); // Read the SMS message
|
|
|
|
CMD += Message.Index;
|
|
|
|
CMD += "\r";
|
2023-09-03 12:22:16 +02:00
|
|
|
mDte.SendCommand(CMD.c_str(), THREADEDGSM_AT_TIMEOUT, "OK\r");
|
|
|
|
mState = READ_CHK_CMGR;
|
2023-09-03 12:05:34 +02:00
|
|
|
} else
|
|
|
|
clearReq(REQ_INBOX);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case READ_CHK_CMGR:
|
2023-09-03 12:22:16 +02:00
|
|
|
if (mDte.getResult() == DTE::EXPECT_RESULT) {
|
|
|
|
int indexStart = mDte.getBuffer().indexOf(F("+CMGR: "));
|
2023-09-03 12:05:34 +02:00
|
|
|
if (indexStart >= 0) {
|
2023-09-03 12:22:16 +02:00
|
|
|
int indexStartPDU = mDte.getBuffer().indexOf(F("\r\n"), indexStart);
|
2023-09-03 12:05:34 +02:00
|
|
|
if (indexStartPDU >= 0) {
|
|
|
|
indexStartPDU += 2;
|
2023-09-03 12:22:16 +02:00
|
|
|
int indexEndPDU = mDte.getBuffer().indexOf(F("\r"), indexStartPDU);
|
2023-09-03 12:05:34 +02:00
|
|
|
if (indexEndPDU >= 0)
|
2023-09-03 12:22:16 +02:00
|
|
|
mSMSi.Text = mDte.getBuffer().substring(indexStartPDU, indexEndPDU);
|
2023-09-03 12:05:34 +02:00
|
|
|
}
|
2023-09-03 12:22:16 +02:00
|
|
|
indexStartPDU = mDte.getBuffer().indexOf(F(",\""), indexStart);
|
2023-09-03 12:05:34 +02:00
|
|
|
if (indexStartPDU >= 0) {
|
|
|
|
indexStartPDU += 2;
|
2023-09-03 12:22:16 +02:00
|
|
|
int indexEndPDU = mDte.getBuffer().indexOf(F("\","), indexStartPDU);
|
2023-09-03 12:05:34 +02:00
|
|
|
if (indexEndPDU >= 0)
|
2023-09-03 12:22:16 +02:00
|
|
|
mSMSi.Number = mDte.getBuffer().substring(indexStartPDU, indexEndPDU);
|
2023-09-03 12:05:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
CMD = F("AT+CMGD="); // Delete the SMS message
|
|
|
|
CMD += Message.Index;
|
|
|
|
CMD += "\r";
|
2023-09-03 12:22:16 +02:00
|
|
|
mDte.SendCommand(CMD.c_str(), THREADEDGSM_AT_TIMEOUT, "OK\r");
|
|
|
|
mState = READ_CHK_CMGD;
|
2023-09-03 12:05:34 +02:00
|
|
|
} else
|
|
|
|
clearReq(REQ_INBOX);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case READ_CHK_CMGD:
|
2023-09-03 12:22:16 +02:00
|
|
|
// if( (mDte.getResult() == DTE::EXPECT_RESULT) && (SMS.InboxMsgContents != ""))
|
|
|
|
if (mDte.getResult() == DTE::EXPECT_RESULT) {
|
|
|
|
if (mConfiguration.incoming != nullptr)
|
|
|
|
mConfiguration.incoming(*this, mSMSi);
|
2023-09-03 12:05:34 +02:00
|
|
|
}
|
|
|
|
clearReq(REQ_INBOX);
|
|
|
|
break;
|
|
|
|
}
|
2023-09-03 12:22:16 +02:00
|
|
|
if (mState != lastState) {
|
2023-09-03 12:05:34 +02:00
|
|
|
DEBUG_PRINT(F("INBOX_STATE: "));
|
2023-09-03 12:22:16 +02:00
|
|
|
DEBUG_PRINTLN(mState);
|
2023-09-03 12:05:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ThreadedGSM::Outbox()
|
|
|
|
{
|
|
|
|
String CMD;
|
|
|
|
|
|
|
|
// CMD.reserve(200);
|
2023-09-03 12:22:16 +02:00
|
|
|
int lastState = mState;
|
|
|
|
switch (mState) {
|
2023-09-03 12:05:34 +02:00
|
|
|
case SEND_REQ:
|
2023-09-03 12:22:16 +02:00
|
|
|
mDte.SendCommand(F("AT+CMGF=1\r"), THREADEDGSM_AT_TIMEOUT, "OK\r"); // SMS Text mode
|
|
|
|
mState = SEND_CHK_CMGF;
|
2023-09-03 12:05:34 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SEND_CHK_CMGF:
|
2023-09-03 12:22:16 +02:00
|
|
|
if (mDte.getResult() == DTE::EXPECT_RESULT) {
|
2023-09-03 12:05:34 +02:00
|
|
|
CMD = F("AT+CMGS=\"");
|
2023-09-03 12:22:16 +02:00
|
|
|
CMD += mSMSo.Number;
|
2023-09-03 12:05:34 +02:00
|
|
|
CMD += "\"\r";
|
2023-09-03 12:22:16 +02:00
|
|
|
mDte.SendCommand(CMD.c_str(), 15000, "> ");
|
|
|
|
mState = SEND_CHK_RDY;
|
2023-09-03 12:05:34 +02:00
|
|
|
} else
|
|
|
|
clearReq(REQ_OUTBOX);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SEND_CHK_RDY:
|
2023-09-03 12:22:16 +02:00
|
|
|
if (mDte.getResult() == DTE::EXPECT_RESULT) {
|
|
|
|
CMD = mSMSo.Text;
|
2023-09-03 12:05:34 +02:00
|
|
|
CMD += (char) 26;
|
2023-09-03 12:22:16 +02:00
|
|
|
mDte.SendCommand(CMD.c_str(), 10000, "OK\r");
|
|
|
|
mState = SEND_CHK_OK;
|
2023-09-03 12:05:34 +02:00
|
|
|
} else
|
|
|
|
clearReq(REQ_OUTBOX);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SEND_CHK_OK:
|
2023-09-03 12:22:16 +02:00
|
|
|
if (mDte.getResult() == DTE::EXPECT_RESULT) {
|
|
|
|
if (mConfiguration.outgoing != nullptr)
|
|
|
|
mConfiguration.outgoing(*this);
|
2023-09-03 12:05:34 +02:00
|
|
|
}
|
|
|
|
clearReq(REQ_OUTBOX);
|
|
|
|
break;
|
|
|
|
}
|
2023-09-03 12:22:16 +02:00
|
|
|
if (mState != lastState) {
|
2023-09-03 12:05:34 +02:00
|
|
|
DEBUG_PRINT(F("OUTBOX_STATE: "));
|
2023-09-03 12:22:16 +02:00
|
|
|
DEBUG_PRINTLN(mState);
|
2023-09-03 12:05:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ThreadedGSM::CheckRing()
|
|
|
|
{
|
2023-09-03 19:06:43 +02:00
|
|
|
|
2023-09-04 17:20:24 +02:00
|
|
|
if (mDte.buffer()) {
|
|
|
|
String & buffer = mDte.getBuffer();
|
|
|
|
|
|
|
|
if (buffer.length() > 0) {
|
|
|
|
bool dump = true;
|
|
|
|
|
|
|
|
if (buffer.startsWith(F("+CLIP: \""))) {
|
|
|
|
// CLIP (RING) detected
|
|
|
|
if (mConfiguration.ring) {
|
|
|
|
int index = 8;
|
|
|
|
int endindex;
|
2023-09-03 19:06:43 +02:00
|
|
|
|
2023-09-04 17:20:24 +02:00
|
|
|
endindex = buffer.indexOf(F("\""), index);
|
|
|
|
if (endindex >= 0) {
|
|
|
|
String num = buffer.substring(index, endindex);
|
2023-09-03 19:06:43 +02:00
|
|
|
|
2023-09-04 17:20:24 +02:00
|
|
|
mConfiguration.ring(*this, num);
|
|
|
|
dump = false;
|
|
|
|
}
|
2023-09-03 19:06:43 +02:00
|
|
|
}
|
2023-09-04 17:20:24 +02:00
|
|
|
} else if (buffer.startsWith(F("NO CARRIER"))) {
|
|
|
|
// end of call detected
|
|
|
|
if (mConfiguration.ring) {
|
|
|
|
String num = F("end");
|
2023-09-03 12:05:34 +02:00
|
|
|
|
2023-09-04 17:20:24 +02:00
|
|
|
mConfiguration.ring(*this, num);
|
|
|
|
dump = false;
|
|
|
|
}
|
|
|
|
} else if (buffer.startsWith(F("+CMTI: \"SM\""))) {
|
|
|
|
// SMS receive detected
|
|
|
|
if (mConfiguration.incoming) {
|
|
|
|
mRequests |= (REQ_INBOX);
|
|
|
|
dump = false;
|
|
|
|
}
|
2023-09-03 12:05:34 +02:00
|
|
|
}
|
2023-09-04 17:20:24 +02:00
|
|
|
if (dump) {
|
|
|
|
TRACE(TRACE_DEBUG, F("Gsm: %s"), buffer.c_str());
|
|
|
|
}
|
|
|
|
mDte.clearBuffer();
|
|
|
|
}
|
2023-09-03 12:05:34 +02:00
|
|
|
}
|
|
|
|
}
|
2023-09-03 19:06:43 +02:00
|
|
|
|
|
|
|
void ThreadedGSM::startupDone()
|
|
|
|
{
|
2023-09-04 17:20:24 +02:00
|
|
|
if (mConfiguration.clock)
|
|
|
|
mRequests |= (REQ_CLOCK);
|
|
|
|
if (mConfiguration.battery)
|
|
|
|
mRequests |= (REQ_BATTERY);
|
|
|
|
if (mConfiguration.signal)
|
|
|
|
mRequests |= (REQ_SIG);
|
|
|
|
if (mConfiguration.incoming)
|
|
|
|
mRequests |= (REQ_INBOX);
|
2023-09-03 19:06:43 +02:00
|
|
|
clearReq(REQ_STARTUP);
|
|
|
|
for (unsigned long & i : tickSync)
|
|
|
|
i = millis();
|
|
|
|
if (mConfiguration.ready != nullptr)
|
|
|
|
mConfiguration.ready(*this);
|
|
|
|
}
|
2023-09-04 17:20:24 +02:00
|
|
|
|
|
|
|
void ThreadedGSM::hangup()
|
|
|
|
{
|
|
|
|
|
|
|
|
mRequests |= (REQ_HANGUP);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ThreadedGSM::restartModem()
|
|
|
|
{
|
|
|
|
|
|
|
|
mRequests |= (REQ_STARTUP);
|
|
|
|
}
|