First commit

This commit is contained in:
EoF 2020-01-23 23:58:57 +05:00
commit 8c79fce887
6 changed files with 2487 additions and 0 deletions

875
GPRS_Shield_Arduino.cpp Normal file
View File

@ -0,0 +1,875 @@
/*
* GPRS_Shield_Arduino.cpp
* A library for SeeedStudio seeeduino GPRS shield
*
* Copyright (c) 2015 seeed technology inc.
* Website : www.seeed.cc
* Author : lawliet zou
* Create Time: April 2015
* Change Log :
*
* The MIT License (MIT)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <stdio.h>
#include <HardwareSerial.h>
#include "GPRS_Shield_Arduino.h"
GPRS* GPRS::inst;
GPRS::GPRS(Stream& serial, uint8_t pkPin) {
_pkPin = pkPin;
inst = this;
stream = &serial;
sim900_init(stream);
}
bool GPRS::init(void) {
if (!sim900_check_with_cmd("AT\r\n","OK\r\n",CMD))
return false;
if (!sim900_check_with_cmd("AT+CFUN=1\r\n","OK\r\n",CMD))
return false;
if (!checkSIMStatus())
return false;
if (!sim900_check_with_cmd("AT+CNMI?\r\n", "+CNMI: 2,2,0,0,0\r\nOK\r\n", CMD)) {
if (!sim900_check_with_cmd("AT+CNMI=2,2,0,0,0\r\n","OK\r\n", CMD)) {
return false;
}
}
if (!sim900_check_with_cmd("AT+CMGF?\r\n", "+CMGF: 1\r\nOK\r\n", CMD)) {
if (!sim900_check_with_cmd("AT+CMGF=1\r\n","OK\r\n", CMD)) {
return false;
}
}
if (!sim900_check_with_cmd("AT+CLIP=1\r\n","OK\r\n", CMD)) {
return false;
}
return true;
}
bool GPRS::checkPowerUp(void) {
return sim900_check_with_cmd("AT\r\n","OK\r\n", CMD);
}
// power Up GPRS Shield
void GPRS::powerOn() {
//delay(1000);
pinMode(_pkPin, OUTPUT);
digitalWrite(_pkPin, HIGH);
delay(500);
digitalWrite(_pkPin, LOW);
delay(3000);
}
// power Off GPRS Shield
void GPRS::powerOff() {
pinMode(_pkPin, OUTPUT);
digitalWrite(_pkPin, HIGH);
delay(2000);
digitalWrite(_pkPin, LOW);
delay(3000);
}
void GPRS::reset() {
powerOff();
powerOn();
}
bool GPRS::checkSIMStatus(void) {
char gprsBuffer[32];
byte count = 0;
sim900_clean_buffer(gprsBuffer,32);
while(count < 3) {
sim900_send_cmd("AT+CPIN?\r\n");
sim900_read_buffer(gprsBuffer,32,DEFAULT_TIMEOUT);
if((NULL != strstr(gprsBuffer,"+CPIN: READY"))) {
break;
}
count++;
delay(300);
}
if(count == 3) {
return false;
}
return true;
}
bool GPRS::sendSMS(const char *number, const char *data) {
// Set message mode to ASCII
if(!sim900_check_with_cmd("AT+CMGF=1\r\n", "OK\r\n", CMD)) {
return false;
}
delay(500);
sim900_send_cmd("AT+CMGS=\"");
sim900_send_cmd(number);
if(!sim900_check_with_cmd("\"\r\n",">",CMD)) {
return false;
}
delay(1000);
sim900_send_cmd(data);
delay(500);
sim900_send_End_Mark();
return sim900_wait_for_resp("OK\r\n", CMD, 2);
}
char GPRS::isSMSunread() {
char gprsBuffer[48]; //48 is enough to see +CMGL:
char *s;
//List of all UNREAD SMS and DON'T change the SMS UNREAD STATUS
sim900_send_cmd(F("AT+CMGL=\"REC UNREAD\",1\r\n"));
/*If you want to change SMS status to READ you will need to send:
AT+CMGL=\"REC UNREAD\"\r\n
This command will list all UNREAD SMS and change all of them to READ
If there is not SMS, response is (30 chars)
AT+CMGL="REC UNREAD",1 --> 22 + 2
--> 2
OK --> 2 + 2
If there is SMS, response is like (>64 chars)
AT+CMGL="REC UNREAD",1
+CMGL: 9,"REC UNREAD","XXXXXXXXX","","14/10/16,21:40:08+08"
Here SMS text.
OK
or
AT+CMGL="REC UNREAD",1
+CMGL: 9,"REC UNREAD","XXXXXXXXX","","14/10/16,21:40:08+08"
Here SMS text.
+CMGL: 10,"REC UNREAD","YYYYYYYYY","","14/10/16,21:40:08+08"
Here second SMS
OK
*/
sim900_clean_buffer(gprsBuffer,31);
sim900_read_buffer(gprsBuffer, 30, DEFAULT_TIMEOUT);
//Serial.print("Buffer isSMSunread: ");Serial.println(gprsBuffer);
if(NULL != ( s = strstr(gprsBuffer,"OK"))) {
//In 30 bytes "doesn't" fit whole +CMGL: response, if recieve only "OK"
// means you don't have any UNREAD SMS
delay(50);
return 0;
} else {
//More buffer to read
//We are going to flush serial data until OK is recieved
sim900_wait_for_resp("OK\r\n", CMD);
//sim900_flush_serial();
//We have to call command again
sim900_send_cmd("AT+CMGL=\"REC UNREAD\",1\r\n");
sim900_clean_buffer(gprsBuffer,48);
sim900_read_buffer(gprsBuffer,47,DEFAULT_TIMEOUT);
//Serial.print("Buffer isSMSunread 2: ");Serial.println(gprsBuffer);
if(NULL != ( s = strstr(gprsBuffer,"+CMGL:"))) {
//There is at least one UNREAD SMS, get index/position
s = strstr(gprsBuffer,":");
if (s != NULL) {
//We are going to flush serial data until OK is recieved
sim900_wait_for_resp("OK\r\n", CMD);
return atoi(s+1);
}
} else {
return -1;
}
}
return -1;
}
bool GPRS::readSMS(int messageIndex, char *message, byte length) {
byte i = 0;
char gprsBuffer[100];
char num[4];
char *p,*s;
sim900_check_with_cmd("AT+CMGF=1\r\n","OK\r\n",CMD);
delay(1000);
sim900_send_cmd("AT+CMGR=");
itoa(messageIndex, num, 10);
sim900_send_cmd(num);
sim900_send_cmd("\r\n");
sim900_clean_buffer(gprsBuffer,sizeof(gprsBuffer));
sim900_read_buffer(gprsBuffer,sizeof(gprsBuffer),DEFAULT_TIMEOUT);
if(NULL != ( s = strstr(gprsBuffer,"+CMGR:"))){
if(NULL != ( s = strstr(s,"\r\n"))){
p = s + 2;
while((*p != '\r')&&(i < length-1)) {
message[i++] = *(p++);
}
message[i] = '\0';
return true;
}
}
return false;
}
byte GPRS::getEvent(char *message, char *phone, char *datetime, char *gprsBuffer, byte size, bool check) {
int len;
byte i = 0;
char *s, *p1, *p2;
// Read buffer
sim900_clean_buffer(gprsBuffer, size);
sim900_read_buffer(gprsBuffer, size - 1);
len = strlen(gprsBuffer);
// Get SMS
s = strstr(gprsBuffer,"+CMT: ");
if (s != NULL) {
// Extract phone number string
p1 = strstr(gprsBuffer, "\"+");
p2 = p1 + 1; //First phone number character
p1 = strstr((char *)(p2), "\"");
if (p1 != NULL) {
i = 0;
while (p2 < p1) {
phone[i++] = *(p2++);
}
phone[i] = '\0';
}
// Extract date time string
p1 = strstr((char *)(p2), ",");
p2 = p1 + 1;
p1 = strstr((char *)(p2), ",");
p2 = p1 + 2; //First date time character
p1 = strstr((char *)(p2), "\"");
if (p1 != NULL) {
i = 0;
while (p2 < p1) {
datetime[i++] = *(p2++);
}
datetime[i] = '\0';
}
// Extract message
p2 = strstr(gprsBuffer, "\r\n");
p2 = p2 + 2;
p1 = strstr(p2, "\r\n");
if (p1 != NULL) {
i = 0;
p1 = p1 + 2; //First message character
while((*p1 != '\r') && (i < len - 1)) {
message[i++] = *(p1++);
}
message[i] = '\0';
}
return SMS;
}
// Get Call
s = strstr(gprsBuffer,"+CLIP: ");
if (s != NULL) {
// Extract phone number string
p1 = strstr(gprsBuffer, "\"+");
p2 = p1 + 1; //First phone number character
p1 = strstr((char *)(p2), "\"");
if (p1 != NULL) {
i = 0;
while (p2 < p1) {
phone[i++] = *(p2++);
}
phone[i] = '\0';
}
return CALL;
}
// Get outgoing call
s = strstr(gprsBuffer,"+COLP: ");
if (s != NULL) {
// Extract phone number string
p1 = strstr(gprsBuffer, "\"+");
p2 = p1 + 1; //First phone number character
p1 = strstr((char *)(p2), "\"");
if (p1 != NULL) {
i = 0;
while (p2 < p1) {
phone[i++] = *(p2++);
}
phone[i] = '\0';
}
return ANSWER;
}
// Get BUSY
s = strstr(gprsBuffer,"BUSY");
if (s != NULL) {
return BUSY;
}
// Get NO CARRIER
s = strstr(gprsBuffer,"NO CARRIER");
if (s != NULL) {
return NO_CARRIER;
}
// Get NO ANSWER
s = strstr(gprsBuffer,"NO ANSWER");
if (s != NULL) {
return NO_ANSWER;
}
// Check modem
if (check) {
if (!sim900_check_with_cmd("AT\r\n","OK\r\n", CMD)) return ERR;
}
return NONE;
}
bool GPRS::getSMS(char *message, char *phone, char *datetime, char *gprsBuffer, byte size) {
/* Response is like:
+CMT: "+79772941911","","15/12/15,01:51:24+12"
SMS text here
*/
//if(!sim900_check_with_cmd("","+CMT: ", CMD, 3)) return false;
if(!sim900_wait_for_resp("+CMT: ", CMD, 1)) return false;
byte i = 0;
//char gprsBuffer[80 + 160];
char *p1, *p2;
sim900_clean_buffer(gprsBuffer, size);//sizeof(gprsBuffer));
sim900_read_buffer(gprsBuffer, size - 1);//sizeof(gprsBuffer));
int len = strlen(gprsBuffer);
//int len = sizeof(message);
//byte len = 160;
// Serial.print("Buff len: ");
// Serial.println(len);
// Serial.print("Buff: ");
// Serial.println(gprsBuffer);
// Serial.println("----- buffer -----");
// Serial.println(gprsBuffer);
// Serial.println("^^^^^ buffer ^^^^^");
// Extract phone number string
p1 = strstr(gprsBuffer, "\"+");
p2 = p1 + 1; //First phone number character
p1 = strstr((char *)(p2), "\"");
if (p1 != NULL) {
i = 0;
while (p2 < p1) {
phone[i++] = *(p2++);
}
phone[i] = '\0';
}
// Extract date time string
p1 = strstr((char *)(p2), ",");
p2 = p1 + 1;
p1 = strstr((char *)(p2), ",");
p2 = p1 + 2; //First date time character
p1 = strstr((char *)(p2), "\"");
if (p1 != NULL) {
i = 0;
while (p2 < p1) {
datetime[i++] = *(p2++);
}
datetime[i] = '\0';
}
// Extract message
p1 = strstr(gprsBuffer, "\r\n");
if (p1 != NULL) {
i = 0;
p1 = p1 + 2; //First message character
while((*p1 != '\r') && (i < len - 1)) {
message[i++] = *(p1++);
}
message[i] = '\0';
}
return true;
}
bool GPRS::deleteSMS(int index)
{
char num[4];
sim900_send_cmd("AT+CMGD=");
itoa(index, num, 10);
sim900_send_cmd(num);
return sim900_check_with_cmd("\r\n","OK\r\n",CMD);
}
bool GPRS::callUp(char *number)
{
if(!sim900_check_with_cmd("AT+COLP=1\r\n","OK\r\n",CMD)) {
return false;
}
delay(1000);
sim900_send_cmd("ATD");
sim900_send_cmd(number);
sim900_send_cmd(";\r\n");
return true;
}
void GPRS::answer(void)
{
//TO CHECK: ATA doesnt return "OK" ????
sim900_send_cmd("ATA\r\n");
}
bool GPRS::ifcallNow(byte timeout)
{
return sim900_check_with_cmd("","RING\r\n",CMD, timeout);
}
bool GPRS::ifcallEnd(void)
{
return sim900_check_with_cmd("","NO CARRIER\r\n",CMD);
}
void GPRS::callEnd(void)
{
sim900_send_cmd("ATH0\r\n");
}
bool GPRS::hangup(void)
{
return sim900_check_with_cmd("ATH\r\n","OK\r\n",CMD);
}
bool GPRS::disableCLIPring(void)
{
return sim900_check_with_cmd("AT+CLIP=0\r\n","OK\r\n",CMD);
}
bool GPRS::isCallActive(char *number, char *gprsBuffer)
{
//char gprsBuffer[46]; //46 is enough to see +CPAS: and CLCC:
char *p, *s;
int i = 0;
sim900_send_cmd("AT+CPAS\r\n");
/*Result code:
0: ready
2: unknown
3: ringing
4: call in progress
AT+CPAS --> 7 + 2 = 9 chars
--> 2 char
+CPAS: 3 --> 8 + 2 = 10 chars
--> 2 char
OK --> 2 + 2 = 4 chars
AT+CPAS
+CPAS: 0
OK
*/
sim900_clean_buffer(gprsBuffer, 46);
sim900_read_buffer(gprsBuffer, 45);
//HACERR cuando haga lo de esperar a OK no me haría falta esto
//We are going to flush serial data until OK is recieved
//Serial.println("Wait OK");
//sim900_wait_for_resp("OK\r\n", CMD);
//Serial.print("Buffer isCallActive 1: ");Serial.println(gprsBuffer);
if(NULL != ( s = strstr(gprsBuffer,"+CPAS:"))) {
s = s + 7;
if (*s != '0') {
//There is something "running" (but number 2 that is unknow)
if (*s != '2') {
//3 or 4, let's go to check for the number
sim900_send_cmd("AT+CLCC\r\n");
/*
AT+CLCC --> 9
+CLCC: 1,1,4,0,0,"656783741",161,""
OK
Without ringing:
AT+CLCC
OK
*/
sim900_clean_buffer(gprsBuffer, 46);
sim900_read_buffer(gprsBuffer, 45);
//Serial.print("Buffer isCallActive 2: ");Serial.println(gprsBuffer);
if(NULL != ( s = strstr(gprsBuffer,"+CLCC:"))) {
//There is at least one CALL ACTIVE, get number
s = strstr((char *)(s),"\"");
s = s + 1; //We are in the first phone number character
p = strstr((char *)(s),"\""); //p is last character """
if (NULL != s) {
i = 0;
while (s < p) {
number[i++] = *(s++);
}
number[i] = '\0';
}
//I need to read more buffer
//We are going to flush serial data until OK is recieved
return sim900_wait_for_resp("OK\r\n", CMD);
}
}
}
}
return false;
}
bool GPRS::getDateTime(char *buffer) {
//AT+CCLK? --> 8 + CRLF = 10
//+CCLK: "14/11/13,21:14:41+04" --> 29+ CRLF = 31
// --> CRLF = 2
//OK
byte i = 0;
char gprsBuffer[46];
char *p,*s;
sim900_send_cmd("AT+CCLK?\r\n");
sim900_clean_buffer(gprsBuffer,43);
sim900_read_buffer(gprsBuffer,43,DEFAULT_TIMEOUT);
if(NULL != ( s = strstr(gprsBuffer,"+CCLK:"))) {
s = strstr((char *)(s),"\"");
s = s + 1; //We are in the first phone number character
p = strstr((char *)(s),"\""); //p is last character """
if (NULL != s) {
i = 0;
while (s < p) {
buffer[i++] = *(s++);
}
buffer[i] = '\0';
}
//We are going to flush serial data until OK is recieved
return sim900_wait_for_resp("OK\r\n", CMD);
}
return false;
}
byte GPRS::getSignalStrength() {
//AT+CSQ: 00,00 --> 13 + CRLF = 15
// --> CRLF = 2
//OK --> 2 + CRLF = 4
byte result = 99;
char gprsBuffer[21];
sim900_clean_buffer(gprsBuffer,21);
char *s;
sim900_send_cmd("AT+CSQ\r\n");
sim900_read_buffer(gprsBuffer,21,DEFAULT_TIMEOUT);
if(NULL != ( s = strstr(gprsBuffer,"+CSQ: "))) {
result = atoi(s+6);
sim900_wait_for_resp("OK\r\n", CMD);
}
return result;
}
//Here is where we ask for APN configuration, with F() so we can save MEMORY
//bool GPRS::join(const __FlashStringHelper *apn, const __FlashStringHelper *userName, const __FlashStringHelper *passWord)
bool GPRS::join(char* apn, char* userName, char* passWord, int timeout) {
byte i;
char *p, *s;
char ipAddr[32];
/* if(!sim900_check_with_cmd("AT+CIPSHUT\r\n","SHUT OK\r\n", CMD)) {
Serial.write("Error = 1\r\n");
return false;
}
delay(1000);
*/
sim900_send_cmd("AT+CIPSHUT\r\n");
delay(500);
//Select multiple connection
//sim900_check_with_cmd("AT+CIPMUX=1\r\n","OK",DEFAULT_TIMEOUT,CMD);
//set APN. OLD VERSION
//snprintf(cmd,sizeof(cmd),"AT+CSTT=\"%s\",\"%s\",\"%s\"\r\n",_apn,_userName,_passWord);
//sim900_check_with_cmd(cmd, "OK\r\n", DEFAULT_TIMEOUT,CMD);
sim900_send_cmd("AT+CSTT=\"");
sim900_send_cmd(apn);
sim900_send_cmd("\",\"");
sim900_send_cmd(userName);
sim900_send_cmd("\",\"");
sim900_send_cmd(passWord);
sim900_send_cmd("\"\r\n");
delay(500);
//Brings up wireless connection
sim900_send_cmd("AT+CIICR\r\n");
delay(4000);
sim900_wait_for_resp("OK\r\n", CMD);
delay(500);
// sim900_check_with_cmd("AT+CIICR\r\n","OK\r\n", CMD);
//Get local IP address
sim900_send_cmd("AT+CIFSR\r\n");
delay(500);
sim900_clean_buffer(ipAddr,32);
sim900_read_buffer(ipAddr,32,DEFAULT_TIMEOUT);
//Response:
//AT+CIFSR\r\n --> 8 + 2
//\r\n --> 0 + 2
//10.160.57.120\r\n --> 15 + 2 (max) : TOTAL: 29
//Response error:
//AT+CIFSR\r\n
//\r\n
//ERROR\r\n
if (NULL != strstr(ipAddr,"ERROR")) {
Serial.write("Error = 2\r\n");
return false;
}
s = ipAddr + 12;
p = strstr((char *)(s),"\r\n"); //p is last character \r\n
if (NULL != s) {
i = 0;
while (s < p) {
ip_string[i++] = *(s++);
}
ip_string[i] = '\0';
}
_ip = str_to_ip(ip_string);
if(_ip != 0) {
return true;
}
Serial.write("Error = 3\r\n");
return false;
}
void GPRS::disconnect() {
sim900_send_cmd("AT+CIPSHUT\r\n");
}
bool GPRS::connect(Protocol ptl,const char * host, int port, int timeout) {
//char cmd[64];
char num[4];
char resp[96];
//sim900_clean_buffer(cmd,64);
if(ptl == TCP) {
sim900_send_cmd("AT+CIPSTART=\"TCP\",\"");
sim900_send_cmd(host);
sim900_send_cmd("\",");
itoa(port, num, 10);
sim900_send_cmd(num);
sim900_send_cmd("\r\n");
// sprintf(cmd, "AT+CIPSTART=\"TCP\",\"%s\",%d\r\n",host, port);
} else if(ptl == UDP) {
sim900_send_cmd("AT+CIPSTART=\"UDP\",\"");
sim900_send_cmd(host);
sim900_send_cmd("\",");
itoa(port, num, 10);
sim900_send_cmd(num);
sim900_send_cmd("\r\n");
// sprintf(cmd, "AT+CIPSTART=\"UDP\",\"%s\",%d\r\n",host, port);
} else {
return false;
}
delay(2000);
//sim900_send_cmd(cmd);
sim900_read_buffer(resp,96,timeout);
//Serial.print("Connect resp: "); Serial.println(resp);
if(NULL != strstr(resp,"CONNECT")) { //ALREADY CONNECT or CONNECT OK
return true;
}
return false;
}
//Overload with F() macro to SAVE memory
bool GPRS::connect(Protocol ptl,const __FlashStringHelper *host, const __FlashStringHelper *port, int timeout) {
//char cmd[64];
char resp[96];
//sim900_clean_buffer(cmd,64);
if(ptl == TCP) {
sim900_send_cmd(F("AT+CIPSTART=\"TCP\",\"")); //%s\",%d\r\n",host, port);
} else if(ptl == UDP) {
sim900_send_cmd(F("AT+CIPSTART=\"UDP\",\"")); //%s\",%d\r\n",host, port);
} else {
return false;
}
sim900_send_cmd(host);
sim900_send_cmd(F("\","));
sim900_send_cmd(port);
sim900_send_cmd(F("\r\n"));
//Serial.print("Connect: "); Serial.println(cmd);
sim900_read_buffer(resp, 96, timeout);
//Serial.print("Connect resp: "); Serial.println(resp);
if(NULL != strstr(resp,"CONNECT")) { //ALREADY CONNECT or CONNECT OK
return true;
}
return false;
}
bool GPRS::is_connected(void) {
char resp[96];
sim900_send_cmd("AT+CIPSTATUS\r\n");
sim900_read_buffer(resp,sizeof(resp),DEFAULT_TIMEOUT);
if(NULL != strstr(resp,"CONNECTED")) {
//+CIPSTATUS: 1,0,"TCP","216.52.233.120","80","CONNECTED"
return true;
} else {
//+CIPSTATUS: 1,0,"TCP","216.52.233.120","80","CLOSED"
//+CIPSTATUS: 0,,"","","","INITIAL"
return false;
}
}
bool GPRS::close() {
// if not connected, return
if (!is_connected()) {
return true;
}
return sim900_check_with_cmd("AT+CIPCLOSE\r\n", "CLOSE OK\r\n", CMD);
}
int GPRS::readable(void) {
return sim900_check_readable();
}
int GPRS::wait_readable(int wait_time) {
return sim900_wait_readable(wait_time);
}
int GPRS::wait_writeable(int req_size) {
return req_size+1;
}
int GPRS::send(const char * str, int len) {
//char cmd[32];
char num[4];
if(len > 0){
//snprintf(cmd,sizeof(cmd),"AT+CIPSEND=%d\r\n",len);
//sprintf(cmd,"AT+CIPSEND=%d\r\n",len);
sim900_send_cmd("AT+CIPSEND=");
itoa(len, num, 10);
sim900_send_cmd(num);
if(!sim900_check_with_cmd("\r\n",">",CMD)) {
//if(!sim900_check_with_cmd(cmd,">",CMD)) {
return 0;
}
/*if(0 != sim900_check_with_cmd(str,"SEND OK\r\n", DEFAULT_TIMEOUT * 10 ,DATA)) {
return 0;
}*/
delay(500);
sim900_send_cmd(str);
delay(500);
sim900_send_End_Mark();
if(!sim900_wait_for_resp("SEND OK\r\n", DATA, DEFAULT_TIMEOUT * 10, DEFAULT_INTERCHAR_TIMEOUT * 10)) {
return 0;
}
}
return len;
}
int GPRS::send(const char * str) {
//char cmd[32];
int len=strlen(str);
char num[4];
if(len > 0){
//snprintf(cmd,sizeof(cmd),"AT+CIPSEND=%d\r\n",len);
//sprintf(cmd,"AT+CIPSEND=%d\r\n",len);
sim900_send_cmd("AT+CIPSEND=");
itoa(len, num, 10);
sim900_send_cmd(num);
if(!sim900_check_with_cmd("\r\n",">",CMD)) {
//if(!sim900_check_with_cmd(cmd,">",CMD)) {
return 0;
}
/*if(0 != sim900_check_with_cmd(str,"SEND OK\r\n", DEFAULT_TIMEOUT * 10 ,DATA)) {
return 0;
}*/
delay(500);
sim900_send_cmd(str);
delay(500);
sim900_send_End_Mark();
if(!sim900_wait_for_resp("SEND OK\r\n", DATA, DEFAULT_TIMEOUT * 10, DEFAULT_INTERCHAR_TIMEOUT * 10)) {
return 0;
}
}
return len;
}
int GPRS::recv(char* buf, int len)
{
sim900_clean_buffer(buf,len);
sim900_read_buffer(buf,len); //Ya he llamado a la funcion con la longitud del buffer - 1 y luego le estoy añadiendo el 0
return strlen(buf);
}
uint32_t GPRS::str_to_ip(const char* str) {
uint32_t ip = 0;
char* p = (char*)str;
for(int i = 0; i < 4; i++) {
ip |= atoi(p);
p = strchr(p, '.');
if (p == NULL) {
break;
}
ip <<= 8;
p++;
}
return ip;
}
char* GPRS::getIPAddress() {
//I have already a buffer with ip_string: snprintf(ip_string, sizeof(ip_string), "%d.%d.%d.%d", (_ip>>24)&0xff,(_ip>>16)&0xff,(_ip>>8)&0xff,_ip&0xff);
return ip_string;
}
unsigned long GPRS::getIPnumber() {
return _ip;
}
bool GPRS::controlGPIO(uint8_t index, uint8_t level) {
char num[4];
sim900_send_cmd("AT+SGPIO=0,");
itoa(index, num, 10);
sim900_send_cmd(num);
sim900_send_cmd(",1,");
itoa(level, num, 10);
sim900_send_cmd(num);
sim900_send_cmd("\r\n");
return sim900_wait_for_resp("OK\r\n", CMD);
}
/* NOT USED bool GPRS::gethostbyname(const char* host, uint32_t* ip)
{
uint32_t addr = str_to_ip(host);
char buf[17];
//snprintf(buf, sizeof(buf), "%d.%d.%d.%d", (addr>>24)&0xff, (addr>>16)&0xff, (addr>>8)&0xff, addr&0xff);
if (strcmp(buf, host) == 0) {
*ip = addr;
return true;
}
return false;
}
*/

304
GPRS_Shield_Arduino.h Normal file
View File

@ -0,0 +1,304 @@
/*
* GPRS_Shield_Arduino.h
* A library for SeeedStudio seeeduino GPRS shield
*
* Copyright (c) 2015 seeed technology inc.
* Website : www.seeed.cc
* Author : lawliet zou
* Create Time: April 2015
* Change Log :
*
* The MIT License (MIT)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef __GPRS_SHIELD_ARDUINO_H__
#define __GPRS_SHIELD_ARDUINO_H__
#define NONE 0
#define SMS 1
#define CALL 2
#define BUSY 3
#define NO_CARRIER 4
#define NO_ANSWER 5
#define ANSWER 6
#define ERR 7
#define CHECK true
#define NO_CHECK false
#include "sim900.h"
/** GPRS class.
* used to realize GPRS communication
*/
enum Protocol {
CLOSED = 0,
TCP = 1,
UDP = 2,
};
class GPRS {
public:
/** Create GPRS instance
*/
GPRS(Stream& serial, uint8_t pkPin = 9);
/** get instance of GPRS class
*/
static GPRS* getInstance() {
return inst;
};
/** initialize GPRS module including SIM card check & signal strength
* @return true if connected, false otherwise
*/
bool init(void);
/** check if GPRS module is powered on or not
* @returns
* true on success
* false on error
*/
bool checkPowerUp(void);
/** power Up GPRS module (JP has to be soldered)
* @param pin pin 9 connected to JP jumper so we can power up and down through software
* @returns
*
*/
void powerOn();
void powerOff();
void reset();
/** send text SMS
* @param *number phone number which SMS will be send to
* @param *data message that will be send to
* @returns
* false on success
* true on error
*/
bool sendSMS(const char* number, const char* data);
/** Check if there is any UNREAD SMS: this function DOESN'T change the UNREAD status of the SMS
* @returns
* 1..20 on success, position/index where SMS is stored, suitable for the function ReadSMS
* -1 on error
* 0 - there is no SMS with specified status (UNREAD)
*/
char isSMSunread();
/** read SMS if getting a SMS message
* @param buffer buffer that get from GPRS module(when getting a SMS, GPRS module will return a buffer array)
* @param message buffer used to get SMS message
* @param check whether to check phone number(we may only want to read SMS from specified phone number)
* @returns
* true on success
* false on error
*/
bool readSMS(int messageIndex, char *message, byte length);
byte getEvent(char *message, char *phone, char *datetime, char *gprsBuffer, byte size, bool check = true);
/** get SMS on the fly, phone and date
* @param message buffer used to get SMS message
* @param phone buffer used to get SMS's sender phone number
* @param datetime buffer used to get SMS's send datetime
* @returns
* true on success
* false on error
*/
bool getSMS(char *message, char *phone, char *datetime, char *gprsBuffer, byte size);
/** delete SMS message on SIM card
* @param index the index number which SMS message will be delete
* @returns
* true on success
* false on error
*/
bool deleteSMS(int index);
/** call someone
* @param number the phone number which you want to call
* @returns
* true on success
* false on error
*/
bool callUp(char* number);
/** auto answer if coming a call
* @returns
*/
void answer(void);
/** hang up if coming a call
* @returns
* true on success
* false on error
*/
bool hangup(void);
/** Disable +CLIP notification when an incoming call is active, RING text is always shown. See isCallActive function
* This is done in order no to overload serial outputCheck if there is a call active and get the phone number in that case
* @returns
* true on success
* false on error
*/
bool ifcallNow(byte timeout = 1);
bool ifcallEnd(void);
void callEnd(void);
bool disableCLIPring(void);
/** Check if there is a call active and get the phone number in that case
* @returns
* true on success
* false on error
*/
bool isCallActive(char *number, char *gprsBuffer);
/** get DateTime from SIM900 (see AT command: AT+CLTS=1) as string
* @param
* @returns
* true on success
* false on error
*/
bool getDateTime(char *buffer);
/** getSignalStrength from SIM900 (see AT command: AT+CSQ)
* @returns
0 113 dBm or less
1 111 dBm
2...30 109... 53 dBm
31 51 dBm or greater
99 not known or not detectable
*/
byte getSignalStrength();
//////////////////////////////////////////////////////
/// GPRS
//////////////////////////////////////////////////////
/** Connect the GPRS module to the network.
* @return true if connected, false otherwise
*/
// bool join(const __FlashStringHelper *apn = 0, const __FlashStringHelper *userName = 0, const __FlashStringHelper *passWord = 0);
bool join(char* apn = 0, char* = 0, char* = 0, int timeout = 2 * DEFAULT_TIMEOUT);
/** Disconnect the GPRS module from the network
* @returns
*/
void disconnect(void);
/** Open a tcp/udp connection with the specified host on the specified port
* @param socket an endpoint of an inter-process communication flow of GPRS module,for SIM900 module, it is in [0,6]
* @param ptl protocol for socket, TCP/UDP can be choosen
* @param host host (can be either an ip address or a name. If a name is provided, a dns request will be established)
* @param port port
* @param timeout wait seconds till connected
* @returns true if successful
*/
bool connect(Protocol ptl, const char * host, int port, int timeout = 2 * DEFAULT_TIMEOUT);
bool connect(Protocol ptl, const __FlashStringHelper *host, const __FlashStringHelper *port, int timeout = 2 * DEFAULT_TIMEOUT);
/** Check if a tcp link is active
* @returns true if successful
*/
bool is_connected(void);
/** Close a tcp connection
* @returns true if successful
*/
bool close(void);
/** check if GPRS module is readable or not
* @returns true if readable
*/
int readable(void);
/** wait a few time to check if GPRS module is readable or not
* @param socket socket
* @param wait_time time of waiting
*/
int wait_readable(int wait_time);
/** wait a few time to check if GPRS module is writeable or not
* @param socket socket
* @param wait_time time of waiting
*/
int wait_writeable(int req_size);
int send(const char * str);
/** send data to socket
* @param socket socket
* @param str string to be sent
* @param len string length
* @returns return bytes that actually been send
*/
int send(const char * str, int len);
/** read data from socket
* @param socket socket
* @param buf buffer that will store the data read from socket
* @param len string length need to read from socket
* @returns bytes that actually read
*/
int recv(char* buf, int len);
/** convert the host to ip
* @param host host ip string, ex. 10.11.12.13
* @param ip long int ip address, ex. 0x11223344
* @returns true if successful
*/
//NOT USED bool gethostbyname(const char* host, uint32_t* ip);
char* getIPAddress();
unsigned long getIPnumber();
/** set GPIO level
* @param GPIO number
* @param GPIO level
* @returns true if successful
*/
bool controlGPIO(uint8_t num, uint8_t level);
private:
bool checkSIMStatus(void);
uint8_t _pkPin = 9;
uint32_t str_to_ip(const char* str);
Stream* stream;
static GPRS* inst;
uint32_t _ip;
char ip_string[16]; //XXX.YYY.ZZZ.WWW + \0
};
#endif

201
sim900.cpp Normal file
View File

@ -0,0 +1,201 @@
/*
* sim900.cpp
* A library for SeeedStudio seeeduino GPRS shield
*
* Copyright (c) 2015 seeed technology inc.
* Website : www.seeed.cc
* Author : lawliet zou
* Create Time: April 2015
* Change Log :
*
* The MIT License (MIT)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "sim900.h"
Stream *serialSIM900 = NULL;
void sim900_init(void * uart_device)
{
serialSIM900 = (Stream*)uart_device;
}
int sim900_check_readable()
{
return serialSIM900->available();
}
int sim900_wait_readable (int wait_time)
{
unsigned long timerStart;
int dataLen = 0;
timerStart = millis();
while((unsigned long) (millis() - timerStart) > wait_time * 1000UL) {
delay(500);
dataLen = sim900_check_readable();
if(dataLen > 0){
break;
}
}
return dataLen;
}
void sim900_flush_serial() {
while(sim900_check_readable()) {
char c = serialSIM900->read();
}
}
void sim900_read_buffer(char *buffer, int count, unsigned int timeout, unsigned int chartimeout)
{
//Serial.println("Read buff");
int i = 0;
unsigned long timerStart, prevChar;
timerStart = millis();
prevChar = 0;
while(1) {
while (sim900_check_readable()) {
char c = serialSIM900->read();
//Serial.print(c);
prevChar = millis();
buffer[i++] = c;
if(i >= count) break;
}
if(i >= count) break;
if ((unsigned long) (millis() - timerStart) > timeout * 1000UL) {
break;
}
//If interchar Timeout => return FALSE. So we can return sooner from this function. Not DO it if we dont recieve at least one char (prevChar <> 0)
if (((unsigned long) (millis() - prevChar) > chartimeout) && (prevChar != 0)) {
break;
}
}
}
void sim900_clean_buffer(char *buffer, int count)
{
for(int i = 0; i < count; i++) {
buffer[i] = '\0';
}
}
//HACERR quitar esta funcion ?
void sim900_send_byte(uint8_t data)
{
serialSIM900->write(data);
//Serial.print((char)data);
}
void sim900_send_char(const char c)
{
serialSIM900->write(c);
//Serial.print((char)c);
}
void sim900_send_cmd(const char* cmd)
{
for(int i=0; i<strlen(cmd); i++)
{
sim900_send_byte(cmd[i]);
}
}
void sim900_send_cmd(const __FlashStringHelper* cmd)
{
int i = 0;
const char *ptr = (const char *) cmd;
while (pgm_read_byte(ptr + i) != 0x00) {
sim900_send_byte(pgm_read_byte(ptr + i++));
}
}
void sim900_send_cmd_P(const char* cmd)
{
while (pgm_read_byte(cmd) != 0x00)
sim900_send_byte(pgm_read_byte(cmd++));
}
void sim900_send_AT(void)
{
sim900_check_with_cmd(F("AT\r\n"),"OK",CMD);
}
void sim900_send_End_Mark(void)
{
sim900_send_byte((char)26);
}
boolean sim900_wait_for_resp(const char* resp, DataType type, unsigned int timeout, unsigned int chartimeout)
{
int len = strlen(resp);
int sum = 0;
unsigned long timerStart, prevChar; //prevChar is the time when the previous Char has been read.
// Serial.println("Wait for resp");
// Serial.println(resp);
// Serial.print("with length: ");
// Serial.println(len);
timerStart = millis();
prevChar = 0;
//Serial.println("Received: ");
while(1) {
if(sim900_check_readable()) {
char c = serialSIM900->read();
//Serial.print(c);
prevChar = millis();
sum = (c==resp[sum]) ? sum+1 : 0;
if(sum == len - 1) {
//Serial.print("BREAK");
break;
}
}
if ((unsigned long) (millis() - timerStart) > timeout * 1000UL) {
//Serial.println("Timeout");
return false;
}
//If interchar Timeout => return FALSE. So we can return sooner from this function.
if (((unsigned long) (millis() - prevChar) > chartimeout) && (prevChar != 0)) {
//Serial.println("Interchar timeout");
return false;
}
}
//Serial.println("End wait cycle");
//If is a CMD, we will finish to read buffer.
if(type == CMD) sim900_flush_serial();
return true;
}
boolean sim900_check_with_cmd(const char* cmd, const char *resp, DataType type, unsigned int timeout, unsigned int chartimeout)
{
sim900_send_cmd(cmd);
return sim900_wait_for_resp(resp,type,timeout,chartimeout);
}
//HACERR que tambien la respuesta pueda ser FLASH STRING
boolean sim900_check_with_cmd(const __FlashStringHelper* cmd, const char *resp, DataType type, unsigned int timeout, unsigned int chartimeout)
{
sim900_send_cmd(cmd);
return sim900_wait_for_resp(resp,type,timeout,chartimeout);
}

62
sim900.h Normal file
View File

@ -0,0 +1,62 @@
/*
* sim900.h
* A library for SeeedStudio seeeduino GPRS shield
*
* Copyright (c) 2015 seeed technology inc.
* Website : www.seeed.cc
* Author : lawliet zou
* Create Time: April 2015
* Change Log :
*
* The MIT License (MIT)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef __SIM900_H__
#define __SIM900_H__
#include <Arduino.h>
#define DEFAULT_TIMEOUT 5 //seconds
#define DEFAULT_INTERCHAR_TIMEOUT 1500 //miliseconds
enum DataType {
CMD = 0,
DATA = 1,
};
void sim900_init(void * uart_device);
int sim900_check_readable();
int sim900_wait_readable(int wait_time);
void sim900_flush_serial();
void sim900_read_buffer(char* buffer,int count, unsigned int timeout = DEFAULT_TIMEOUT, unsigned int chartimeout = DEFAULT_INTERCHAR_TIMEOUT);
void sim900_clean_buffer(char* buffer, int count);
void sim900_send_byte(uint8_t data);
void sim900_send_char(const char c);
void sim900_send_cmd(const char* cmd);
void sim900_send_cmd(const __FlashStringHelper* cmd);
void sim900_send_cmd_P(const char* cmd);
void sim900_send_AT(void);
void sim900_send_End_Mark(void);
boolean sim900_wait_for_resp(const char* resp, DataType type, unsigned int timeout = DEFAULT_TIMEOUT, unsigned int chartimeout = DEFAULT_INTERCHAR_TIMEOUT);
boolean sim900_check_with_cmd(const char* cmd, const char *resp, DataType type, unsigned int timeout = DEFAULT_TIMEOUT, unsigned int chartimeout = DEFAULT_INTERCHAR_TIMEOUT);
boolean sim900_check_with_cmd(const __FlashStringHelper* cmd, const char *resp, DataType type, unsigned int timeout = DEFAULT_TIMEOUT, unsigned int chartimeout = DEFAULT_INTERCHAR_TIMEOUT);
#endif

877
watchdog_3-leonardo.ino Normal file
View File

@ -0,0 +1,877 @@
// ----------------------------------------------------------------------------------------------------
// Watchdog v3 - Leonardo
// EoF 2017
// ----------------------------------------------------------------------------------------------------
#include "watchdog_3.h"
GPRS modem(Serial1, MOD_PWR);
bool modemOK = false;
byte modemErrCount = 0;
DHT dht(T_PIN, DHT11);
char command[CMD_SIZE];
char message[SMS_SIZE];
char phone[PHONE_SIZE];
char datetime[DATE_SIZE];
char s_buffer[BUFFER_SIZE];
char l_buffer[LONG_BUFFER_SIZE];
bool cmdFromModem = false;
unsigned long t = 0;
int addr = 0;
byte temp = 0, hum = 0, loud = 0, power = 0, battery = 0;
byte btnCount = 0;
bool btnTrigger = false;
byte event;
const float r12_1 = 20000; // 20K
const float r12_2 = 10000; // 10K
const float r5_1 = 10000; // 20K
const float r5_2 = 10000; // 10K
const float rbat_1 = 10000; // 10K
const float rbat_2 = 10000; // 10K
const float rout_1 = 10000; // 10K
const float rout_2 = 10000; // 10K
float vcc = 0.0;
float k12, k5, kbat, kout;
float v12, v5, vbat, vout;
// эту константу (typVbg) необходимо откалибровать индивидуально
const float typVbg = 1.08; // 1.0 -- 1.2
void setup() {
Serial.begin(COM_BR);
Serial1.begin(MOD_BR);
modem.powerOn();
modemOK = modem.init();
// Конфигурируем пины
pinMode(A_PIN, INPUT);
pinMode(V5_PIN, INPUT);
pinMode(V12_PIN, INPUT);
pinMode(VBAT_PIN, INPUT);
pinMode(VOUT_PIN, INPUT);
pinMode(LED_PIN, OUTPUT);
pinMode(BTN_PIN, INPUT);
pinMode(FAN_PIN, OUTPUT);
// Инициализируем климатический сенсор
dht.begin();
// Коэффициенты делителей напряжений
k12 = r12_2 / (r12_1 + r12_2);
k5 = r5_2 / (r5_1 + r5_2);
kbat = rbat_2 / (rbat_1 + rbat_2);
kout = rout_2 / (rout_1 + rout_2);
modem.controlGPIO(1, 0);
modem.controlGPIO(2, 0);
modem.controlGPIO(3, 0);
modem.controlGPIO(4, 0);
sprint("Init");
printParams();
sprint_P(str_help);
initEEPROM();
}
void loop() {
if (millis() - t > PERIOD) {
getStatus();
t = millis();
//sprint("Status!");
}
checkModem();
if (!cmdFromModem) {
readSerial(command, CMD_SIZE);
}
if (command[0] != '\0') {
sprint(">", false);
sprint(command);
if (!strcmp_P(command, cmd_status)) {
getStatusMessage(message);
returnAnswer(message);
} else if (!strcmp_P(command, cmd_help)) {
sprint_P(str_help);
sendHelp();
} else if (!strcmp_P(command, cmd_sms_on)) {
smsOn(true);
returnAnswer();
} else if (!strcmp_P(command, cmd_sms_off)) {
smsOn(false);
returnAnswer();
} else if (!strcmp_P(command, cmd_auth_on)) {
authOn(true);
returnAnswer();
} else if (!strcmp_P(command, cmd_auth_off)) {
authOn(false);
returnAnswer();
} else if (!strcmp_P(command, cmd_fwd_on)) {
fwdOn(true);
returnAnswer();
} else if (!strcmp_P(command, cmd_fwd_off)) {
fwdOn(false);
returnAnswer();
} else if (!strcmp_P(command, cmd_on)) {
mainPowerOn();
returnAnswer();
} else if (!strcmp_P(command, cmd_off)) {
mainPowerOff();
returnAnswer();
} else if (!strcmp_P(command, cmd_reset)) {
mainReset();
returnAnswer();
} else if (!strcmp_P(command, cmd_a)) {
a_PowerBreak();
returnAnswer();
} else if (!strcmp_P(command, cmd_b)) {
b_PowerBreak();
returnAnswer();
} else if (!strcmp_P(command, cmd_forward)) {
forwardLastSMS();
} else if (!strcmp_P(command, cmd_modem_reset) && !cmdFromModem) {
modem.reset();
modem.init();
returnAnswer();
} else if (!strcmp_P(command, cmd_modem_console) && !cmdFromModem) {
modemConsole();
} else if (!strcmp_P(command, cmd_edit_ab) && !cmdFromModem) {
editAddressBook();
} else if (!strcmp_P(command, cmd_show_ab) && !cmdFromModem) {
printAddressBook();
} else {
sprint_P(str_help);
sendHelp();
}
}
ledOn();
delay(5);
ledOff();
if (buttonPressed()) {
ledOn();
if (btnCount < BTN_COUNT) btnCount++;
} else {
ledOff();
btnCount = 0;
btnTrigger = false;
}
if (btnCount >= BTN_COUNT && !btnTrigger) {
btnTrigger = true;
if (entryNotEmpty(0)) {
loadPhoneNumber(0, phone);
modem.callUp(phone);
sprint("Out call: ", phone);
while (true) {
ledOn();
event = modem.getEvent(message, phone, datetime, l_buffer, LONG_BUFFER_SIZE, NO_CHECK);
ledOff();
delay(150);
if (event == BUSY || event == NO_CARRIER || event == NO_ANSWER) break;
if (event == ANSWER) t = millis();
if (!buttonPressed()) btnTrigger = false;
if (millis() - t > CALL_TIMEOUT || (buttonPressed() && !btnTrigger)) {
btnTrigger = true;
break;
}
}
modem.hangup();
sprint("Call over");
} else {
flash(5);
}
}
}
// Запрос статуса
word getStatus() {
unsigned int stat = 0;
// Get sensors
getTH();
if (temp > 28) stat |= TEMP_WARN;
if (hum > 85) stat |= HUM_WARN;
loud = analogRead(A_PIN);
if (loud > 250) stat |= LOUD_WARN;
getVs();
if (v12 < 10) stat |= POWER_WARN;
if (vbat < 6.4) stat |= BAT_WARN;
return stat;
}
//
void printAll() {
sprint("phone: ", phone);
sprint("date: ", datetime);
sprint("msg: ", message);
sprint("msg len: ", strlen(message));
sprint("cmd: ", command);
sprint("t: ", temp);
sprint("h: ", hum);
sprint("l: ", loud);
sprint("mdm: ", modemOK, true);
sprint("sms: ", smsOn(), true);
sprint("auth: ", authOn(), true);
sprint("fwd: ", fwdOn(), true);
sprint("Vcc: ", vcc);
sprint("V12: ", v12);
sprint("V5: ", v5);
sprint("Vbat: ", vbat);
sprint("Vout: ", vout);
}
// Формируем читабельную строку со статусом
void getStatusMessage(char *message) {
word stat = getStatus();
char s[10];
message[0] = '\0';
if (stat != 0) {
strcat(message, "WARNING");
} else {
strcat(message, "OK");
}
strcat(message, "\nT: ");
itoa(temp, s, 10);
strcat(message, s);
strcat(message, "C");
if (stat & TEMP_WARN) strcat(message, " !");
strcat(message, " H: ");
itoa(hum, s, 10);
strcat(message, s);
strcat(message, "%");
if (stat & HUM_WARN) strcat(message, " !");
strcat(message, " L: ");
itoa(loud, s, 10);
strcat(message, s);
strcat(message, "UE");
if (stat & LOUD_WARN) strcat(message, " !");
strcat(message, "\nVcc: ");
ftoa(vcc, s);
strcat(message, s);
strcat(message, "V");
strcat(message, "\nV12: ");
ftoa(v12, s);
strcat(message, s);
strcat(message, "V");
strcat(message, " V5: ");
ftoa(v5, s);
strcat(message, s);
strcat(message, "V");
strcat(message, "\nVbat: ");
ftoa(vbat, s);
strcat(message, s);
strcat(message, "V");
strcat(message, " Vout: ");
ftoa(vout, s);
strcat(message, s);
strcat(message, "V");
strcat(message, "\n\nPower: ");
if (stat & POWER_WARN) strcat(message, "Off");
else strcat(message, "On");
strcat(message, " Battery: ");
if (stat & BAT_WARN) strcat(message, "Low");
else strcat(message, "Ok");
strcat(message, "\nSMS: ");
if (smsOn()) strcat(message, "On");
else strcat(message, "Off");
strcat(message, " Auth: ");
if (authOn()) strcat(message, "On");
else strcat(message, "Off");
strcat(message, " Fwd: ");
if (fwdOn()) strcat(message, "On");
else strcat(message, "Off");
}
// Обработка событий модема
void checkModem() {
cmdFromModem = false;
command[0] = '\0';
switch (modem.getEvent(message, phone, datetime, l_buffer, LONG_BUFFER_SIZE)) {
case ERR:
sprint("Mdm err!");
modemOK = false;
if (modemErrCount < MAX_ERROR) modemErrCount++;
if (modemErrCount >= MAX_ERROR) {
sprint("Rst mdm...");
modem.reset();
if (modem.init()) {
sprint("Mdm OK");
modemOK = true;
}
}
return;
case SMS:
sprint("SMS: ", phone);
flash(3);
if (authOn() && !authOK(phone)) {
strcpy_P(command, cmd_forward);
} else {
strncpy(command, message, CMD_SIZE);
}
cmdFromModem = true;
break;
case CALL:
sprint("Call: ", phone);
if (authOn() && !authOK(phone)) {
modem.hangup();
sprint("Unauth call");
} else {
modem.answer();
t = millis();
while (!modem.ifcallEnd()) {
ledOn();
delay(1000);
ledOff();
if (millis() - t > CALL_TIMEOUT || buttonPressed()) {
modem.hangup();
break;
}
}
sprint("Call over");
}
cmdFromModem = true;
break;
case NONE:
cmdFromModem = false;
break;
}
modemErrCount = 0;
modemOK = true;
}
// Консоль модема
void modemConsole() {
sprint_P(str_modem_cons_on);
sprint("Timeout is ", TIMEOUT, false);
sprint(" ms after last command");
t = millis();
byte i = 0;
while (millis() - t < TIMEOUT) {
if (Serial1.available()) {
while(Serial1.available()) {
s_buffer[i++] = Serial1.read();
if(i == BUFFER_SIZE) break;
}
Serial.write(s_buffer, i);
i = 0;
}
if (Serial.available()) {
Serial1.write(Serial.read());
t = millis();
}
}
sprint_P(str_modem_cons_off);
}
// Читаем команды с COM-порта
void readSerial(char *com, byte com_size) {
com[0] = '\0';
com[com_size - 1] = '\0';
byte i = 0;
while (Serial.available() > 0 && i < com_size - 1) {
com[i] = Serial.read();
if (com[i] == '\r') {
com[i] = '\0';
} else if (com[i] == '\n') {
com[i] = '\0';
break;
}
i++;
}
}
// Отправляем ответ
void returnAnswer(const char * answer) {
sprint(answer);
if (modemOK && smsOn() && cmdFromModem) {
modem.sendSMS(phone, answer);
}
}
void sendHelp() {
if (modemOK && smsOn() && cmdFromModem) {
if (authOn() && !authOK(phone)) return;
modem.sendSMS(phone, str_help);
}
}
void forwardLastSMS() {
char main_phone[PHONE_SIZE];
sprint("Get SMS from: ", false);
sprint(phone);
sprint("at: ", false);
sprint(datetime);
sprint(message);
if (fwdOn() && entryNotEmpty(0)) {
loadPhoneNumber(0, main_phone);
s_buffer[0] = '\0';
strcat(s_buffer, "SMS from ");
strcat(s_buffer, phone);
strcat(s_buffer, " at ");
strcat(s_buffer, datetime);
modem.sendSMS(main_phone, s_buffer);
modem.sendSMS(main_phone, message);
}
}
// Управление подключенным оборудованием
void mainPowerOn() {
if (!isPowerOn()) {
modem.controlGPIO(1, 1);
delay(500);
modem.controlGPIO(1, 0);
}
}
void mainPowerOff() {
modem.controlGPIO(1, 1);
delay(6000);
modem.controlGPIO(1, 0);
}
void mainReset() {
modem.controlGPIO(2, 1);
delay(500);
modem.controlGPIO(2, 0);
}
void a_PowerBreak() {
modem.controlGPIO(3, 1);
delay(5000);
modem.controlGPIO(3, 0);
}
void b_PowerBreak() {
modem.controlGPIO(4, 1);
delay(5000);
modem.controlGPIO(4, 0);
}
bool isPowerOn() {
getVs();
if (v12 > 10) return true;
else return false;
}
// Адресная книга
bool savePhoneNumber(byte index, char * phone) {
if (index > AB_MAX_INDEX) return false;
addr = AB_ADDR + index * PHONE_SIZE;
for (byte i = 0; i < PHONE_SIZE; i++)
EEPROM.update(addr + i, phone[i]);
return true;
}
bool delPhoneNumber(byte index) {
if (index > AB_MAX_INDEX) return false;
clearBuffer(phone, PHONE_SIZE);
strcpy(phone, "<NONE>");
return savePhoneNumber(index, phone);
}
bool loadPhoneNumber(byte index, char * phone) {
if (index > AB_MAX_INDEX) return false;
addr = AB_ADDR + index * PHONE_SIZE;
for (byte i = 0; i < PHONE_SIZE - 1; i++)
phone[i] = EEPROM.read(addr + i);
phone[PHONE_SIZE - 1] = '\0';
return true;
}
bool entryNotEmpty(byte index) {
char phone[PHONE_SIZE];
loadPhoneNumber(index, phone);
return strcmp(phone, "<NONE>");
}
void printPhoneNumber(byte index) {
if (index > AB_MAX_INDEX) {
sprint("Max index is: ", AB_MAX_INDEX);
return;
}
loadPhoneNumber(index, phone);
sprint("", index, false);
sprint(": ", false);
sprint(phone);
}
void printAddressBook() {
sprint("i Phone");
for (byte i = 0; i <= AB_MAX_INDEX; i++)
printPhoneNumber(i);
}
void clearAddressBook() {
for (byte i = 0; i <= AB_MAX_INDEX; i++)
delPhoneNumber(i);
}
void editAddressBook() {
char *p;
char indexString[4];
byte index, i = 0;
sprint_P(str_eab);
sprint_P(str_help_ab);
sprint_P(str_format_ab);
t = millis();
while (millis() - t < TIMEOUT) {
readSerial(s_buffer, BUFFER_SIZE);
if (s_buffer[0] != '\0') {
t = millis();
if (!strcmp_P(s_buffer, cmd_exit)) {
break;
} else if (!strcmp_P(s_buffer, cmd_show)) {
printAddressBook();
} else if (!strcmp_P(s_buffer, cmd_clear)) {
clearAddressBook();
} else {
p = strstr(s_buffer, ":");
i = 0;
while(s_buffer[i] != ':' && i < BUFFER_SIZE) i++;
if (p == NULL || i == 0 || i > 1) {
sprint_P(str_format_ab);
} else {
// Get index
clearBuffer(indexString, 4);
strncpy(indexString, s_buffer, i);
index = atoi(indexString);
// Get phone
i = 0;
p = strstr(s_buffer, ":") + 1;
strcpy(phone, p);
if (strcmp(phone, "delete")) {
// Save
savePhoneNumber(index, phone);
sprint("OK");
} else {
// Delete
delPhoneNumber(index);
sprint("OK");
}
}
}
}
}
sprint_P(str_help);
}
// Утилиты
void clearBuffer(char *in_buffer, byte in_size) {
for(byte i = 0; i < in_size - 1; i++) in_buffer[i] = '\0';
}
void printParams() {
if(smsOn()) sprint("SMS on | ", false); else sprint("SMS off | ", false);
if(authOn()) sprint("Auth on | ", false); else sprint("Auth off | ", false);
if(smsOn()) sprint("Fwd on"); else sprint("Fwd off");
}
bool authOK(char *phone) {
char t_phone[PHONE_SIZE];
for(byte i = 0; i <= AB_MAX_INDEX; i++) {
loadPhoneNumber(i, t_phone);
if (!strcmp(phone, t_phone)) return true;
}
return false;
}
void sprint(const char *description, const byte data, const bool ln) {
Serial.print(description);
Serial.print(data);
if (ln) Serial.println();
}
void sprint(const char *description, const char *data, const bool ln) {
Serial.print(description);
Serial.print(data);
if (ln) Serial.println();
}
void sprint(const char *description, const int data, const bool ln) {
Serial.print(description);
Serial.print(data);
if (ln) Serial.println();
}
void sprint(const char *description, const unsigned int data, const bool ln) {
Serial.print(description);
Serial.print(data);
if (ln) Serial.println();
}
void sprint(const char *description, const long int data, const bool ln) {
Serial.print(description);
Serial.print(data);
if (ln) Serial.println();
}
void sprint(const char *description, const long unsigned int data, const bool ln) {
Serial.print(description);
Serial.print(data);
if (ln) Serial.println();
}
void sprint(const char *description, const float data, const bool ln) {
Serial.print(description);
Serial.print(data);
if (ln) Serial.println();
}
void sprint(const char *description, const bool ln) {
Serial.print(description);
if (ln) Serial.println();
}
void sprint_P(const char *description, const bool ln) {
int len = strlen_P(description);
char c;
for (byte i = 0; i < len; i++) {
c = pgm_read_byte_near(description + i);
Serial.print(c);
}
if (ln) Serial.println();
}
bool smsOn() {
addr = PARAM_ADDR + SMS_ON_INDEX;
return (bool)EEPROM.read(addr);
}
void smsOn(bool temp) {
addr = PARAM_ADDR + SMS_ON_INDEX;
EEPROM.update(addr, (byte)temp);
}
bool authOn() {
addr = PARAM_ADDR + AUTH_ON_INDEX;
return (bool)EEPROM.read(addr);
}
void authOn(bool temp) {
addr = PARAM_ADDR + AUTH_ON_INDEX;
EEPROM.update(addr, (byte)temp);
}
bool fwdOn() {
addr = PARAM_ADDR + FWD_ON_INDEX;
return (bool)EEPROM.read(addr);
}
void fwdOn(bool temp) {
addr = PARAM_ADDR + FWD_ON_INDEX;
EEPROM.update(addr, (byte)temp);
}
void fanPWM(byte power) {
analogWrite(FAN_PIN, power);
}
void fanOn() {
digitalWrite(FAN_PIN, HIGH);
}
void fanOff() {
digitalWrite(FAN_PIN, LOW);
}
void ledPWM(byte power) {
analogWrite(LED_PIN, power);
}
void ledOn() {
digitalWrite(LED_PIN, HIGH);
}
void ledOff() {
digitalWrite(LED_PIN, LOW);
}
void flash(byte count) {
for (byte i = 0; i < count; i++) {
ledOn();
delay(5);
ledOff();
delay(150);
}
}
bool buttonPressed() {
if (digitalRead(BTN_PIN) == LOW) return true;
return false;
}
float readvcc() {
byte i;
float tmp = 0.0;
// Read 1.1V reference against Avcc
// set the reference to vcc and the measurement to the internal 1.1V reference
#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
#elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
ADMUX = _BV(MUX5) | _BV(MUX0);
#elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
ADMUX = _BV(MUX3) | _BV(MUX2);
#else
// works on an Arduino 168 or 328
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
#endif
delay(3); // Wait for Vref to settle
ADCSRA |= _BV(ADSC); // Start conversion
while (bit_is_set(ADCSRA,ADSC)); // measuring
uint8_t low = ADCL; // must read ADCL first - it then locks ADCH
uint8_t high = ADCH; // unlocks both
tmp = (high<<8) | low;
tmp = (typVbg * 1023.0) / tmp;
return tmp;
}
void getVs() {
v12 = 0.0;
v5 = 0.0;
vbat = 0.0;
vout = 0.0;
v12 += readvcc() * analogRead(V12_PIN);
v5 += readvcc() * analogRead(V5_PIN);
vbat += readvcc() * analogRead(VBAT_PIN);
vout += readvcc() * analogRead(VOUT_PIN);
vcc = readvcc();
v12 = v12 / 1024.0 / k12;
v5 = v5 / 1024.0 / k5;
vbat = vbat / 1024.0 / kbat;
vout = vout / 1024.0 / kout;
}
void printVs() {
sprint("Vcc: ", vcc);
sprint("V12: ", v12);
sprint("V5: ", v5);
sprint("Vbat: ", vbat);
sprint("Vout: ", vout);
}
void getTH() {
int check;
check = dht.read();
switch (check) {
case DHT_OK:
temp = dht.getTemperatureC();
hum = dht.getHumidity();
break;
case DHT_ERROR_TIMEOUT:
temp = 253;
break;
case DHT_ERROR_CHECKSUM:
temp = 254;
break;
}
}
void ftoa(float f, char *s) {
int d1, d2;
char t[10];
s[0] = '\0';
d1 = (int)f;
f = f - d1;
f = f * 100;
d2 = (int)f;
itoa(d1, t, 10);
strcat(s, t);
strcat(s, ".");
itoa(d2, t, 10);
strcat(s, t);
}
void initEEPROM() {
int flag_addr = PARAM_ADDR + EEPROM_INIT_INDEX;
if (EEPROM.read(flag_addr) != INIT_FLAG) {
clearAddressBook();
smsOn(false);
authOn(true);
fwdOn(true);
EEPROM.write(flag_addr, INIT_FLAG);
}
}

168
watchdog_3.h Normal file
View File

@ -0,0 +1,168 @@
// ----------------------------------------------------------------------------------------------------
// Watchdog v3 - Leonardo
// EoF 2017
// Header
// ----------------------------------------------------------------------------------------------------
#include <EEPROM.h>
#include <avr/pgmspace.h>
#include "GPRS_Shield_Arduino.h"
#include <TroykaDHT.h>
/*
* EEPROM mapping
* 1024 Kb
* 10 x 16 = 160 - address book | first addr 0
* 16 x 1 = 16 - parameters | first addr 160
* -------------
* 176 bytes
* 848 bytes free
*/
#define AB_ADDR 0
#define AB_MAX_INDEX 9
#define PARAM_ADDR 160
#define PARAM_MAX_INDEX 15
#define SMS_ON_INDEX 0
#define AUTH_ON_INDEX 1
#define FWD_ON_INDEX 2
#define EEPROM_INIT_INDEX 15
#define INIT_FLAG 0xAC
const char cmd_status[] PROGMEM = {"status"};
const char cmd_help[] PROGMEM = {"help"};
const char cmd_sms_on[] PROGMEM = {"sms on"};
const char cmd_sms_off[] PROGMEM = {"sms off"};
const char cmd_on[] PROGMEM = {"on"};
const char cmd_off[] PROGMEM = {"off"};
const char cmd_reset[] PROGMEM = {"reset"};
const char cmd_a[] PROGMEM = {"a"};
const char cmd_b[] PROGMEM = {"b"};
const char cmd_forward[] PROGMEM = {"forward"};
const char cmd_modem_reset[] PROGMEM = {"modem reset"};
const char cmd_modem_console[] PROGMEM = {"modem console"};
const char cmd_edit_ab[] PROGMEM = {"edit ab"};
const char cmd_show_ab[] PROGMEM = {"show ab"};
const char cmd_show[] PROGMEM = {"show"};
const char cmd_clear[] PROGMEM = {"clear"};
const char cmd_exit[] PROGMEM = {"exit"};
const char cmd_auth_on[] PROGMEM = {"auth on"};
const char cmd_auth_off[] PROGMEM = {"auth off"};
const char cmd_fwd_on[] PROGMEM = {"forward on"};
const char cmd_fwd_off[] PROGMEM = {"forward off"};
const char str_init_eeprom[] PROGMEM = {"EEPROM init complete"};
const char str_eab[] PROGMEM = {"Edit address book mode"};
const char str_modem_cons_on[] PROGMEM = {"Modem console mode on"};
const char str_modem_cons_off[] PROGMEM = {"Modem console mode off"};
const char str_help[] PROGMEM = {"Usage: help/status/on/off/reset/a/b/modem reset|console/edit ab/show ab/sms on|off/auth on|off/fwd on|off"};
const char str_help_ab[] PROGMEM = {"Type \"show\" to view, \"clear\" to erase, \"exit\" to return"};
const char str_format_ab[] PROGMEM = {"Format: \"i:+xxxxxxxxxxx\" to update or \"i:delete\" to delete"};
// Всякое
#define TIMEOUT 60000
#define PERIOD 15000
#define MAX_ERROR 5
#define CALL_TIMEOUT 60000
#define BTN_COUNT 3
// Сенсоры
#define A_PIN A0
#define T_PIN A1
#define VOUT_PIN A2
#define VBAT_PIN A3
#define V5_PIN A4
#define V12_PIN A5
#define LED_PIN 13
#define BTN_PIN 12
#define FAN_PIN 11
// GSM-модем
#define MOD_PWR 9
#define MOD_BR 115200
#define COM_BR 115200
#define SMS_LEN 160
// Размеры буферов;
#define CMD_SIZE 16
#define SMS_SIZE 160
#define PHONE_SIZE 16
#define DATE_SIZE 24
#define BUFFER_SIZE 64
#define LONG_BUFFER_SIZE 240
// Флаги статуса
#define TEMP_WARN 0x01
#define HUM_WARN 0x02
#define LOUD_WARN 0x04
#define POWER_WARN 0x08
#define BAT_WARN 0x016
word getStatus();
void getStatusMessage(char * message);
bool isCommandMatchIndex(const char * command, byte index);
void checkModem();
void modemConsole();
void incomingCall();
void readModem(char* msg, byte size);
void readSerial(char *com, byte size);
void returnAnswer(const char * answer = "OK");
void sendHelp();
void mainPowerOn();
void mainPowerOff();
void mainReset();
void a_PowerBreak();
void b_PowerBreak();
bool isPowerOn();
// Адресная книга
bool savePhoneNumber(byte index, char * phone);
bool delPhoneNumber(byte index);
bool loadPhoneNumber(byte index, char * phone);
bool entryNotEmpty(byte index);
void printPhoneNumber(byte index);
void printAddressBook();
void clearAddressBook();
void editAddressBook();
// Утилиты
void clearBuffer(char *buffer, byte size);
void printShortString(byte index, bool ln = true);
void printLongString(byte index, bool ln = true);
void printHelp();
void printParams();
bool authOK(char *phone);
void sprint(const char *description, const byte data, const bool ln = true);
void sprint(const char *description, const char *data, const bool ln = true);
void sprint(const char *description, const int data, const bool ln = true);
void sprint(const char *description, const unsigned int data, const bool ln = true);
void sprint(const char *description, const long int data, const bool ln = true);
void sprint(const char *description, const long unsigned int data, const bool ln = true);
void sprint(const char *description, const float data, const bool ln = true);
void sprint(const char *description, const bool ln = true);
void sprint_P(const char *description, const bool ln = true);
bool smsOn();
void smsOn(bool temp);
bool authOn();
void authOn(bool temp);
bool fwdOn();
void fwdOn(bool temp);
void fanPWM(byte power = 128);
void fanOn();
void fanOff();
void ledPWM(byte power = 128);
void ledOn();
void ledOff();
void flash(byte count = 3);
bool buttonPressed();
float readvcc();
void getVs();
void printVs();
void getTH();
void initEEPROM();