From 8c79fce887373e9075344bc71dc2f2613bf4c8ba Mon Sep 17 00:00:00 2001 From: EoF Date: Thu, 23 Jan 2020 23:58:57 +0500 Subject: [PATCH] First commit --- GPRS_Shield_Arduino.cpp | 875 +++++++++++++++++++++++++++++++++++++++ GPRS_Shield_Arduino.h | 304 ++++++++++++++ sim900.cpp | 201 +++++++++ sim900.h | 62 +++ watchdog_3-leonardo.ino | 877 ++++++++++++++++++++++++++++++++++++++++ watchdog_3.h | 168 ++++++++ 6 files changed, 2487 insertions(+) create mode 100644 GPRS_Shield_Arduino.cpp create mode 100644 GPRS_Shield_Arduino.h create mode 100644 sim900.cpp create mode 100644 sim900.h create mode 100644 watchdog_3-leonardo.ino create mode 100644 watchdog_3.h diff --git a/GPRS_Shield_Arduino.cpp b/GPRS_Shield_Arduino.cpp new file mode 100644 index 0000000..b55f0c8 --- /dev/null +++ b/GPRS_Shield_Arduino.cpp @@ -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 +#include +#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; +} +*/ diff --git a/GPRS_Shield_Arduino.h b/GPRS_Shield_Arduino.h new file mode 100644 index 0000000..36f516d --- /dev/null +++ b/GPRS_Shield_Arduino.h @@ -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 diff --git a/sim900.cpp b/sim900.cpp new file mode 100644 index 0000000..16166f3 --- /dev/null +++ b/sim900.cpp @@ -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; iread(); + //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); +} diff --git a/sim900.h b/sim900.h new file mode 100644 index 0000000..01ab7e5 --- /dev/null +++ b/sim900.h @@ -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 + +#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 diff --git a/watchdog_3-leonardo.ino b/watchdog_3-leonardo.ino new file mode 100644 index 0000000..4ee336e --- /dev/null +++ b/watchdog_3-leonardo.ino @@ -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, ""); + + 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, ""); +} + +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); + } +} diff --git a/watchdog_3.h b/watchdog_3.h new file mode 100644 index 0000000..6cfb230 --- /dev/null +++ b/watchdog_3.h @@ -0,0 +1,168 @@ +// ---------------------------------------------------------------------------------------------------- +// Watchdog v3 - Leonardo +// EoF 2017 +// Header +// ---------------------------------------------------------------------------------------------------- + +#include +#include +#include "GPRS_Shield_Arduino.h" +#include + +/* + * 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();