WIP: pridani ring indikace (zatim nefunkcni)

This commit is contained in:
Pavel Brychta 2021-11-08 13:02:56 +01:00
parent 49ffb2109c
commit e2c5e5dcd9
2 changed files with 662 additions and 665 deletions

117
src/DTE.h
View File

@ -5,24 +5,22 @@
* Author: Neta Yahav
*/
#ifndef __DTE_H__
#define __DTE_H__
#pragma once
#include <Arduino.h>
class DTE
{
//variables
public:
enum CommandResult
{
EXPECT_BUSY,
EXPECT_TIMEOUT,
EXPECT_DELAY,
EXPECT_RESULT
EXPECT_RESULT,
EXPECT_RING
};
protected:
private:
String buffer;
Stream& stream;
@ -33,33 +31,32 @@ private:
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(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)
{
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
flush();
stream.print(command);
buffer = "";
tick = millis();
proccess();
}
void SendCommand(const __FlashStringHelper* command, unsigned long timeout, const char* response1, const char* response2 = 0, const char* response3 = 0)
{
// char cmd[32];
void SendCommand(const __FlashStringHelper* command, unsigned long timeout, const char* response1, const char* response2 = 0, const char* response3 = 0) {
match = 0;
result = EXPECT_BUSY;
@ -68,74 +65,90 @@ public:
response[2] = response3;
this->timeout = timeout;
// clear rx buffer
while (stream.available())
{
stream.read();
}
flush();
// send command
// strcpy_P(cmd, command);
stream.print((const __FlashStringHelper *)command);
// stream.print(cmd);
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(void) {
proccess();
return (result == EXPECT_BUSY) || (result == EXPECT_DELAY);
}
CommandResult getResult() { return result ; }
unsigned int getMatch() { return match; }
String& getBuffer() { return buffer; }
protected:
CommandResult getResult(void) {
return result;
}
unsigned int getMatch(void) {
return match;
}
String& getBuffer(void) {
return buffer;
}
private:
void proccess()
{
if(result == EXPECT_DELAY)
{
void flush(void) {
// clear rx buffer
while (stream.available()) {
stream.read();
}
}
void proccess(void) {
if (result == EXPECT_DELAY) {
if(millis() - tick >= timeout)
result = EXPECT_RESULT;
return;
}
if(result != EXPECT_BUSY) return;
if (result != EXPECT_BUSY) {
if (stream.available()) {
char c;
c = stream.read();
buffer += c;
if (buffer.length() > 4) {
if (buffer.endsWith(F("RING\n"))) {
result = EXPECT_RING;
}
buffer.remove(0);
}
}
return;
}
char c;
unsigned long now = millis();
while(millis() - tick < timeout)
{
while(stream.available() && (buffer.length() < (bufferSize)))
{
while (millis() - tick < timeout) {
while (stream.available() && (buffer.length() < bufferSize)) {
c = stream.read();
buffer += c;
if(buffer.endsWith(response[0]))
{
if (buffer.endsWith(response[0])) {
match = 0;
result = EXPECT_RESULT;
return;
}else if(response[1].length() != 0)
{
if(buffer.endsWith(response[1]))
{
} 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]))
{
} else if (response[2].length() != 0) {
if (buffer.endsWith(response[2])) {
match = 2;
result = EXPECT_RESULT;
return;
@ -150,5 +163,3 @@ private:
result = EXPECT_TIMEOUT;
}
}; //DTE
#endif //__DTE_H__

View File

@ -5,9 +5,7 @@
* Author: Neta Yahav
*/
#ifndef __THREADEDGSM_H__
#define __THREADEDGSM_H__
#pragma once
#include <Arduino.h>
#include "DTE.h"
@ -96,6 +94,7 @@ public:
typedef void (*ThreadedGSMCallbackIncomingSMS)(ThreadedGSM&, SMSInfo&);
typedef void (*ThreadedGSMCallbackBool)(ThreadedGSM&, bool);
typedef void (*ThreadedGSMCallback)(ThreadedGSM&);
typedef void (*ThreadedGSMCallbackRing)(ThreadedGSM&, String&);
struct conf
{
ThreadedGSMCallbackSignal signal;
@ -105,6 +104,7 @@ public:
ThreadedGSMCallback outgoing;
ThreadedGSMCallbackBool power;
ThreadedGSMCallbackBattery battery;
ThreadedGSMCallbackRing ring;
};
protected:
private:
@ -159,6 +159,12 @@ private:
SEND_CHK_OK
};
enum StatesCheckRing
{
RING_WAIT,
RING_CHK,
};
unsigned long tick;
struct
@ -176,7 +182,8 @@ private:
unsigned long Intervals[THREADEDGSM_INTERVAL_COUNT];
// callbacks
conf configuration = {NULL, NULL, NULL, NULL, NULL, NULL, NULL};
// conf configuration = {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr};
conf configuration{0};
enum ReqTypes
{
@ -190,9 +197,13 @@ private:
int requests;
int state;
int job;
int ringState;
//functions
public:
ThreadedGSM(Stream& stream) : stream(stream), dte(stream, THREADEDGSM_DTE_BUFFER_SIZE)
ThreadedGSM(Stream& stream)
: stream(stream)
, dte(stream, THREADEDGSM_DTE_BUFFER_SIZE)
, ringState(RING_WAIT)
{
for (int i = 0; i < THREADEDGSM_INTERVAL_COUNT; i++)
Intervals[i] = 0;
@ -204,50 +215,47 @@ public:
~ThreadedGSM() {};
void nextJob()
{
void nextJob(void) {
job = 0;
}
void setHandlers(conf config)
{
void setHandlers(conf config) {
this->configuration = config;
}
void setInterval(IntervalSourceE source, unsigned long interval)
{
void setInterval(IntervalSourceE source, unsigned long interval) {
Intervals[source] = interval;
tickSync[source] = millis();
}
// Initialization
void begin()
{
void begin(void) {
requests = (REQ_STARTUP);
}
// Call this function for executing thread
void loop()
{
if(dte.getIsBusy()) return;
void loop(void) {
if (dte.getIsBusy())
return;
// intervals
for(int i=0;i<THREADEDGSM_INTERVAL_COUNT;i++)
{
if(Intervals[i])
{
if(millis() - tickSync[i] >= Intervals[i])
{
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;
@ -257,8 +265,7 @@ public:
}
}
if(job == 0)
{
if (job == 0) {
// no assigned job, assign it
if (requests & REQ_CLOCK)
job = REQ_CLOCK;
@ -273,8 +280,7 @@ public:
else if (requests & REQ_BATTERY)
job = REQ_BATTERY;
if(job)
{
if (job) {
state = 0;
DEBUG_PRINT(F("Job ID: "));
DEBUG_PRINTLN(job);
@ -294,42 +300,41 @@ public:
Outbox();
else if (job == REQ_BATTERY)
Battery();
else CheckRing();
}
// Requests
void sendSMS(String& Number, String& Text)
{
void sendSMS(String& Number, String& Text) {
requests |= (REQ_OUTBOX);
SMSo.Number = Number;
SMSo.Text = Text;
}
void sendSMS(String& Number, char *Text)
{
requests |= (REQ_OUTBOX);
SMSo.Number = Number;
SMSo.Text = Text;
void sendSMS(String& Number, char *Text) {
String t = Text;
sendSMS(Number, t);
}
protected:
private:
// States
void Startup()
{
void Startup(void) {
int lastState = state;
switch(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);
@ -337,43 +342,38 @@ private:
tick = millis();
state = STARTUP_DELAY;
break;
case STARTUP_DELAY:
if(millis() - tick >= THREADEDGSM_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)
{
if (dte.getResult() == DTE::EXPECT_RESULT) {
dte.SendCommand(F("AT+CPIN?\r"), 10000, "OK\r");
state = STARTUP_CHK_CPIN;
}
else
{
} else {
state = STARTUP_POWER_OFF;
}
break;
case STARTUP_CHK_CPIN:
if(dte.getResult() == DTE::EXPECT_RESULT)
{
if(dte.getBuffer().indexOf(F("+CPIN: READY")) != -1)
{
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
{
} 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))
{
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
@ -381,17 +381,17 @@ private:
} else
state = STARTUP_POWER_OFF;
break;
case STARTUP_CHK_CLTS:
if(dte.getResult() == DTE::EXPECT_RESULT)
{
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)
{
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++)
@ -402,43 +402,38 @@ private:
state = STARTUP_POWER_OFF;
break;
}
if(state != lastState)
{
if (state != lastState) {
DEBUG_PRINT(F("STARTUP_STATE: "));
DEBUG_PRINTLN(state);
}
}
// Threads
void Clock()
{
void Clock(void) {
String clockTime;
int lastState = state;
switch(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)
{
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
{
else {
endindex = dte.getBuffer().indexOf(F("-"), index);
if (endindex >= 0)
clockTime = dte.getBuffer().substring(index, endindex);
}
if(endindex >= 0)
{
if (endindex >= 0) {
NetworkTime ClockTime;
ClockTime.year = 2000 + clockTime.substring(0, 2).toInt();
ClockTime.month = clockTime.substring(3, 5).toInt();
@ -453,33 +448,29 @@ private:
clearReq(REQ_CLOCK);
break;
}
if(state != lastState)
{
if (state != lastState) {
DEBUG_PRINT(F("CLOCK_STATE: "));
DEBUG_PRINTLN(state);
}
}
void Signal()
{
void Signal(void) {
int lastState = state;
switch(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)
{
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 (GsmSignal.Value != 0) {
if (this->configuration.signal != NULL)
this->configuration.signal(*this, GsmSignal);
}
@ -487,26 +478,23 @@ private:
clearReq(REQ_SIG);
break;
}
if(state != lastState)
{
if (state != lastState) {
DEBUG_PRINT(F("SIGNAL_STATE: "));
DEBUG_PRINTLN(state);
}
}
void Battery()
{
void Battery(void) {
int lastState = state;
switch(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)
{
if (index >= 0) {
BatteryInfo BattInfo;
// parse battery level
String buffer = dte.getBuffer().substring(index);
@ -521,42 +509,38 @@ private:
clearReq(REQ_BATTERY);
break;
}
if(state != lastState)
{
if (state != lastState) {
DEBUG_PRINT(F("BATTERY_STATE: "));
DEBUG_PRINTLN(state);
}
}
void clearReq(int req)
{
void clearReq(int req) {
requests &= ~(req);
nextJob();
}
void Inbox()
{
void Inbox(void) {
String CMD;
int lastState = state;
switch(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)
{
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)
{
if (dte.getResult() == DTE::EXPECT_RESULT) {
CMD = F("AT+CMGL="); // Read all SMS messages
CMD += (int) READ_TYPE_ALL;
CMD += "\r";
@ -565,16 +549,14 @@ private:
}
else clearReq(REQ_INBOX);
break;
case READ_CHK_CMGL:
if(dte.getResult() == DTE::EXPECT_RESULT)
{
if (dte.getResult() == DTE::EXPECT_RESULT) {
//fetch index
int indexStart = dte.getBuffer().indexOf(F("+CMGL: "));
if (indexStart >= 0)
{
if (indexStart >= 0) {
Message.Index = dte.getBuffer().substring(indexStart + 7, dte.getBuffer().indexOf(F(","))).toInt();
if(Message.Index != 0)
{
if (Message.Index != 0) {
dte.Delay(2000);
state = READ_DELAY_CLEAR_BUFF;
}
@ -591,8 +573,7 @@ private:
break;
case READ_TEXT_CMGR:
if (dte.getResult() == DTE::EXPECT_RESULT)
{
if (dte.getResult() == DTE::EXPECT_RESULT) {
CMD = F("AT+CMGR="); // Read the SMS message
CMD += Message.Index;
CMD += "\r";
@ -603,22 +584,18 @@ private:
break;
case READ_CHK_CMGR:
if(dte.getResult() == DTE::EXPECT_RESULT)
{
if (dte.getResult() == DTE::EXPECT_RESULT) {
int indexStart = dte.getBuffer().indexOf(F("+CMGR: "));
if(indexStart >= 0)
{
if (indexStart >= 0) {
int indexStartPDU = dte.getBuffer().indexOf(F("\r\n"), indexStart);
if (indexStartPDU >= 0)
{
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)
{
if (indexStartPDU >= 0) {
indexStartPDU += 2;
int indexEndPDU = dte.getBuffer().indexOf(F("\","), indexStartPDU);
if (indexEndPDU >= 0)
@ -633,39 +610,35 @@ private:
} else
clearReq(REQ_INBOX);
break;
case READ_CHK_CMGD:
//if( (dte.getResult() == DTE::EXPECT_RESULT) && (SMS.InboxMsgContents != ""))
if(dte.getResult() == DTE::EXPECT_RESULT)
{
if (dte.getResult() == DTE::EXPECT_RESULT) {
if (this->configuration.incoming != NULL)
this->configuration.incoming(*this, SMSi);
}
clearReq(REQ_INBOX);
break;
}
if(state != lastState)
{
if (state != lastState) {
DEBUG_PRINT(F("INBOX_STATE: "));
DEBUG_PRINTLN(state);
}
}
void Outbox()
{
void Outbox(void) {
String CMD;
//CMD.reserve(200);
int lastState = state;
switch(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)
{
if (dte.getResult() == DTE::EXPECT_RESULT) {
CMD = F("AT+CMGS=\"");
CMD += SMSo.Number;
CMD += "\"\r";
@ -674,30 +647,43 @@ private:
}
else clearReq(REQ_OUTBOX);
break;
case SEND_CHK_RDY:
if(dte.getResult() == DTE::EXPECT_RESULT)
{
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 (dte.getResult() == DTE::EXPECT_RESULT) {
if (this->configuration.outgoing != NULL)
this->configuration.outgoing(*this);
}
clearReq(REQ_OUTBOX);
break;
}
if(state != lastState)
{
if (state != lastState) {
DEBUG_PRINT(F("OUTBOX_STATE: "));
DEBUG_PRINTLN(state);
}
}
}; //ThreadedGSM
#endif //__THREADEDGSM_H__
void CheckRing(void) {
int lastState = ringState;
switch (ringState) {
case RING_WAIT:
if (dte.getResult() == DTE::EXPECT_RING) {
ringState = RING_CHK;
}
break;
}
if (ringState != lastState) {
DEBUG_PRINT(F("RING_STATE: "));
DEBUG_PRINTLN(ringState);
}
}
}; //ThreadedGSM