Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdlib.h>
- #include <iostream>
- #include <string>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <vector>
- #include <errno.h>
- #include <string.h>
- #include <unistd.h> //Used for UART
- #include <fcntl.h> //Used for UART
- #include <termios.h> //Used for UART
- #include <unistd.h>
- #include <sys/wait.h>
- #include <stdio.h>
- #include <functional>
- #include <signal.h>
- #include <poll.h>
- #include <algorithm>
- class Logger
- {
- public:
- static void Log(const std::string & message)
- {
- std::cout << message << std::endl;
- }
- };
- class ProgrammExecutor
- {
- public:
- void Execute(const char **argv, std::function<bool(void)> continuePredicate)
- {
- pid_t myPid = fork();
- if (myPid == 0)
- {
- pid_t pid = execve(argv[0], (char**) argv, NULL);
- if (pid == -1)
- {
- Logger::Log((std::string)"Error executing program: " + argv[0] + " error: " + std::to_string(errno));
- return;
- }
- else
- {
- Logger::Log((std::string)"Executing command " + argv[0]);
- }
- }
- else
- {
- int status = 0;
- std::cout << "Waiting" << std::endl;
- while (waitpid(myPid, &status, WNOHANG) == 0)
- {
- sleep(1);
- if (!continuePredicate())
- {
- kill(myPid, SIGKILL);
- while (waitpid(myPid, &status, WNOHANG) == 0);
- std::cout << "Killed" << std::endl;
- break;
- }
- }
- std::cout << "The end" << std::endl;
- }
- }
- };
- class AudioPlayer
- {
- public:
- AudioPlayer(const std::string &inFileName, std::function<bool(void)> continuePredicate)
- {
- const std::string path = ((std::string)"/home/pi/Sounds/" + inFileName);
- const char *arguments[64] = {"/usr/bin/aplay", path.c_str(), NULL };
- ProgrammExecutor executor;
- executor.Execute(arguments, continuePredicate);
- }
- };
- class Serial
- {
- private:
- static const size_t bufferSize = 4096;
- int uart = -1;
- public:
- Serial(const std::string & device)
- {
- uart = open(device.c_str(), O_RDWR | O_NOCTTY | O_NDELAY);
- if (uart != -1)
- {
- Logger::Log("UART has been open.");
- termios options = {0};
- tcgetattr(uart, &options);
- options.c_cflag = B9600 | CS8 | CLOCAL | CREAD;
- options.c_iflag = IGNPAR;
- options.c_oflag = 0;
- options.c_lflag = 0;
- options.c_cc[VMIN] = 0;
- tcflush(uart, TCIFLUSH);
- tcsetattr(uart, TCSANOW, &options);
- Logger::Log("UART has been configured.");
- }
- else
- Logger::Log("Not abble to open UART. Exiting.");
- }
- ~Serial()
- {
- if (uart == -1)
- return;
- close (uart);
- Logger::Log("Deinitializing Serial");
- }
- void Send(const std::string & data) const
- {
- if (uart < 0)
- {
- Logger::Log("Can't send info. UART was not open properly");
- return;
- }
- if (write(uart, data.c_str(), data.size()) < 0)
- Logger::Log("Error sending data");
- else
- Logger::Log("Sent \"" + data + "\"");
- }
- const std::string Read(bool blocking = true) const
- {
- while (tcdrain(uart) != 0);
- int result = 0;
- char rx_buffer[bufferSize];
- while ((result = read(uart, (void*) rx_buffer, bufferSize)) == 0 && blocking);
- if (blocking && result < 0)
- {
- Logger::Log("Error reading data");
- return "Error reading data";
- }
- else
- {
- rx_buffer[result] = '\0';
- return std::string(rx_buffer);
- }
- }
- };
- class GSMModule
- {
- private:
- const Serial * serial;
- mutable std::string buffer;
- public:
- GSMModule(const Serial * inSerialToUse) : serial(inSerialToUse)
- {
- SendCommand("ATE1");
- }
- enum CallStatus
- {
- None = -1,
- Talking = 0,
- Held = 1,
- Dialing = 2,
- Alerting = 3
- };
- CallStatus GetCallStatus() const
- {
- SendCommand("AT+CLCC");
- std::string result;
- while ((result = Receive()).size() == 0);
- Logger::Log(result);
- const std::string expectedResult = "+CLCC:";
- if (Contains(result, expectedResult))
- return (CallStatus) GetParameters(result)[2];
- else
- return CallStatus::None;
- }
- void Response() const
- {
- SendCommand("ATA");
- }
- void EndCall() const
- {
- SendCommand("ATH");
- }
- void SendAT() const
- {
- SendCommand("AT");
- }
- void SendBusy()
- {
- SendCommand("AT+GSMBUSY");
- }
- void TurnOn() const
- {
- SendCommand("AT+CPOWD=1");
- }
- void TurnOff()
- {
- SendCommand("AT+CPOWD=0");
- }
- void Call(const std::string &number) const
- {
- SendCommand("ATD" + number + ";");
- }
- void SendCommand(const std::string &inCommand) const
- {
- const std::string commandToSend = inCommand + "\r\n";
- serial->Send(commandToSend);
- }
- const std::string Receive() const
- {
- const std::string result = serial->Read(false);
- if (result.size() != 0)
- buffer += result;
- if (buffer.size() > 2 && *buffer.rbegin() == '\n' && *(buffer.rbegin() + 1) == '\r')
- {
- std::string fullMessage = buffer;
- fullMessage = fullMessage.substr(0, fullMessage.size() - 2);
- buffer = "";
- return fullMessage;
- }
- return "";
- }
- private:
- const std::vector<int> GetParameters(const std::string &inString) const
- {
- std::vector<int> parameters;
- auto start = std::find(inString.begin(), inString.end(), ',');
- if (start == inString.end())
- return parameters;
- start--;
- for (auto it = start; it != start + 10 && it < inString.end(); it += 2)
- {
- parameters.push_back((*it) - '0');
- }
- return parameters;
- }
- inline bool Contains(const std::string &inString, const std::string &inSub) const
- {
- if (inSub.size() > inString.size())
- return false;
- auto current = inSub.begin();
- for (auto it = inString.begin(); it != inString.end(); it++)
- {
- if (*it == *current)
- {
- current++;
- if (current == inSub.end())
- return true;
- }
- else
- current = inSub.begin();
- }
- return false;
- }
- };
- class NetworkController
- {
- private:
- static const size_t bufferSize = 4096;
- int currentConnection = -1;
- int socketId = -1;
- public:
- NetworkController(int port)
- {
- socketId = socket(AF_INET, SOCK_STREAM | O_NONBLOCK, 0);
- if (socketId < 0)
- {
- Logger::Log((std::string)"Error opening socket: " + strerror(errno));
- return;
- }
- sockaddr_in addr = {0};
- addr.sin_family = AF_INET;
- addr.sin_port = htons(port);
- addr.sin_addr.s_addr = htonl(INADDR_ANY);
- int bindResult = 0;
- if ((bindResult = bind(socketId, (sockaddr*) & addr, sizeof(addr))) < 0)
- {
- Logger::Log((std::string)"Error binding socket: " + strerror(bindResult));
- return;
- }
- listen(socketId, 1);
- }
- bool HasConnection() const
- {
- return currentConnection != -1;
- }
- bool SendIdle()
- {
- return SendToConnection("idle");
- }
- bool SendToConnection(const std::string &inAnswer) const
- {
- if (currentConnection == -1)
- {
- Logger::Log("No connection");
- return false;
- }
- size_t size = inAnswer.size() + 1;
- char * buffer = new char[size];
- memcpy(buffer, inAnswer.c_str(), inAnswer.size());
- buffer[size - 1] = '\0';
- int result = sendall(currentConnection, buffer, size, MSG_NOSIGNAL) >= 0;
- delete[] buffer;
- if (result < 0)
- {
- Logger::Log((std::string)"Error sending repsonse: " + std::to_string(errno));
- return false;
- }
- else
- return true;
- }
- const std::string Receive() const
- {
- if (currentConnection == -1)
- return std::string();
- char buffer[bufferSize];
- std::string results;
- pollfd fd = {0};
- fd.fd = currentConnection;
- fd.events = POLLIN;
- poll(&fd, 1, 0);
- if (fd.revents & POLLIN)
- {
- int received = recv(currentConnection, buffer, bufferSize, O_NONBLOCK);
- if (received < 0)
- {
- Logger::Log((std::string)"Error receiving data: " + strerror(received));
- }
- else if (received != 0)
- {
- buffer[received] = '\0';
- return std::string(buffer);
- }
- }
- return std::string();
- }
- void Update()
- {
- int accepted = accept(socketId, NULL, NULL);
- if (accepted > 0)
- {
- if (currentConnection != -1)
- close(currentConnection);
- currentConnection = accepted;
- }
- }
- ~NetworkController()
- {
- if (currentConnection != -1)
- close(currentConnection);
- currentConnection = -1;
- if (socketId < 0)
- return;
- close(socketId);
- }
- private:
- int sendall(const int s, const char *buf, const int len, const int flags) const
- {
- int total = 0;
- int n;
- while(total < len)
- {
- n = send(s, buf+total, len-total, flags);
- if(n == -1) { break; }
- total += n;
- }
- return (n==-1 ? -1 : total);
- }
- };
- class CommandExecutor
- {
- private:
- const GSMModule * module = nullptr;
- const NetworkController *networkController = nullptr;
- class EndCommandMessageSender
- {
- private:
- const NetworkController * networkController = nullptr;
- public:
- EndCommandMessageSender(const NetworkController * inNetworkController) : networkController(inNetworkController)
- {
- }
- ~EndCommandMessageSender()
- {
- if (networkController->HasConnection())
- networkController->SendToConnection("command finished");
- }
- };
- public:
- CommandExecutor(const GSMModule * inModule, const NetworkController * inNetworkController) : module(inModule), networkController(inNetworkController)
- {
- }
- bool ExecuteCommand(const std::string &command, const std::vector<std::string> ¶meters) const
- {
- EndCommandMessageSender endCommandHandler(networkController);
- Logger::Log("Start command execution '" + command + "'");
- if (command == "call")
- {
- Logger::Log("Before calling 'call' command");
- if (parameters.size() != 1)
- {
- Logger::Log("Incorrect count of parameters for call command");
- return false;
- }
- pid_t pid = fork();
- if (pid_t != 0)
- return true;
- SendCalling();
- module->Call(parameters[0]);
- while (module->GetCallStatus() == GSMModule::CallStatus::None)
- {
- SendCalling();
- Logger::Log("Waiting for call");
- sleep(1);
- }
- while (module->GetCallStatus() != GSMModule::CallStatus::Talking)
- {
- SendCalling();
- sleep(1);
- if (module->GetCallStatus() == GSMModule::CallStatus::None)
- {
- Logger::Log("The call has been interrupted");
- return true;
- }
- }
- SendCalling();
- Logger::Log("Call answered");
- do
- {
- sleep(1);
- SendCalling();
- }
- while (module->GetCallStatus() == GSMModule::CallStatus::Talking);
- //AudioPlayer(parameters[1], [&]() { return module->GetCallStatus() == GSMModule::CallStatus::Talking; });
- //module->EndCall();
- exit(0);
- return true;
- }
- else if (command == "at")
- {
- module->SendAT();
- return true;
- }
- else if (command == "raw_command")
- {
- if (parameters.size() != 1)
- {
- Logger::Log("This command should have only one parameter");
- return false;
- }
- module->SendCommand(parameters[0]);
- return true;
- }
- Logger::Log("Unknown command (" + command + ")");
- return false;
- }
- private:
- bool SendCalling() const
- {
- Logger::Log("Sending call");
- if (!networkController->HasConnection())
- return false;
- bool result = networkController->SendToConnection("calling");
- if (!result)
- Logger::Log("Error sending data");
- return result;
- }
- };
- class CommandParser
- {
- public:
- class CommandInfo
- {
- private:
- const std::string commandName;
- const std::vector<std::string> parameters;
- public:
- CommandInfo(const std::string &inCommandName, const std::vector<std::string> inParameters) : commandName(inCommandName), parameters(inParameters)
- {
- }
- const std::string GetName() const
- {
- return commandName;
- }
- const std::vector<std::string> GetParameters() const
- {
- return parameters;
- }
- };
- const std::vector<std::string> Parse(const std::string & inString) const
- {
- std::vector<std::string> result;
- result.push_back("");
- bool previousWasSpace = true;
- for (auto it = inString.begin(); it != inString.end(); it++)
- {
- bool isSpace= isspace(*it);
- if (isSpace && !previousWasSpace)
- {
- result.push_back("");
- continue;
- }
- previousWasSpace = isSpace;
- if (isSpace)
- continue;
- result[result.size() -1] += (*it);
- }
- return result;
- }
- const CommandInfo ParseToCommandInfo(const std::string &inString) const
- {
- std::vector<std::string> data = Parse(inString);
- if (data.size() <= 0)
- {
- Logger::Log("Can't parse command. It's empty");
- return CommandInfo("", std::vector<std::string>());
- }
- std::string commandName = data[0];
- data.erase(data.begin());
- return CommandInfo(commandName, data);
- }
- };
- int main(int argc, char **argv)
- {
- Logger::Log("Starting application.");
- NetworkController networkController(5551);
- Serial serial("/dev/ttyS0");
- GSMModule module(&serial);
- CommandExecutor executor(&module, &networkController);
- CommandParser parser;
- while (true)
- {
- networkController.Update();
- auto received = networkController.Receive();
- if (received.size() != 0)
- {
- CommandParser::CommandInfo info = parser.ParseToCommandInfo(received);
- executor.ExecuteCommand(info.GetName(), info.GetParameters());
- }
- }
- Logger::Log("Exiting.");
- while (true);
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement