diff --git a/.gitignore b/.gitignore index 89cc49c..ffe74bd 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,7 @@ .vscode/c_cpp_properties.json .vscode/launch.json .vscode/ipch +.vscode/ +.vs/ + + diff --git a/.idea/.idea.GSM-Chata.dir/.idea/.gitignore b/.idea/.idea.GSM-Chata.dir/.idea/.gitignore new file mode 100644 index 0000000..8790f46 --- /dev/null +++ b/.idea/.idea.GSM-Chata.dir/.idea/.gitignore @@ -0,0 +1,13 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Rider ignored files +/contentModel.xml +/modules.xml +/projectSettingsUpdater.xml +/.idea.GSM-Chata.iml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/.idea.GSM-Chata.dir/.idea/encodings.xml b/.idea/.idea.GSM-Chata.dir/.idea/encodings.xml new file mode 100644 index 0000000..df87cf9 --- /dev/null +++ b/.idea/.idea.GSM-Chata.dir/.idea/encodings.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/.idea.GSM-Chata.dir/.idea/indexLayout.xml b/.idea/.idea.GSM-Chata.dir/.idea/indexLayout.xml new file mode 100644 index 0000000..7b08163 --- /dev/null +++ b/.idea/.idea.GSM-Chata.dir/.idea/indexLayout.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/.idea.GSM-Chata.dir/.idea/vcs.xml b/.idea/.idea.GSM-Chata.dir/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/.idea.GSM-Chata.dir/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..30f1af8 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,8 @@ +{ + "files.associations": { + "pinsdefinitions": "c", + "new": "cpp" + } + + +} diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..ada4221 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,14 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "type": "PlatformIO", + "task": "Build (uno)", + "problemMatcher": [ + "$platformio" + ], + "group": "build", + "label": "PlatformIO: Build (uno)" + } + ] +} \ No newline at end of file diff --git a/Arduino-GSM-Chata.code-workspace b/Arduino-GSM-Chata.code-workspace new file mode 100644 index 0000000..91479a6 --- /dev/null +++ b/Arduino-GSM-Chata.code-workspace @@ -0,0 +1,14 @@ +{ + "folders": [ + { + "name": "Arduino-GSM-Chata", + "path": "." + } + ], + "settings": { + "files.associations": { + "pinsdefinitions": "c", + "new": "cpp" + } + } +} \ No newline at end of file diff --git a/src/.theia/launch.json b/lib/.theia/launch.json similarity index 100% rename from src/.theia/launch.json rename to lib/.theia/launch.json diff --git a/lib/Data/DeviceBase.cpp b/lib/Data/DeviceBase.cpp new file mode 100644 index 0000000..d3b8c10 --- /dev/null +++ b/lib/Data/DeviceBase.cpp @@ -0,0 +1,3 @@ +#include "DeviceBase.h" + + DeviceBase::DeviceBase(const String id): Id(id) {}; \ No newline at end of file diff --git a/lib/Data/DeviceBase.h b/lib/Data/DeviceBase.h new file mode 100644 index 0000000..f6e336f --- /dev/null +++ b/lib/Data/DeviceBase.h @@ -0,0 +1,14 @@ +#ifndef _DeviceBase_h +#define _DeviceBase_h + +#include + +class DeviceBase +{ +public: + String Id; + DeviceBase(const String id); + +}; + +#endif \ No newline at end of file diff --git a/lib/Data/GSMMobileData.cpp b/lib/Data/GSMMobileData.cpp new file mode 100644 index 0000000..ba6b5a0 --- /dev/null +++ b/lib/Data/GSMMobileData.cpp @@ -0,0 +1,47 @@ + +#include +#include "GSMMobileData.h" +#include "EEPROMUtils.h" +#include "DeviceBase.h" + + +GSMMobileData::GSMMobileData(String id) : DeviceBase(id) +{ + readAllData(id); +} + +void GSMMobileData::readAllData(String id) +{ + EEPROMUtils eepromUtils = EEPROMUtils(); + MobileNumber = eepromUtils.readString(1, 20); + Sms = eepromUtils.readString(21, 100); +} + +void GSMMobileData::updateMobileNumber(const String &newMobileNumber) +{ + if (newMobileNumber.length() <= 0) + { + return; + } + + if (newMobileNumber != MobileNumber) + { + EEPROMUtils eepromUtils = EEPROMUtils(); + MobileNumber = newMobileNumber; + eepromUtils.writeString(1, newMobileNumber, 20); + } +} + +void GSMMobileData::updateSMS(const String &newSMS) +{ + if (newSMS.length() <= 0) + { + return; + } + if (newSMS != Sms) + { + EEPROMUtils eepromUtils = EEPROMUtils(); + Sms = newSMS; + eepromUtils.writeString(21, newSMS, 100); + } +} diff --git a/lib/Data/GSMMobileData.h b/lib/Data/GSMMobileData.h new file mode 100644 index 0000000..db64a58 --- /dev/null +++ b/lib/Data/GSMMobileData.h @@ -0,0 +1,24 @@ +#ifndef GSMMobileData_H +#define GSMMobileData_H + +#include +#include "DeviceBase.h" // Include the missing header file + + +class GSMMobileData : public DeviceBase +{ +private: + void readAllData(String id); + +public: + String MobileNumber; + String Sms; + + GSMMobileData(String id); + + void updateMobileNumber(const String &newMobileNumber); + + void updateSMS(const String &newSMS); +}; + +#endif // GSMMobileData_H \ No newline at end of file diff --git a/lib/Data/PinTypeIn.cpp b/lib/Data/PinTypeIn.cpp new file mode 100644 index 0000000..163fb13 --- /dev/null +++ b/lib/Data/PinTypeIn.cpp @@ -0,0 +1,9 @@ +#include +#include "PinTypeIn.h" + + + +bool PinTypeIn::IsPinHigh() +{ + return digitalRead(_pin) == HIGH ? true : false; +} diff --git a/lib/Data/PinTypeIn.h b/lib/Data/PinTypeIn.h new file mode 100644 index 0000000..33709eb --- /dev/null +++ b/lib/Data/PinTypeIn.h @@ -0,0 +1,31 @@ +#ifndef PinTypeIn_H +#define PinTypeIn_H + +#include +#include "DeviceBase.h" + +class PinTypeIn : public DeviceBase +{ +private: + uint8_t _pin; + unsigned long _debounceDelay; + unsigned long _lastDebounceTime; + int _lastButtonState; + int _buttonState; + +public: + const char *description; + + PinTypeIn(String id, uint8_t pin, unsigned long debounceDelay, const char *description): DeviceBase(id), _pin(pin), _debounceDelay(debounceDelay) + { + this->description = description; + pinMode(pin, INPUT); + } + + /// @brief Get Actual Pin Value if is SET = True, if is NOT SET = False + /// @return + bool IsPinHigh(); + +}; + +#endif \ No newline at end of file diff --git a/lib/Data/PinTypeOut.cpp b/lib/Data/PinTypeOut.cpp new file mode 100644 index 0000000..51e05ce --- /dev/null +++ b/lib/Data/PinTypeOut.cpp @@ -0,0 +1,20 @@ +#include "PinTypeOut.h" +#include + + +void PinTypeOut::setOutputSignalToHigh() +{ + digitalWrite(_pinNumber, HIGH); + +} + +void PinTypeOut::setOutputSignalToLow() +{ + digitalWrite(_pinNumber, LOW); + +} + +bool PinTypeOut::IsPinOn() +{ + return digitalRead(_pinNumber) == HIGH; +} \ No newline at end of file diff --git a/lib/Data/PinTypeOut.h b/lib/Data/PinTypeOut.h new file mode 100644 index 0000000..9a355ae --- /dev/null +++ b/lib/Data/PinTypeOut.h @@ -0,0 +1,37 @@ +#ifndef PINTYPEOUT_H +#define PINTYPEOUT_H + +#include +#include "DeviceBase.h" + +class PinTypeOut : public DeviceBase +{ +private: + uint8_t _pinNumber; + + unsigned long _debounceTime; + unsigned long lastStateChangeTime; + + +public: + const char *description; + + PinTypeOut(String id, uint8_t pinNumber, unsigned long debounceTime, const char *description) + : DeviceBase(id), _pinNumber(pinNumber), _debounceTime(debounceTime), lastStateChangeTime(0), description(description) + { + pinMode(pinNumber, OUTPUT); + } + + PinTypeOut(String id, uint8_t pinNumber, const char *description) + : DeviceBase(id), _pinNumber(pinNumber),_debounceTime(0), lastStateChangeTime(0), description(description) + { + pinMode(pinNumber, OUTPUT); + } + + void setOutputSignalToHigh(); + void setOutputSignalToLow(); + + bool IsPinOn(); +}; + +#endif // PinTypeOut_H \ No newline at end of file diff --git a/lib/Data/WebServerData.cpp b/lib/Data/WebServerData.cpp new file mode 100644 index 0000000..4e4fb77 --- /dev/null +++ b/lib/Data/WebServerData.cpp @@ -0,0 +1,49 @@ +/*#include +#include +#include + +String WebServerData::getValue(const String &data, const String &key) +{ + return getValue(data, key, '&'); +} + +/// @brief Separe data PIN1=ON to PIN1 and ON +/// @param data PIN1=ON +/// @param key = +/// @param endchar end of string & or space or any other character +/// @return +String WebServerData::getValue(const String &data, const String &key, char endchar) +{ + int keyIndex = data.indexOf(key); + if (keyIndex == -1) + { + return ""; // return empty string if key is not found + } + int separatorIndex = data.indexOf(endchar, keyIndex); + + String value = data.substring(keyIndex + key.length(), separatorIndex != -1 ? separatorIndex : data.length()); + + return removeAllCharactersAfterEmptySpace(value); +} + +String WebServerData::getVariableName(const String &data, const String &key) +{ + int keyIndex = data.indexOf(key); + + String value = data.substring(0, keyIndex != -1 ? keyIndex : keyIndex); + + return removeAllCharactersAfterEmptySpace(value); +} + +String WebServerData::removeAllCharactersAfterEmptySpace(String &data) +{ + int keyIndex = data.indexOf(' '); + if (keyIndex == -1) + { + return data; // return empty string if key is not found + } + data.remove(keyIndex); + data.replace("_", " "); + return data; +} +*/ \ No newline at end of file diff --git a/lib/Data/WebServerData.h b/lib/Data/WebServerData.h new file mode 100644 index 0000000..273ebd8 --- /dev/null +++ b/lib/Data/WebServerData.h @@ -0,0 +1,23 @@ +/*ifndef WebServerData_H +#define WebServerData_H + +#include +#include + +class WebServerData +{ +public: + String Request; + bool IsEmpty; + + WebServerData() : IsEmpty(true){}; + WebServerData(String request) : Request(request), IsEmpty(false){}; + String getValue(const String &data, const String &key, char endchar); + String getValue(const String &data, const String &key); + String removeAllCharactersAfterEmptySpace(String &data); + String getVariableName(const String &data, const String &key); + +}; + +#endif // WebServerData_H +*/ \ No newline at end of file diff --git a/lib/Device/EEPROMUtils.cpp b/lib/Device/EEPROMUtils.cpp new file mode 100644 index 0000000..cdeaae7 --- /dev/null +++ b/lib/Device/EEPROMUtils.cpp @@ -0,0 +1,32 @@ +#include "EEPROMUtils.h" +#include +#include + + +// Statická metoda pro čtení řetězce z EEPROM +String EEPROMUtils::readString(int addr, int length) +{ + String data; + for (int i = 0; i < length; i++) + { + char onedata = char(EEPROM.read(addr + i)); // read one byte at a time + if (onedata == '\n') + return data; + data += onedata; + } + return data; +} + +// Statická metoda pro zápis řetězce do EEPROM +void EEPROMUtils::writeString(int addr, String data, int limit) +{ + int numBytes = data.length(); // get length of the string + for (int i = 0; i < numBytes && i < limit; i++) + { + EEPROM.write(addr + i, data[i]); // write one byte at a time + } + if (numBytes < limit) + { + EEPROM.write(addr + numBytes, '\n'); // add newline character at the end + } +} diff --git a/lib/Device/EEPROMUtils.h b/lib/Device/EEPROMUtils.h new file mode 100644 index 0000000..f7aded6 --- /dev/null +++ b/lib/Device/EEPROMUtils.h @@ -0,0 +1,13 @@ +#ifndef EEPROMUtils_h +#define EEPROMUtils_h + +#include // Include the missing header file for the String class + +class EEPROMUtils +{ +public: + static String readString(int addr, int length); + static void writeString(int addr, const String data, int limit); // Fix the function signature +}; + +#endif \ No newline at end of file diff --git a/lib/Device/GSMMobileDevice.cpp b/lib/Device/GSMMobileDevice.cpp new file mode 100644 index 0000000..b57e38b --- /dev/null +++ b/lib/Device/GSMMobileDevice.cpp @@ -0,0 +1,112 @@ +#include "GSMMobileData.h" +#include +#include "GSMMobileDevice.h" +#include "DebugLog.h" +#include "Helper.h" + +//#define DEBUG + +void GSMMobileDevice::init() +{ + // init software serial + _gsmSerial.begin(_baudRate); + delay(5000); // initialization GSM module (give it some time to boot up) +} + +void GSMMobileDevice::end() +{ + _gsmSerial.end(); +#ifdef DEBUG + DebugLog::log("GSM End .."); +#endif +} + +void GSMMobileDevice::executeAtCommand(const String &atCommand) +{ +#ifdef DEBUG + DebugLog::log(atCommand); +#endif + + _gsmSerial.print(atCommand + "\r"); + delay(500); +#ifdef DEBUG + DebugLog::log("read fromGMS:" + readStringSerialPort()); + delay(100); +#endif +} + +String GSMMobileDevice::readStringSerialPort() +{ + return _gsmSerial.readString(); +} + +void GSMMobileDevice::sendSMSToGSM(GSMMobileData gsmData) +{ +#ifdef DEBUG + DebugLog::log("SMS Start SEND SMS Id:" + gsmData.Id + " M:" + gsmData.MobileNumber + " with message " + gsmData.Sms); +#endif + executeAtCommand("AT+CMGF=1"); + + executeAtCommand("AT + CMGS =\"" + gsmData.MobileNumber + "\""); + executeAtCommand("ID:" + gsmData.Id + " Msg:" + gsmData.Sms); + + delay(1000); + // Send a Ctrl+Z / ASCII SUB + _gsmSerial.print((char)26); + delay(500); + // Close the connection + _gsmSerial.print((char)27); + delay(500); +} + +bool GSMMobileDevice::checkSMSError() +{ + return true; + String response = readStringSerialPort(); + if (response.indexOf("ERROR") != -1) + { + // If there was an error, try to reconnect and resend + _gsmSerial.println("AT+CFUN=1,1"); // Restart the module + delay(15000); // Wait for the module to restart + return true; + } + return false; +} + +unsigned long _lastSMSTime = 0; + +void GSMMobileDevice::sendSMS(GSMMobileData gsmData) +{ + // Check if enough time has passed since the last SMS was sent + if (millis() - _lastSMSTime >= 60000) + { + // Send the SMS + init(); + sendSMSToGSM(gsmData); + if (checkSMSError()) + { + // Log that the SMS was sent + DebugLog::log("SMS sent successfully."); + } + else + { + // Log that the SMS was not sent + DebugLog::log("SMS not sent. Error occurred."); + } + // Update the last SMS time + _lastSMSTime = millis(); + end(); + } + else + { + // Log that the SMS was not sent + DebugLog::log("SMS not sent. Not enough time has passed since the last SMS was sent."); + } +} + +// GSMMobileDevice::~GSMMobileDevice() +// { +// // // close gsmSerial +// // // close gsmSerial +// _gsmSerial.end(); +// } \ No newline at end of file diff --git a/lib/Device/GSMMobileDevice.h b/lib/Device/GSMMobileDevice.h new file mode 100644 index 0000000..303ae11 --- /dev/null +++ b/lib/Device/GSMMobileDevice.h @@ -0,0 +1,31 @@ +#ifndef GSMMobileDevice_H +#define GSMMobileDevice_H + +#include "GSMMobileData.h" +#include "SoftwareSerial.h" + +class GSMMobileDevice +{ +private: + SoftwareSerial _gsmSerial; + + // Methods + + void executeAtCommand(const String &atCommand); + String readStringSerialPort(); + void sendSMSToGSM(GSMMobileData gsmData); + long _baudRate; + bool checkSMSError(); + +public: + // Constructor with no parameters + GSMMobileDevice(uint8_t pinRx, uint8_t pinTx, long baudRate) : _gsmSerial(pinRx, pinTx), _baudRate(baudRate) + { + } + + // Methods + void init(); + void sendSMS(GSMMobileData gsmData); + void end(); +}; +#endif // GSMDevice_H \ No newline at end of file diff --git a/lib/Device/WebServer.cpp b/lib/Device/WebServer.cpp new file mode 100644 index 0000000..7d1dcbc --- /dev/null +++ b/lib/Device/WebServer.cpp @@ -0,0 +1,137 @@ +/*#include +#include +#include "WebServer.h" +#include "WebServerData.h" +#include "DebugLog.h" + +// Constructor +WebServer::WebServer() : _server(80) {} + +WebServer::WebServer(byte mac[6], IPAddress ip, uint16_t port) : _ip(ip), _server(port) +{ + memcpy(_mac, mac, 6); +} + +// Initialize the Ethernet and start the server +void WebServer::init() +{ + Ethernet.begin(_mac, _ip); + +#ifdef DEBUG + DebugLog::log("Ethernet IP: " + Ethernet.localIP()); +#endif + + _server.begin(); + +#ifdef DEBUG + DebugLog::log("Server Start"); +#endif +} + +// Move the declaration of EthernetClient inside the WebServer class +EthernetClient client; +// Handle client requests +WebServerData WebServer::getWebServerData() +{ + // Check if a client has connected + + client = _server.available(); + if (client) + { + if (client.connected()) + { +#ifdef DEBUG + DebugLog::log("Client connected"); +#endif + + unsigned long startTime = millis(); + while (client.available() == 0) + { + if (millis() - startTime >= 10000) + { + break; + } + delay(10); + } + + client.println(F("HTTP/1.1 200 OK")); // Respond together with the Web page in the HTML + client.println(F("Content-Type: text/html")); + client.println(F("Connection: close")); + client.println(); + + String request = client.readStringUntil('\r'); + + if (request.startsWith("GET / HTTP/1.1")) + { + +#ifdef DEBUG + DebugLog::log("EMPTY DATA: " + request); +#endif + + return WebServerData(); + } + + // client.flush(); // Clear the incoming buffer after reading the GET request + // If you've gotten to the end of the line (received a newline + // character) and the line is blank, the http request has ended, + // so you can send a reply + + if (request.startsWith("GET /")) + { +#ifdef DEBUG + DebugLog::log("GET WEB SERVER DATA: " + request); +#endif + WebServerData webServerData = WebServerData(request); + return webServerData; + } + } + } + return WebServerData(); + // Give the web browser time to receive the data +} + +// Return a default-constructed WebServerData object if no client is available + +void WebServer::endServer() +{ + if (_server.available()) + { + delay(10); + // Close the connection + client.stop(); + } +} + +void WebServer::SendToBrowser(const String &dataString) +{ + const byte chunkSize = 50; + + // Send data in chunks + unsigned int stringIndex = 0; + unsigned long startTime = millis(); + + while (stringIndex < dataString.length()) + { + if (client.availableForWrite() > 0) + { + int chunkLength = min(chunkSize, dataString.length() - stringIndex); + const String chunk = dataString.substring(stringIndex, stringIndex + chunkLength); + + // Send the chunk (consider error handling) +#ifdef DEBUG + DebugLog::log("StBC: " + chunk); +#endif + client.print(chunk); + stringIndex += chunkLength; + delay(5); // Optional delay between chunks + } + else if (millis() - startTime >= 10000) + { + return; // Timeout + } + + delay(5); // Optional delay between chunks + } + client.println(""); +} +*/ \ No newline at end of file diff --git a/lib/Device/WebServer.h b/lib/Device/WebServer.h new file mode 100644 index 0000000..d9f8f53 --- /dev/null +++ b/lib/Device/WebServer.h @@ -0,0 +1,27 @@ +/*#ifndef WebServer_H +#define WebServer_H + +#include +#include +#include + +class WebServer +{ +private: + byte _mac[6]; + IPAddress _ip; + EthernetServer _server; + + public: + EthernetClient client; + + WebServer(); + WebServer(byte mac[6], IPAddress ip, uint16_t port); + WebServerData getWebServerData(); + void init(); + void endServer(); + void SendToBrowser(const String &dataString); +}; + +#endif // WebServer_H +*/ \ No newline at end of file diff --git a/lib/Helper/DebugLog.cpp b/lib/Helper/DebugLog.cpp new file mode 100644 index 0000000..b12b64a --- /dev/null +++ b/lib/Helper/DebugLog.cpp @@ -0,0 +1,31 @@ + + +#include +#include "DebugLog.h" + +void DebugLog::log(const String &log) +{ + // WriteToSerial(log); +} + +void DebugLog::init(const long &bound) +{ + Serial.begin(bound); + Serial.println("Serial Port Initialized"); +} + +void DebugLog::WriteToSerial(const String &dataString) +{ + const byte chunkSize = 60; + unsigned int stringIndex = 0; + while (stringIndex < dataString.length()) + { + int chunkLength = min(chunkSize, dataString.length() - stringIndex); + String chunk = dataString.substring(stringIndex, stringIndex + chunkLength); + + Serial.print(chunk); + stringIndex += chunkLength; + delay(4); // Optional delay between chunks + } + Serial.println(""); +} diff --git a/lib/Helper/DebugLog.h b/lib/Helper/DebugLog.h new file mode 100644 index 0000000..792d258 --- /dev/null +++ b/lib/Helper/DebugLog.h @@ -0,0 +1,18 @@ +#ifndef DebugLog_H +#define DebugLog_H + +#include + + +class DebugLog +{ +private: + static void WriteToSerial(const String &dataString); + +public: + static void init(const long &bound); + static void log(const String &log); +}; + + +#endif \ No newline at end of file diff --git a/lib/Helper/HTMLGenerator.cpp b/lib/Helper/HTMLGenerator.cpp new file mode 100644 index 0000000..248c11d --- /dev/null +++ b/lib/Helper/HTMLGenerator.cpp @@ -0,0 +1,21 @@ +#include +#include "HTMLGenerator.h" +#include "DebugLog.h" + +const String HTMLGenerator::GetElement(const String &tag, const String &content) +{ + return "<" + tag + ">" + content + ""; +} + +const String HTMLGenerator::DisplayOuputPinStatus(const String &pinName, const bool &isOn, const String &description) +{ + const String pinvariable = pinName + (isOn ? "=OFF" : "=ON"); + String content = pinName + " is " + (isOn ? "ON" : "OFF") + " | " + pinvariable + " "; + return GetElement("p", content); +} + +const String HTMLGenerator::DisplayInputPinStatus(const String &pinName, const bool &isOn, const String &description) +{ + const String content = pinName + " is " + (isOn ? "ON" : "OFF"); + return GetElement("H4", content); +} diff --git a/lib/Helper/HTMLGenerator.h b/lib/Helper/HTMLGenerator.h new file mode 100644 index 0000000..f14ed4e --- /dev/null +++ b/lib/Helper/HTMLGenerator.h @@ -0,0 +1,14 @@ +#ifndef HTMLGENERATOR_H +#define HTMLGENERATOR_H + +#include + +class HTMLGenerator +{ +public: + static const String GetElement(const String &tag,const String &content ); + static const String DisplayOuputPinStatus( const String &pinName,const bool &isOn, const String &description); + static const String DisplayInputPinStatus( const String &pinName,const bool &isOn,const String &description); +}; + +#endif // HTMLGENERATOR_H \ No newline at end of file diff --git a/lib/Helper/Helper.cpp b/lib/Helper/Helper.cpp new file mode 100644 index 0000000..66d3f7b --- /dev/null +++ b/lib/Helper/Helper.cpp @@ -0,0 +1,30 @@ + +#include +#include +#include "Helper.h" + +unsigned long currentTime = millis(); +unsigned long lastOverflowTime = 0; // Add missing declaration and initialization + +// Function to check for overflow and update lastOverflowTime +bool Helper::hasOverflowed() +{ + if (currentTime < lastOverflowTime) + { + lastOverflowTime = currentTime; + return true; + } + return false; +} + +// Calculate elapsed time considering overflow +unsigned long Helper::getElapsedTime(bool resetTime) +{ + + unsigned long elapsedTime = currentTime - lastOverflowTime; + if (hasOverflowed()) + { + elapsedTime += (ULONG_MAX - lastOverflowTime); // Add the time since last overflow + } + return elapsedTime; +} diff --git a/lib/Helper/Helper.h b/lib/Helper/Helper.h new file mode 100644 index 0000000..84e3550 --- /dev/null +++ b/lib/Helper/Helper.h @@ -0,0 +1,18 @@ +#ifndef HELPER_H +#define HELPER_H + +#include +#include + +class Helper +{ +private: + +public: + Helper(); + + bool hasOverflowed(); + unsigned long getElapsedTime(bool reset); +}; + +#endif \ No newline at end of file diff --git a/platformio.ini b/platformio.ini index 1ee07a7..bea0a82 100644 --- a/platformio.ini +++ b/platformio.ini @@ -12,4 +12,9 @@ platform = atmelavr board = uno framework = arduino -lib_deps = arduino-libraries/Ethernet@^2.0.2 +debug_tool = avr-stub +debug_port = COM8 +monitor_port = COM8 +monitor_speed = 115200 +lib_deps = + jdolinay/avr-debugger@^1.5 diff --git a/src/Zabezpecovacka-GSM.cpp b/src/Zabezpecovacka-GSM.cpp deleted file mode 100644 index 7c3d3b8..0000000 --- a/src/Zabezpecovacka-GSM.cpp +++ /dev/null @@ -1,337 +0,0 @@ -#include -#include -#include -#include - -#define DEBUG - -// MAC address and IP address for the Ethernet module -byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; -IPAddress ip(192, 168, 1, 177); - -// Initialize the Ethernet server (port 80 is default for HTTP) -EthernetServer server(80); - -// Initialize software serial for RS232 communication (RX, TX) -SoftwareSerial gsmSerial(5, 6); // RX, TX (this is using for communicate with GSM module as AT commands) - -uint8_t PIN_OUT_2 = 2; -uint8_t PIN_OUT_3 = 3; - -String ElmP = "p"; -String ElmH2 = "H2"; -EthernetClient client; - -struct BaseTypeScript { - String id; -}; - -// Definice struktury pro ukládání parametrů GET požadavku -struct GsmPostParams : public BaseTypeScript { - String mobileNumber; - String sms; -}; - -//Pin (Vstupni piny) -struct pinState { - uint8_t pinNumber; - volatile bool lastState; - unsigned long debounceTime; - unsigned long lastStateChangeTime; - const char *description; -}; - -const uint8_t numInputPins = 2; // Replace with the actual number of input pins - -// definice ignorace vstupnich pinu -pinState inputStates[numInputPins] = { - // { 4, LOW, 60000, 0, "Enter Door" }, // Pin 4, debounce time 1 minute - { 7, LOW, 30000, 0, "Alarm Alert" }, // Pin 8, debounce time 30 seconds - { 8, LOW, 10000, 0, "Electric Alarm" } // Pin 9, debounce time 10 seconds -}; -GsmPostParams gsmPostParams; - -String readStringFromEEPROM(int addr, int length) { - String data; - for (int i = 0; i < length; i++) { - char onedata = char(EEPROM.read(addr + i)); // read one byte at a time - if (onedata == '\n') return data; - data += onedata; - } - return data; -} - -void logDebug(const String &log) { - // Serial.println(log); -} - -void setup() { - - // if (Serial.available() > 0) { - // Serial.begin(115200); - // } - - gsmSerial.begin(115200); - - // Start the Ethernet connection and the server - Ethernet.begin(mac, ip); - server.begin(); - - gsmPostParams.mobileNumber = readStringFromEEPROM(1, 20); - gsmPostParams.sms = readStringFromEEPROM(21, 200); - gsmPostParams.id = "GSM"; - - logDebug("Init .."); - // Set all input pins as inputs - for (int i = 0; i < numInputPins; i++) { - pinMode(inputStates[i].pinNumber, INPUT); - } - - // Set pin 2 and 3 as OUTPUT - pinMode(PIN_OUT_2, OUTPUT); - pinMode(PIN_OUT_3, OUTPUT); - - logDebug("Init I/O is OK"); - // Open serial communications -} - - -String removeAllCharactesrAfterEmpty(String& data) { - int keyIndex = data.indexOf(' '); - if (keyIndex == -1) { - return data; // return empty string if key is not found - } - data.remove(keyIndex); - data.replace("+", " "); - return data; -} - -// Metoda pro parsování parametrů - -String getValue(String &data, const String &key) { - int keyIndex = data.indexOf(key); - if (keyIndex == -1) { - return ""; // return empty string if key is not found - } - int separatorIndex = data.indexOf('&', keyIndex); - - String value = data.substring(keyIndex + key.length(), separatorIndex != -1 ? separatorIndex : data.length()); - logDebug("Only value:" + value); - return removeAllCharactesrAfterEmpty(value); -} - -void writeToLogAndIntoWebAsP(const String &msg, const String &element) { - String lineElement = "<" + element + ">" + msg + ""; - // logDebug(msg); - //gsmlogDebug("GSM:" + msg); - client.println(lineElement); -} - -// pin = definice pinu Arduino, string je post hodnota, ktera se porovnava -void checkValue(String &request, uint8_t pin, const String &postValue) { - if (request.indexOf("/PIN") == -1) return; - - if (request.indexOf("/" + postValue + "=ON") != -1) { - digitalWrite(pin, HIGH); - String msgOn = "PIN ON: " + String(pin) + " PostVale: " + postValue; - writeToLogAndIntoWebAsP(msgOn, ElmH2); // Send state to debug console - } - if (request.indexOf("/" + postValue + "=OFF") != -1) { - digitalWrite(pin, LOW); - String msgOff = "PIN OFF: " + String(pin) + " PostVale: " + postValue; - writeToLogAndIntoWebAsP(msgOff, ElmH2); // Send state to debug console - } -} - - - -String ConvertStatusToString(uint8_t &pin, bool showLink) { - String pinAsStr = String(pin); - String elm = ""; - if (digitalRead(pin) == HIGH) { - elm = "PIN" + pinAsStr + " is ON "; - if (showLink) elm += "OFF"; - return elm; - } - - elm = "PIN" + pinAsStr + " is OFF "; - if (showLink) elm += "ON"; - return elm; -} - -void changeDataIfNotNull(String &variable, String &data) { - if (data == "") return; - variable = data; -} - -void SednAtCommandWithLog(String msg) { - logDebug(msg); - gsmSerial.print(msg + "\r"); - delay(400); - logDebug(gsmSerial.readString()); -} - -void SendSMS(String pin) { - // Set the SIM900A to text mode - SednAtCommandWithLog("AT+CMGF=1"); - delay(400); - - SednAtCommandWithLog("AT + CMGS =\"" + gsmPostParams.mobileNumber + "\""); - delay(400); - - // Specify the SMS message - SednAtCommandWithLog(pin + " " + gsmPostParams.sms); - delay(1000); - - // Send a Ctrl+Z / ASCII SUB - gsmSerial.print((char)26); - delay(1000); - // Close the connection - gsmSerial.print((char)27); - delay(1000); - logDebug("Close communication GSM"); - // String msg = gsmSerial.readStringUntil("/n"); - // gsmlogDebug("Msg:"+msg); -} - -void writeStringToEEPROM(int addr, const String &data, int limit) { - uint8_t endIndex =0; - int numBytes = data.length(); // get length of the string - for (uint8_t i = 0; i < numBytes && i < limit; i++) { - EEPROM.write(addr + i, data[i]); // write one byte at a time - endIndex = i; - } - if (endIndex < limit) { - EEPROM.write(addr + endIndex + 1, '\n'); - } -} - -void SetPin(uint8_t pin, const char *description) { - SendSMS("PIN:" + String(pin) + "|" + description); -} - - -void checkInputPins() { - unsigned long currentTime = millis(); - - for (int i = 0; i < numInputPins; i++) { - pinState *currentState = &inputStates[i]; // Pointer to current pin state - - bool currentInputState = digitalRead(currentState->pinNumber); - if (currentInputState != currentState->lastState && currentTime - currentState->lastStateChangeTime >= currentState->debounceTime) { - // Input state change confirmed after debounce time - currentState->lastState = currentInputState; - - if (currentInputState) { - - // Call SetPin function (modify for specific pin control) - SetPin(currentState->pinNumber, currentState->description); // Example usage with pin number passed - } - currentState->lastStateChangeTime = currentTime; - } - } -} - -int iterationCounter = 0; // Counter for loop iterations - - - -void loop() { - // Listen for incoming clients - String msg = ""; - client = server.available(); - - if (client) { - String request = client.readStringUntil('\r'); - - logDebug("request:" + request); - - if (request.indexOf("GET /?id=GSM") != -1) { - logDebug("it is GSM"); - //int start = request.indexOf("/?id=") + 2; - String data = request.substring(6); - logDebug("data:" + data); - - String id = getValue(data, "id="); - logDebug("id data:" + id); - - String value = getValue(data, "mobileNumber="); - changeDataIfNotNull(gsmPostParams.mobileNumber, value); - - value = getValue(data, "sms="); - changeDataIfNotNull(gsmPostParams.sms, value); - msg += "PARSING GMS DATA SUCESSFULLY"; - } - - logDebug("struc GSM:" + gsmPostParams.mobileNumber + " sms:" + gsmPostParams.sms); - - if (request.indexOf("GET /SEND-SMS") != -1) { - msg += "SEND SMS TROUGHT GSM. "; - } - - if (request.indexOf("GET /SAVE-EEPROM") != -1) { - writeStringToEEPROM(1, gsmPostParams.mobileNumber, 20); - writeStringToEEPROM(21, gsmPostParams.sms, 200); - msg += "Update to EEPROM is sucessfully. "; - } - - logDebug("Request:" + request); - client.println("HTTP/1.1 200 OK"); - client.println("Content-Type: text/html"); - client.println("Connection: close"); - client.println(); - client.println(""); - client.println("
"); - - client.println("

Trochta.net:

"); - - writeToLogAndIntoWebAsP(msg, "H3"); - //nastav jestli je post - checkValue(request, PIN_OUT_2, "PIN2"); - checkValue(request, PIN_OUT_3, "PIN3"); - - // Vypis aktualni hodnoty - writeToLogAndIntoWebAsP("Input:", ElmP); - - for (int i = 0; i < numInputPins; i++) { - pinState *currentState = &inputStates[i]; - writeToLogAndIntoWebAsP(ConvertStatusToString(currentState->pinNumber, false), ElmP); - } - - writeToLogAndIntoWebAsP("Output:", ElmP); - writeToLogAndIntoWebAsP(ConvertStatusToString(PIN_OUT_2, true), ElmP); - writeToLogAndIntoWebAsP(ConvertStatusToString(PIN_OUT_3, true), ElmP); - - writeToLogAndIntoWebAsP("GSM Number:" + gsmPostParams.mobileNumber, ElmP); - writeToLogAndIntoWebAsP("SMS:" + gsmPostParams.sms, ElmP); - - writeToLogAndIntoWebAsP("Send SMS", "H4"); - writeToLogAndIntoWebAsP("Save to EEPROM", ElmP); - writeToLogAndIntoWebAsP("Refresh", ElmP); - // Send the time and the message that the page is loaded - client.println("
"); - // Give the web browser time to receive the data - client.stop(); - - logDebug("Time: " + String(millis() / 1000)); - - if (request.indexOf("GET /SEND-SMS") != -1) { - SendSMS("Web Link (Test)"); - } - // Zjkontroluje vstupni piny - - delay(5); - } - - iterationCounter++; - if (iterationCounter == INT_FAST16_MAX) iterationCounter = 0; - if (iterationCounter % 5 == 0) { // Check if 10 iterations have passed - checkInputPins(); // Call checkInputPins() every 10 iterations - } - - delay(100); -} diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..56fbf77 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,61 @@ +#include "GSMMobileDevice.h" +//#include "WebServer.h" +#include "PinTypeIn.h" +#include "PinTypeOut.h" +#include +//#include +// #include +// #include "WebServer.h" +// #include "WebServerData.h" + +//#include "HTMLGenerator.h" +#include "avr8-stub.h" + +//#define DEBUG + +// PIN INPUT Initialization as OUTPUT +static const int COUNT_OUTPUTS_PIN_OUT = 2; +static PinTypeOut PinOutAlarm8 = PinTypeOut("PIN8", 8, "Electric Alarm"); +static PinTypeOut PinOutCase7 = PinTypeOut("PIN7", 7, "Default Description"); +static const PinTypeOut OUPUTS_PINS_ARRAY[COUNT_OUTPUTS_PIN_OUT] = {PinOutAlarm8, PinOutCase7}; + +// PIN INPUT Initialization as INPUT +static const int COUNT_INPUTS_PIN_IN = 2; +static PinTypeIn PinInEZSAlarm2 = PinTypeIn("PIN4", 4, 100, "Input EZS ALARM"); // 100ms debounce; +static PinTypeIn PinInCaseOpen3 = PinTypeIn("PIN3", 3, 100, "Input Contact Box"); +static const PinTypeIn INPUTS_PINS_ARRAY[COUNT_INPUTS_PIN_IN] = {PinInEZSAlarm2, PinInCaseOpen3}; + +// // GSM Serial Port +//https://arduino.stackexchange.com/questions/44599/sim900a-mini-modem-imei-0-help-with-tx-rx-pins +static const uint8_t GSM_PIN_RX = 5; +static const uint8_t GSM_PIN_TX = 6; +static const long GSM_BAUD_RATE = 115200; +GSMMobileDevice gsmDevice = GSMMobileDevice(GSM_PIN_RX, GSM_PIN_TX, GSM_BAUD_RATE); +// // Pin Input +GSMMobileData gsmData = GSMMobileData("GSM"); + +void setup() +{ + debug_init(); + + gsmData.MobileNumber = "+420608126674"; + gsmData.Sms = "Alarm EZS CHATA"; +} + +void loop() +{ + ; + if (PinInEZSAlarm2.IsPinHigh()) + { + PinOutAlarm8.setOutputSignalToHigh(); + gsmDevice.sendSMS(gsmData); + } + else + { + PinOutAlarm8.setOutputSignalToLow(); + } + + delay(1000); + +} +