Rozdeleni h/cpp, prechod na potomka Executable
This commit is contained in:
		
							
								
								
									
										122
									
								
								src/DTE.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										122
									
								
								src/DTE.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,122 @@
 | 
			
		||||
#include "DTE.h"
 | 
			
		||||
 | 
			
		||||
DTE::DTE(Stream & stream, unsigned int size)
 | 
			
		||||
    : stream(stream), bufferSize(size), result(EXPECT_RESULT)
 | 
			
		||||
{
 | 
			
		||||
    buffer.reserve(size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DTE::SendCommand(const char * command, unsigned long timeout, const char * response1, const char * response2, const char * response3)
 | 
			
		||||
{
 | 
			
		||||
    match = 0;
 | 
			
		||||
    result = EXPECT_BUSY;
 | 
			
		||||
    response[0] = response1;
 | 
			
		||||
    response[1] = response2;
 | 
			
		||||
    response[2] = response3;
 | 
			
		||||
    this->timeout = timeout;
 | 
			
		||||
    flush();
 | 
			
		||||
    stream.print(command);
 | 
			
		||||
    buffer = "";
 | 
			
		||||
    tick = millis();
 | 
			
		||||
    process();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DTE::SendCommand(const __FlashStringHelper * command, unsigned long timeout, const char * response1, const char * response2, const char * response3)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    match = 0;
 | 
			
		||||
    result = EXPECT_BUSY;
 | 
			
		||||
    response[0] = response1;
 | 
			
		||||
    response[1] = response2;
 | 
			
		||||
    response[2] = response3;
 | 
			
		||||
    this->timeout = timeout;
 | 
			
		||||
    // clear rx buffer
 | 
			
		||||
    flush();
 | 
			
		||||
    // send command
 | 
			
		||||
    stream.print((const __FlashStringHelper *) command);
 | 
			
		||||
    buffer = "";
 | 
			
		||||
    tick = millis();
 | 
			
		||||
    process();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DTE::Delay(unsigned long delay)
 | 
			
		||||
{
 | 
			
		||||
    timeout = delay;
 | 
			
		||||
    result = EXPECT_DELAY;
 | 
			
		||||
    tick = millis();
 | 
			
		||||
    process();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool DTE::getIsBusy()
 | 
			
		||||
{
 | 
			
		||||
    process();
 | 
			
		||||
    return (result == EXPECT_BUSY) || (result == EXPECT_DELAY);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DTE::CommandResult DTE::getResult()
 | 
			
		||||
{
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
unsigned int DTE::getMatch() const
 | 
			
		||||
{
 | 
			
		||||
    return match;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
String & DTE::getBuffer()
 | 
			
		||||
{
 | 
			
		||||
    return buffer;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DTE::flush()
 | 
			
		||||
{
 | 
			
		||||
    // clear rx buffer
 | 
			
		||||
    while (stream.available()) {
 | 
			
		||||
        stream.read();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DTE::process()
 | 
			
		||||
{
 | 
			
		||||
    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.concat(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;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										128
									
								
								src/DTE.h
									
									
									
									
									
								
							
							
						
						
									
										128
									
								
								src/DTE.h
									
									
									
									
									
								
							@@ -1,8 +1,7 @@
 | 
			
		||||
/*
 | 
			
		||||
 * DTE.h
 | 
			
		||||
 *
 | 
			
		||||
 * Created: 20/09/2016 15:40:51
 | 
			
		||||
 * Author: Neta Yahav
 | 
			
		||||
 * Author: Neta Yahav, Pavel Brychta
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
@@ -18,7 +17,7 @@ class DTE {
 | 
			
		||||
        EXPECT_RESULT
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
  private:
 | 
			
		||||
  protected:
 | 
			
		||||
    String buffer;
 | 
			
		||||
    Stream & stream;
 | 
			
		||||
    unsigned int bufferSize;
 | 
			
		||||
@@ -29,127 +28,26 @@ class DTE {
 | 
			
		||||
    CommandResult result;
 | 
			
		||||
 | 
			
		||||
  public:
 | 
			
		||||
    DTE(Stream & stream, unsigned int size)
 | 
			
		||||
        : stream(stream), bufferSize(size), result(EXPECT_RESULT)
 | 
			
		||||
    {
 | 
			
		||||
        buffer.reserve(size);
 | 
			
		||||
    }
 | 
			
		||||
    DTE(Stream & stream, unsigned int size);
 | 
			
		||||
 | 
			
		||||
    ~DTE() = default;
 | 
			
		||||
 | 
			
		||||
    void SendCommand(const char * command, unsigned long timeout, const char * response1, const char * response2 = nullptr, const char * response3 = nullptr)
 | 
			
		||||
    {
 | 
			
		||||
        match = 0;
 | 
			
		||||
        result = EXPECT_BUSY;
 | 
			
		||||
        response[0] = response1;
 | 
			
		||||
        response[1] = response2;
 | 
			
		||||
        response[2] = response3;
 | 
			
		||||
        this->timeout = timeout;
 | 
			
		||||
        flush();
 | 
			
		||||
        stream.print(command);
 | 
			
		||||
        buffer = "";
 | 
			
		||||
        tick = millis();
 | 
			
		||||
        proccess();
 | 
			
		||||
    }
 | 
			
		||||
    void SendCommand(const char * command, unsigned long timeout, const char * response1, const char * response2 = nullptr, const char * response3 = nullptr);
 | 
			
		||||
 | 
			
		||||
    void SendCommand(const __FlashStringHelper * command, unsigned long timeout, const char * response1, const char * response2 = nullptr, const char * response3 = nullptr)
 | 
			
		||||
    {
 | 
			
		||||
    void SendCommand(const __FlashStringHelper * command, unsigned long timeout, const char * response1, const char * response2 = nullptr, const char * response3 = nullptr);
 | 
			
		||||
 | 
			
		||||
        match = 0;
 | 
			
		||||
        result = EXPECT_BUSY;
 | 
			
		||||
        response[0] = response1;
 | 
			
		||||
        response[1] = response2;
 | 
			
		||||
        response[2] = response3;
 | 
			
		||||
        this->timeout = timeout;
 | 
			
		||||
        // clear rx buffer
 | 
			
		||||
        flush();
 | 
			
		||||
        // send command
 | 
			
		||||
        stream.print((const __FlashStringHelper *) command);
 | 
			
		||||
        buffer = "";
 | 
			
		||||
        tick = millis();
 | 
			
		||||
        proccess();
 | 
			
		||||
    }
 | 
			
		||||
    void Delay(unsigned long delay);
 | 
			
		||||
 | 
			
		||||
    void Delay(unsigned long delay)
 | 
			
		||||
    {
 | 
			
		||||
        timeout = delay;
 | 
			
		||||
        result = EXPECT_DELAY;
 | 
			
		||||
        tick = millis();
 | 
			
		||||
        proccess();
 | 
			
		||||
    }
 | 
			
		||||
    bool getIsBusy();
 | 
			
		||||
 | 
			
		||||
    bool getIsBusy()
 | 
			
		||||
    {
 | 
			
		||||
        proccess();
 | 
			
		||||
        return (result == EXPECT_BUSY) || (result == EXPECT_DELAY);
 | 
			
		||||
    }
 | 
			
		||||
    CommandResult getResult();
 | 
			
		||||
 | 
			
		||||
    CommandResult getResult()
 | 
			
		||||
    {
 | 
			
		||||
        return result;
 | 
			
		||||
    }
 | 
			
		||||
    [[nodiscard]] unsigned int getMatch() const;
 | 
			
		||||
 | 
			
		||||
    unsigned int getMatch() const
 | 
			
		||||
    {
 | 
			
		||||
        return match;
 | 
			
		||||
    }
 | 
			
		||||
    String & getBuffer();
 | 
			
		||||
 | 
			
		||||
    String & getBuffer()
 | 
			
		||||
    {
 | 
			
		||||
        return buffer;
 | 
			
		||||
    }
 | 
			
		||||
  protected:
 | 
			
		||||
    void flush();
 | 
			
		||||
 | 
			
		||||
  private:
 | 
			
		||||
    void flush()
 | 
			
		||||
    {
 | 
			
		||||
        // clear rx buffer
 | 
			
		||||
        while (stream.available()) {
 | 
			
		||||
            stream.read();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    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.concat(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;
 | 
			
		||||
    }
 | 
			
		||||
    void process();
 | 
			
		||||
}; // DTE
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										512
									
								
								src/ThreadedGSM.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										512
									
								
								src/ThreadedGSM.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,512 @@
 | 
			
		||||
#include "ThreadedGSM.h"
 | 
			
		||||
 | 
			
		||||
#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)
 | 
			
		||||
    : stream(stream), dte(stream, THREADEDGSM_DTE_BUFFER_SIZE), ringState(RING_WAIT)
 | 
			
		||||
{
 | 
			
		||||
    for (unsigned long & Interval : Intervals)
 | 
			
		||||
        Interval = 0;
 | 
			
		||||
 | 
			
		||||
    job = state = requests = 0;
 | 
			
		||||
    // SMSo.Text.reserve(150);
 | 
			
		||||
    // SMSi.Text.reserve(150);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ThreadedGSM::nextJob()
 | 
			
		||||
{
 | 
			
		||||
    job = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ThreadedGSM::setHandlers(conf config)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    this->configuration = config;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ThreadedGSM::setInterval(IntervalSourceE source, unsigned long interval)
 | 
			
		||||
{
 | 
			
		||||
    Intervals[source] = interval;
 | 
			
		||||
    tickSync[source] = millis();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Initialization
 | 
			
		||||
void ThreadedGSM::begin()
 | 
			
		||||
{
 | 
			
		||||
    requests = (REQ_STARTUP);
 | 
			
		||||
    TimeBase.attachLoop(this);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Call this function for executing thread
 | 
			
		||||
void ThreadedGSM::exec()
 | 
			
		||||
{
 | 
			
		||||
    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();
 | 
			
		||||
    else
 | 
			
		||||
        CheckRing();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Requests
 | 
			
		||||
void ThreadedGSM::sendSMS(String & Number, String & Text)
 | 
			
		||||
{
 | 
			
		||||
    requests |= (REQ_OUTBOX);
 | 
			
		||||
    SMSo.Number = Number;
 | 
			
		||||
    SMSo.Text = Text;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ThreadedGSM::sendSMS(String & Number, const char * Text)
 | 
			
		||||
{
 | 
			
		||||
    String t = Text;
 | 
			
		||||
 | 
			
		||||
    sendSMS(Number, t);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// States
 | 
			
		||||
void ThreadedGSM::Startup()
 | 
			
		||||
{
 | 
			
		||||
    int lastState = state;
 | 
			
		||||
    switch (state) {
 | 
			
		||||
        case STARTUP_POWER_OFF:
 | 
			
		||||
            if (this->configuration.power != nullptr)
 | 
			
		||||
                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 != nullptr)
 | 
			
		||||
                this->configuration.power(*this, true);
 | 
			
		||||
            // begin delay
 | 
			
		||||
            tick = millis();
 | 
			
		||||
            state = STARTUP_DELAY;
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        case STARTUP_DELAY:
 | 
			
		||||
            if (millis() - tick >= THREADEDGSM_STARTUP_DELAY) {
 | 
			
		||||
                dte.SendCommand(F("AT\r"), THREADEDGSM_AT_TIMEOUT, "OK\r");
 | 
			
		||||
                state = STARTUP_ENTER_AT;
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        case STARTUP_ENTER_AT:
 | 
			
		||||
            if (dte.getResult() == DTE::EXPECT_RESULT) {
 | 
			
		||||
                dte.SendCommand(F("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(F("+CPIN: READY")) != -1) {
 | 
			
		||||
                    dte.SendCommand(F("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(F(",1")) >= 0) || (dte.getBuffer().indexOf(F(",5")) >= 0)) {
 | 
			
		||||
                    dte.SendCommand(F("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(F("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 != nullptr)
 | 
			
		||||
                    this->configuration.ready(*this);
 | 
			
		||||
            } else
 | 
			
		||||
                state = STARTUP_POWER_OFF;
 | 
			
		||||
            break;
 | 
			
		||||
    }
 | 
			
		||||
    if (state != lastState) {
 | 
			
		||||
        DEBUG_PRINT(F("STARTUP_STATE: "));
 | 
			
		||||
        DEBUG_PRINTLN(state);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Threads
 | 
			
		||||
void ThreadedGSM::Clock()
 | 
			
		||||
{
 | 
			
		||||
    String clockTime;
 | 
			
		||||
    int lastState = state;
 | 
			
		||||
    switch (state) {
 | 
			
		||||
        case CLOCK_REQ:
 | 
			
		||||
            dte.SendCommand(F("AT+CCLK?\r"), THREADEDGSM_AT_TIMEOUT, "OK\r");
 | 
			
		||||
            state = CLOCK_VERIFY;
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        case CLOCK_VERIFY:
 | 
			
		||||
            int index = dte.getBuffer().indexOf(F("+CCLK: "));
 | 
			
		||||
            if (index >= 0) {
 | 
			
		||||
                // parse clock
 | 
			
		||||
                index += 8;
 | 
			
		||||
                int endindex;
 | 
			
		||||
                endindex = dte.getBuffer().indexOf(F("+"), index);
 | 
			
		||||
                if (endindex >= 0)
 | 
			
		||||
                    clockTime = dte.getBuffer().substring(index, endindex);
 | 
			
		||||
                else {
 | 
			
		||||
                    endindex = dte.getBuffer().indexOf(F("-"), 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 != nullptr)
 | 
			
		||||
                        this->configuration.clock(*this, ClockTime);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            clearReq(REQ_CLOCK);
 | 
			
		||||
            break;
 | 
			
		||||
    }
 | 
			
		||||
    if (state != lastState) {
 | 
			
		||||
        DEBUG_PRINT(F("CLOCK_STATE: "));
 | 
			
		||||
        DEBUG_PRINTLN(state);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ThreadedGSM::Signal()
 | 
			
		||||
{
 | 
			
		||||
    int lastState = state;
 | 
			
		||||
    switch (state) {
 | 
			
		||||
        case SIGNAL_REQ:
 | 
			
		||||
            dte.SendCommand(F("AT+CSQ\r"), THREADEDGSM_AT_TIMEOUT, "OK\r");
 | 
			
		||||
            state = SIGNAL_VERIFY;
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        case SIGNAL_VERIFY:
 | 
			
		||||
            int index = dte.getBuffer().indexOf(F("+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 != nullptr)
 | 
			
		||||
                        this->configuration.signal(*this, GsmSignal);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            clearReq(REQ_SIG);
 | 
			
		||||
            break;
 | 
			
		||||
    }
 | 
			
		||||
    if (state != lastState) {
 | 
			
		||||
        DEBUG_PRINT(F("SIGNAL_STATE: "));
 | 
			
		||||
        DEBUG_PRINTLN(state);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ThreadedGSM::Battery()
 | 
			
		||||
{
 | 
			
		||||
    int lastState = state;
 | 
			
		||||
    switch (state) {
 | 
			
		||||
        case BATTERY_REQ:
 | 
			
		||||
            dte.SendCommand(F("AT+CBC\r"), THREADEDGSM_AT_TIMEOUT, "OK\r");
 | 
			
		||||
            state = BATTERY_VERIFY;
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        case BATTERY_VERIFY:
 | 
			
		||||
            int index = dte.getBuffer().indexOf(F("+CBC:"));
 | 
			
		||||
            if (index >= 0) {
 | 
			
		||||
                BatteryInfo BattInfo{};
 | 
			
		||||
                // parse battery level
 | 
			
		||||
                String buffer = dte.getBuffer().substring(index);
 | 
			
		||||
                String buffer2 = buffer.substring(buffer.indexOf(F(",")) + 1);
 | 
			
		||||
                buffer = buffer2;
 | 
			
		||||
                BattInfo.Percent = buffer2.substring(0, buffer2.indexOf(F(","))).toInt(); // converts the result to interger
 | 
			
		||||
                buffer2 = buffer.substring(buffer.indexOf(F(",")) + 1);
 | 
			
		||||
                BattInfo.Voltage = buffer2.substring(0, buffer2.indexOf(F("\r"))).toInt(); // converts the result to interger
 | 
			
		||||
                if (this->configuration.battery != nullptr)
 | 
			
		||||
                    this->configuration.battery(*this, BattInfo);
 | 
			
		||||
            }
 | 
			
		||||
            clearReq(REQ_BATTERY);
 | 
			
		||||
            break;
 | 
			
		||||
    }
 | 
			
		||||
    if (state != lastState) {
 | 
			
		||||
        DEBUG_PRINT(F("BATTERY_STATE: "));
 | 
			
		||||
        DEBUG_PRINTLN(state);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ThreadedGSM::clearReq(int req)
 | 
			
		||||
{
 | 
			
		||||
    requests &= ~(req);
 | 
			
		||||
    nextJob();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ThreadedGSM::Inbox()
 | 
			
		||||
{
 | 
			
		||||
    String CMD;
 | 
			
		||||
    int lastState = state;
 | 
			
		||||
    switch (state) {
 | 
			
		||||
        case READ_REQ:
 | 
			
		||||
            SMSi.Text = "";
 | 
			
		||||
            SMSi.Number = "";
 | 
			
		||||
            dte.SendCommand(F("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(F("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(F("+CMGL: "));
 | 
			
		||||
                if (indexStart >= 0) {
 | 
			
		||||
                    Message.Index = dte.getBuffer().substring(indexStart + 7, dte.getBuffer().indexOf(F(","))).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(F("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(F("+CMGR: "));
 | 
			
		||||
                if (indexStart >= 0) {
 | 
			
		||||
                    int indexStartPDU = dte.getBuffer().indexOf(F("\r\n"), indexStart);
 | 
			
		||||
                    if (indexStartPDU >= 0) {
 | 
			
		||||
                        indexStartPDU += 2;
 | 
			
		||||
                        int indexEndPDU = dte.getBuffer().indexOf(F("\r"), indexStartPDU);
 | 
			
		||||
                        if (indexEndPDU >= 0)
 | 
			
		||||
                            SMSi.Text = dte.getBuffer().substring(indexStartPDU, indexEndPDU);
 | 
			
		||||
                    }
 | 
			
		||||
                    indexStartPDU = dte.getBuffer().indexOf(F(",\""), indexStart);
 | 
			
		||||
                    if (indexStartPDU >= 0) {
 | 
			
		||||
                        indexStartPDU += 2;
 | 
			
		||||
                        int indexEndPDU = dte.getBuffer().indexOf(F("\","), 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 != nullptr)
 | 
			
		||||
                    this->configuration.incoming(*this, SMSi);
 | 
			
		||||
            }
 | 
			
		||||
            clearReq(REQ_INBOX);
 | 
			
		||||
            break;
 | 
			
		||||
    }
 | 
			
		||||
    if (state != lastState) {
 | 
			
		||||
        DEBUG_PRINT(F("INBOX_STATE: "));
 | 
			
		||||
        DEBUG_PRINTLN(state);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ThreadedGSM::Outbox()
 | 
			
		||||
{
 | 
			
		||||
    String CMD;
 | 
			
		||||
 | 
			
		||||
    // CMD.reserve(200);
 | 
			
		||||
    int lastState = state;
 | 
			
		||||
    switch (state) {
 | 
			
		||||
        case SEND_REQ:
 | 
			
		||||
            dte.SendCommand(F("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 != nullptr)
 | 
			
		||||
                    this->configuration.outgoing(*this);
 | 
			
		||||
            }
 | 
			
		||||
            clearReq(REQ_OUTBOX);
 | 
			
		||||
            break;
 | 
			
		||||
    }
 | 
			
		||||
    if (state != lastState) {
 | 
			
		||||
        DEBUG_PRINT(F("OUTBOX_STATE: "));
 | 
			
		||||
        DEBUG_PRINTLN(state);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ThreadedGSM::CheckRing()
 | 
			
		||||
{
 | 
			
		||||
    int lastState = ringState;
 | 
			
		||||
    switch (ringState) {
 | 
			
		||||
        case RING_WAIT:
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        case RING_CHK:
 | 
			
		||||
            if (this->configuration.ring != nullptr) {
 | 
			
		||||
                String s = "Ring";
 | 
			
		||||
                this->configuration.ring(*this, s);
 | 
			
		||||
            }
 | 
			
		||||
            ringState = RING_WAIT;
 | 
			
		||||
            break;
 | 
			
		||||
    }
 | 
			
		||||
    if (ringState != lastState) {
 | 
			
		||||
        DEBUG_PRINT(F("RING_STATE: "));
 | 
			
		||||
        DEBUG_PRINTLN(ringState);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,19 +1,19 @@
 | 
			
		||||
/*
 | 
			
		||||
 * ThreadedGSM.h
 | 
			
		||||
 *
 | 
			
		||||
 * Created: 20/09/2016 11:14:02
 | 
			
		||||
 * Author: Neta Yahav
 | 
			
		||||
 * Author: Neta Yahav, Pavel Brychta
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "DTE.h"
 | 
			
		||||
#include <Arduino.h>
 | 
			
		||||
//#include <Arduino.h>
 | 
			
		||||
#include <Chronos.hpp>
 | 
			
		||||
 | 
			
		||||
// Defaults
 | 
			
		||||
#define THREADEDGSM_DEF_DTE_BUF_SIZ 512
 | 
			
		||||
#define THREADEDGSM_DEF_AT_TIMEOUT  5000
 | 
			
		||||
#define THREADEDGSM_DEF_STA_PON     10000
 | 
			
		||||
#define THREADEDGSM_DEF_AT_TIMEOUT  2000
 | 
			
		||||
#define THREADEDGSM_DEF_STA_PON     15000
 | 
			
		||||
#define THREADEDGSM_DEF_STA_POF     1000
 | 
			
		||||
 | 
			
		||||
// Use custom values or default ones
 | 
			
		||||
@@ -30,17 +30,10 @@
 | 
			
		||||
    #define THREADEDGSM_STARTUP_POWER_OFF_DELAY THREADEDGSM_DEF_STA_POF
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define THREADEDGSM_INTERVAL_COUNT 4
 | 
			
		||||
#define THREADEDGSM_INTERVAL_COUNT 3
 | 
			
		||||
 | 
			
		||||
#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 {
 | 
			
		||||
class ThreadedGSM : public Executable
 | 
			
		||||
{
 | 
			
		||||
    // variables
 | 
			
		||||
  public:
 | 
			
		||||
    struct NetworkTime {
 | 
			
		||||
@@ -101,7 +94,6 @@ class ThreadedGSM {
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
  protected:
 | 
			
		||||
  private:
 | 
			
		||||
    enum StatesStartup {
 | 
			
		||||
        STARTUP_POWER_OFF,
 | 
			
		||||
        STARTUP_POWER_OFF_DELAY,
 | 
			
		||||
@@ -186,509 +178,43 @@ class ThreadedGSM {
 | 
			
		||||
    int ringState;
 | 
			
		||||
    // functions
 | 
			
		||||
  public:
 | 
			
		||||
    ThreadedGSM(Stream & stream)
 | 
			
		||||
        : stream(stream), dte(stream, THREADEDGSM_DTE_BUFFER_SIZE), ringState(RING_WAIT)
 | 
			
		||||
    {
 | 
			
		||||
        for (unsigned long & Interval : Intervals)
 | 
			
		||||
            Interval = 0;
 | 
			
		||||
    explicit ThreadedGSM(Stream & stream);
 | 
			
		||||
 | 
			
		||||
        job = state = requests = 0;
 | 
			
		||||
        // SMSo.Text.reserve(150);
 | 
			
		||||
        // SMSi.Text.reserve(150);
 | 
			
		||||
    }
 | 
			
		||||
    ~ThreadedGSM() override = default;
 | 
			
		||||
 | 
			
		||||
    ~ThreadedGSM() = default;
 | 
			
		||||
    void nextJob();
 | 
			
		||||
 | 
			
		||||
    void nextJob()
 | 
			
		||||
    {
 | 
			
		||||
        job = 0;
 | 
			
		||||
    }
 | 
			
		||||
    void setHandlers(conf config);
 | 
			
		||||
 | 
			
		||||
    void setHandlers(conf config)
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
        this->configuration = config;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void setInterval(IntervalSourceE source, unsigned long interval)
 | 
			
		||||
    {
 | 
			
		||||
        Intervals[source] = interval;
 | 
			
		||||
        tickSync[source] = millis();
 | 
			
		||||
    }
 | 
			
		||||
    void setInterval(IntervalSourceE source, unsigned long interval);
 | 
			
		||||
 | 
			
		||||
    // Initialization
 | 
			
		||||
    void begin()
 | 
			
		||||
    {
 | 
			
		||||
        requests = (REQ_STARTUP);
 | 
			
		||||
    }
 | 
			
		||||
    void begin();
 | 
			
		||||
 | 
			
		||||
    // 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();
 | 
			
		||||
        else
 | 
			
		||||
            CheckRing();
 | 
			
		||||
    }
 | 
			
		||||
    void exec() override;
 | 
			
		||||
 | 
			
		||||
    // Requests
 | 
			
		||||
    void sendSMS(String & Number, String & Text)
 | 
			
		||||
    {
 | 
			
		||||
        requests |= (REQ_OUTBOX);
 | 
			
		||||
        SMSo.Number = Number;
 | 
			
		||||
        SMSo.Text = Text;
 | 
			
		||||
    }
 | 
			
		||||
    void sendSMS(String & Number, String & Text);
 | 
			
		||||
 | 
			
		||||
    void sendSMS(String & Number, const char * Text)
 | 
			
		||||
    {
 | 
			
		||||
        String t = Text;
 | 
			
		||||
 | 
			
		||||
        sendSMS(Number, t);
 | 
			
		||||
    }
 | 
			
		||||
    void sendSMS(String & Number, const char * Text);
 | 
			
		||||
 | 
			
		||||
  protected:
 | 
			
		||||
  private:
 | 
			
		||||
    // States
 | 
			
		||||
    void Startup()
 | 
			
		||||
    {
 | 
			
		||||
        int lastState = state;
 | 
			
		||||
        switch (state) {
 | 
			
		||||
            case STARTUP_POWER_OFF:
 | 
			
		||||
                if (this->configuration.power != nullptr)
 | 
			
		||||
                    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 != nullptr)
 | 
			
		||||
                    this->configuration.power(*this, true);
 | 
			
		||||
                // begin delay
 | 
			
		||||
                tick = millis();
 | 
			
		||||
                state = STARTUP_DELAY;
 | 
			
		||||
                break;
 | 
			
		||||
 | 
			
		||||
            case STARTUP_DELAY:
 | 
			
		||||
                if (millis() - tick >= THREADEDGSM_STARTUP_DELAY) {
 | 
			
		||||
                    dte.SendCommand(F("AT\r"), THREADEDGSM_AT_TIMEOUT, "OK\r");
 | 
			
		||||
                    state = STARTUP_ENTER_AT;
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
 | 
			
		||||
            case STARTUP_ENTER_AT:
 | 
			
		||||
                if (dte.getResult() == DTE::EXPECT_RESULT) {
 | 
			
		||||
                    dte.SendCommand(F("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(F("+CPIN: READY")) != -1) {
 | 
			
		||||
                        dte.SendCommand(F("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(F(",1")) >= 0) || (dte.getBuffer().indexOf(F(",5")) >= 0)) {
 | 
			
		||||
                        dte.SendCommand(F("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(F("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 != nullptr)
 | 
			
		||||
                        this->configuration.ready(*this);
 | 
			
		||||
                } else
 | 
			
		||||
                    state = STARTUP_POWER_OFF;
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
        if (state != lastState) {
 | 
			
		||||
            DEBUG_PRINT(F("STARTUP_STATE: "));
 | 
			
		||||
            DEBUG_PRINTLN(state);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    void Startup();
 | 
			
		||||
 | 
			
		||||
    // Threads
 | 
			
		||||
    void Clock()
 | 
			
		||||
    {
 | 
			
		||||
        String clockTime;
 | 
			
		||||
        int lastState = state;
 | 
			
		||||
        switch (state) {
 | 
			
		||||
            case CLOCK_REQ:
 | 
			
		||||
                dte.SendCommand(F("AT+CCLK?\r"), THREADEDGSM_AT_TIMEOUT, "OK\r");
 | 
			
		||||
                state = CLOCK_VERIFY;
 | 
			
		||||
                break;
 | 
			
		||||
    void Clock();
 | 
			
		||||
 | 
			
		||||
            case CLOCK_VERIFY:
 | 
			
		||||
                int index = dte.getBuffer().indexOf(F("+CCLK: "));
 | 
			
		||||
                if (index >= 0) {
 | 
			
		||||
                    // parse clock
 | 
			
		||||
                    index += 8;
 | 
			
		||||
                    int endindex;
 | 
			
		||||
                    endindex = dte.getBuffer().indexOf(F("+"), index);
 | 
			
		||||
                    if (endindex >= 0)
 | 
			
		||||
                        clockTime = dte.getBuffer().substring(index, endindex);
 | 
			
		||||
                    else {
 | 
			
		||||
                        endindex = dte.getBuffer().indexOf(F("-"), index);
 | 
			
		||||
                        if (endindex >= 0)
 | 
			
		||||
                            clockTime = dte.getBuffer().substring(index, endindex);
 | 
			
		||||
                    }
 | 
			
		||||
    void Signal();
 | 
			
		||||
 | 
			
		||||
                    if (endindex >= 0) {
 | 
			
		||||
                        NetworkTime ClockTime{};
 | 
			
		||||
    void Battery();
 | 
			
		||||
 | 
			
		||||
                        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 != nullptr)
 | 
			
		||||
                            this->configuration.clock(*this, ClockTime);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                clearReq(REQ_CLOCK);
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
        if (state != lastState) {
 | 
			
		||||
            DEBUG_PRINT(F("CLOCK_STATE: "));
 | 
			
		||||
            DEBUG_PRINTLN(state);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    void clearReq(int req);
 | 
			
		||||
 | 
			
		||||
    void Signal()
 | 
			
		||||
    {
 | 
			
		||||
        int lastState = state;
 | 
			
		||||
        switch (state) {
 | 
			
		||||
            case SIGNAL_REQ:
 | 
			
		||||
                dte.SendCommand(F("AT+CSQ\r"), THREADEDGSM_AT_TIMEOUT, "OK\r");
 | 
			
		||||
                state = SIGNAL_VERIFY;
 | 
			
		||||
                break;
 | 
			
		||||
    void Inbox();
 | 
			
		||||
 | 
			
		||||
            case SIGNAL_VERIFY:
 | 
			
		||||
                int index = dte.getBuffer().indexOf(F("+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 != nullptr)
 | 
			
		||||
                            this->configuration.signal(*this, GsmSignal);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                clearReq(REQ_SIG);
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
        if (state != lastState) {
 | 
			
		||||
            DEBUG_PRINT(F("SIGNAL_STATE: "));
 | 
			
		||||
            DEBUG_PRINTLN(state);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    void Outbox();
 | 
			
		||||
 | 
			
		||||
    void Battery()
 | 
			
		||||
    {
 | 
			
		||||
        int lastState = state;
 | 
			
		||||
        switch (state) {
 | 
			
		||||
            case BATTERY_REQ:
 | 
			
		||||
                dte.SendCommand(F("AT+CBC\r"), THREADEDGSM_AT_TIMEOUT, "OK\r");
 | 
			
		||||
                state = BATTERY_VERIFY;
 | 
			
		||||
                break;
 | 
			
		||||
 | 
			
		||||
            case BATTERY_VERIFY:
 | 
			
		||||
                int index = dte.getBuffer().indexOf(F("+CBC:"));
 | 
			
		||||
                if (index >= 0) {
 | 
			
		||||
                    BatteryInfo BattInfo{};
 | 
			
		||||
                    // parse battery level
 | 
			
		||||
                    String buffer = dte.getBuffer().substring(index);
 | 
			
		||||
                    String buffer2 = buffer.substring(buffer.indexOf(F(",")) + 1);
 | 
			
		||||
                    buffer = buffer2;
 | 
			
		||||
                    BattInfo.Percent = buffer2.substring(0, buffer2.indexOf(F(","))).toInt(); // converts the result to interger
 | 
			
		||||
                    buffer2 = buffer.substring(buffer.indexOf(F(",")) + 1);
 | 
			
		||||
                    BattInfo.Voltage = buffer2.substring(0, buffer2.indexOf(F("\r"))).toInt(); // converts the result to interger
 | 
			
		||||
                    if (this->configuration.battery != nullptr)
 | 
			
		||||
                        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(F("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(F("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(F("+CMGL: "));
 | 
			
		||||
                    if (indexStart >= 0) {
 | 
			
		||||
                        Message.Index = dte.getBuffer().substring(indexStart + 7, dte.getBuffer().indexOf(F(","))).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(F("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(F("+CMGR: "));
 | 
			
		||||
                    if (indexStart >= 0) {
 | 
			
		||||
                        int indexStartPDU = dte.getBuffer().indexOf(F("\r\n"), indexStart);
 | 
			
		||||
                        if (indexStartPDU >= 0) {
 | 
			
		||||
                            indexStartPDU += 2;
 | 
			
		||||
                            int indexEndPDU = dte.getBuffer().indexOf(F("\r"), indexStartPDU);
 | 
			
		||||
                            if (indexEndPDU >= 0)
 | 
			
		||||
                                SMSi.Text = dte.getBuffer().substring(indexStartPDU, indexEndPDU);
 | 
			
		||||
                        }
 | 
			
		||||
                        indexStartPDU = dte.getBuffer().indexOf(F(",\""), indexStart);
 | 
			
		||||
                        if (indexStartPDU >= 0) {
 | 
			
		||||
                            indexStartPDU += 2;
 | 
			
		||||
                            int indexEndPDU = dte.getBuffer().indexOf(F("\","), 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 != nullptr)
 | 
			
		||||
                        this->configuration.incoming(*this, SMSi);
 | 
			
		||||
                }
 | 
			
		||||
                clearReq(REQ_INBOX);
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
        if (state != lastState) {
 | 
			
		||||
            DEBUG_PRINT(F("INBOX_STATE: "));
 | 
			
		||||
            DEBUG_PRINTLN(state);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void Outbox()
 | 
			
		||||
    {
 | 
			
		||||
        String CMD;
 | 
			
		||||
 | 
			
		||||
        // CMD.reserve(200);
 | 
			
		||||
        int lastState = state;
 | 
			
		||||
        switch (state) {
 | 
			
		||||
            case SEND_REQ:
 | 
			
		||||
                dte.SendCommand(F("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 != nullptr)
 | 
			
		||||
                        this->configuration.outgoing(*this);
 | 
			
		||||
                }
 | 
			
		||||
                clearReq(REQ_OUTBOX);
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
        if (state != lastState) {
 | 
			
		||||
            DEBUG_PRINT(F("OUTBOX_STATE: "));
 | 
			
		||||
            DEBUG_PRINTLN(state);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void CheckRing()
 | 
			
		||||
    {
 | 
			
		||||
        int lastState = ringState;
 | 
			
		||||
        switch (ringState) {
 | 
			
		||||
            case RING_WAIT:
 | 
			
		||||
                break;
 | 
			
		||||
 | 
			
		||||
            case RING_CHK:
 | 
			
		||||
                if (this->configuration.ring != nullptr) {
 | 
			
		||||
                    String s = "Ring";
 | 
			
		||||
                    this->configuration.ring(*this, s);
 | 
			
		||||
                }
 | 
			
		||||
                ringState = RING_WAIT;
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
        if (ringState != lastState) {
 | 
			
		||||
            DEBUG_PRINT(F("RING_STATE: "));
 | 
			
		||||
            DEBUG_PRINTLN(ringState);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    void CheckRing();
 | 
			
		||||
}; // ThreadedGSM
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user