diff --git a/RPi_utils/HttpClient.cpp b/RPi_utils/HttpClient.cpp new file mode 100644 index 0000000..6ae1cc2 --- /dev/null +++ b/RPi_utils/HttpClient.cpp @@ -0,0 +1,143 @@ +#include "HttpClient.h" + +#include +#include +#include +#include + +using namespace std; + +inline bool ends_with(std::string const & value, std::string const & ending) +{ + if (ending.size() > value.size()) return false; + return std::equal(ending.rbegin(), ending.rend(), value.rbegin()); +} + + +HttpRequest::HttpRequest(const string& method, const string& endpoint) + :m_method(method), + m_endpoint(endpoint), + m_curl(nullptr), + m_curl_headers(nullptr) +{} + +void HttpRequest::AddHeader(const string& name, const string& value) +{ + m_headers[name] = value; +} + +void HttpRequest::AddBody(vector bytes) +{ + m_body = bytes; +} + +void HttpRequest::AddBody(const string body) +{ + m_body = vector(&body.c_str()[0], &body.c_str()[body.size()]); +} + +vector HttpRequest::GetBodyData() +{ + return m_body; +} + + +map HttpRequest::GetHeaders() +{ + return this->m_headers; +} + +CURL* HttpRequest::GetCURL(const string& host, int port) +{ + if(m_curl == nullptr) { + curl_global_init(CURL_GLOBAL_ALL); + + m_curl = curl_easy_init(); + if(! m_curl) return NULL; + + curl_easy_setopt(m_curl, CURLOPT_CUSTOMREQUEST, this->m_method.c_str()); + + auto headers = this->GetCurlHeaders(); + if(headers != NULL) { + curl_easy_setopt(m_curl, CURLOPT_HTTPHEADER, headers); + } + + if(m_body.size() > 0) { + curl_easy_setopt(m_curl, CURLOPT_POSTFIELDS, &m_body.at(0)); + curl_easy_setopt(m_curl, CURLOPT_POSTFIELDSIZE, m_body.size()); + } + } + string url = host + ":" + to_string(port); + if( ends_with(url, "/")) { + url += "/"; + } + url += this->m_endpoint; + + curl_easy_setopt(m_curl, CURLOPT_URL, url.c_str()); + + return m_curl; +} + +struct curl_slist * HttpRequest::GetCurlHeaders() +{ + struct curl_slist *headers=NULL; + + for(auto it = m_headers.begin(); it != m_headers.end(); it++) + { + string header = it->first + ": " + it->second; + headers = curl_slist_append(headers, header.c_str()); + } + return headers; +} + + +HttpRequest::~HttpRequest() +{ + if(m_curl != nullptr) { + curl_easy_cleanup(m_curl); + } + if(m_curl_headers != nullptr) { + curl_slist_free_all(m_curl_headers); + } +} + + + +static size_t CurlWrite_CallbackFunc_StdString(void *contents, size_t size, size_t nmemb, std::string *s) +{ + size_t newLength = size*nmemb; + try + { + s->append((char*)contents, newLength); + } + catch(std::bad_alloc &e) + { + return 0; + } + return newLength; +} + +HttpClient::HttpClient(std::string host, unsigned short port) : +m_host(host), +m_port(port) +{ +} + + + +HttpStatusCode HttpClient::DoRequest(HttpRequest& request) +{ + auto curl = request.GetCURL(this->m_host, this->m_port); + + if(curl) + { + + string response = ""; + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWrite_CallbackFunc_StdString); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response); + + CURLcode res = curl_easy_perform(curl); + } + sleep(2); + return HttpStatusCode::HTTP_STATUS_OK; +} diff --git a/RPi_utils/HttpClient.h b/RPi_utils/HttpClient.h new file mode 100644 index 0000000..ddf6e43 --- /dev/null +++ b/RPi_utils/HttpClient.h @@ -0,0 +1,57 @@ + +#include +#include +#include + +#include "curl/curl.h" + +typedef enum { + HTTP_STATUS_OK = 200, + HTTP_STATUS_UNAUTHORIZED = 401, + HTTP_STATUS_FORBIDDEN = 403, + HTTP_STATUS_NOT_FOUNT = 404, + HTTP_STATUS_INTERNAL_SERVER_ERROR = 500 +} HttpStatusCode; + +class HttpRequest { +public: + HttpRequest(const std::string& method, const std::string& endpoint); + + void AddHeader(const std::string& name, const std::string& value); + + void AddBody(std::vector bytes); + + void AddBody(const std::string body); + + std::vector GetBodyData(); + + std::map GetHeaders(); + + CURL * GetCURL(const std::string& host, int port); + + ~HttpRequest(); + +private: + struct curl_slist * GetCurlHeaders(); + + std::map m_headers; + std::string m_method; + std::string m_endpoint; + std::vector m_body; + + struct curl_slist * m_curl_headers; + + CURL* m_curl; +}; + +class HttpClient { +public: + HttpClient(std::string host, unsigned short port); + + HttpStatusCode DoRequest(HttpRequest& request); +private: + + std::string m_host; + unsigned short m_port; + +}; \ No newline at end of file diff --git a/RPi_utils/HttpClientMain.cpp b/RPi_utils/HttpClientMain.cpp new file mode 100644 index 0000000..b488c6a --- /dev/null +++ b/RPi_utils/HttpClientMain.cpp @@ -0,0 +1,91 @@ +#include +#include +#include "HttpClient.h" + +#include +#include +#include +#include + +#include + +#include + +#include + +#include + +#define QUEUE_PERMISSIONS 0660 + +using namespace std; + +static int32_t qid; + +mqd_t mqd; + +static void intHandler(int dummy) { + mq_close(mqd); + mq_unlink("/RFSniffer_MQ"); + exit(0); +} + + +static int32_t send_value_http(int32_t value) +{ + HttpClient client("http://192.168.15.9", 5000); + HttpRequest req("POST", "/value"); + char body[32]; + + signal(SIGINT, intHandler); + + sprintf(body, "%d", value); + + req.AddHeader("Content-Type", "text/*"); + + req.AddBody(string(body)); + + + HttpStatusCode ret = client.DoRequest(req); + return (int) ret; +} + +int main(int argc, char * argv[]) +{ + + struct mq_attr attr; + attr.mq_flags = 0; + attr.mq_maxmsg = 10; + attr.mq_msgsize = sizeof(int); + attr.mq_curmsgs = 0; + + mqd = mq_open("/RFSniffer_MQ", O_CREAT | O_RDONLY , 0660, &attr); + if(mqd == -1) { + perror("mq_open"); + return -1; + } + + while(1) + { + char *buffer = (char*) calloc (sizeof(int), 10); + unsigned int priority = 0; + + if ((mq_receive (mqd, buffer, sizeof(int) *50, NULL)) == -1) + { + perror ("Failed to receive message\n"); + + continue; + } + + int value = *((int*)buffer); + //rfs_message.message.value = 12; + printf("Received value [%d]\n", value); + + send_value_http(value); + + free(buffer); + } + + mq_close(mqd); + + return 0; +} diff --git a/RPi_utils/Makefile b/RPi_utils/Makefile index 93c9acd..08e3c65 100644 --- a/RPi_utils/Makefile +++ b/RPi_utils/Makefile @@ -2,7 +2,7 @@ # Defines the RPI variable which is needed by rc-switch/RCSwitch.h CXXFLAGS=-DRPI -all: send codesend RFSniffer +all: send codesend RFSniffer HttpClient send: ../rc-switch/RCSwitch.o send.o $(CXX) $(CXXFLAGS) $(LDFLAGS) $+ -o $@ -lwiringPi -lwiringPiDev -lcrypt @@ -11,9 +11,11 @@ codesend: ../rc-switch/RCSwitch.o codesend.o $(CXX) $(CXXFLAGS) $(LDFLAGS) $+ -o $@ -lwiringPi -lwiringPiDev -lcrypt RFSniffer: ../rc-switch/RCSwitch.o RFSniffer.o - $(CXX) $(CXXFLAGS) $(LDFLAGS) $+ -o $@ -lwiringPi -lwiringPiDev -lcrypt + $(CXX) $(CXXFLAGS) $(LDFLAGS) $+ -o $@ -lwiringPi -lwiringPiDev -lcrypt -lrt +HttpClient: HttpClientMain.o HttpClient.o + $(CXX) $(CXXFLAGS) $(LDFLAGS) $+ -o $@ -lwiringPi -lwiringPiDev -lcrypt -lcurl -lrt clean: - $(RM) ../rc-switch/*.o *.o send codesend servo RFSniffer + $(RM) ../rc-switch/*.o *.o send codesend servo RFSniffer HttpClient diff --git a/RPi_utils/README.md b/RPi_utils/README.md index 7a0fedf..4151668 100644 --- a/RPi_utils/README.md +++ b/RPi_utils/README.md @@ -15,3 +15,7 @@ It uses wiringPi pin no 2 by default. You may want to change the used GPIO pin b ## Note The 'RF\_Sniffer' code is as yet untested. It _should_ work, but it is still being tested thoroughly. It's provided to allow you to start playing with it now. + +## cURL +The HTTP client meant to update the read values to a server use libcurl. It needs to be installed on the Raspberry: +```sudo apt install libcurl4 --yes``` diff --git a/RPi_utils/RFSniffer.cpp b/RPi_utils/RFSniffer.cpp index 286ab3d..c8ec75f 100644 --- a/RPi_utils/RFSniffer.cpp +++ b/RPi_utils/RFSniffer.cpp @@ -12,11 +12,47 @@ #include #include #include - + +#include RCSwitch mySwitch; - +static mqd_t mqd = -1; +static struct mq_attr attr; + +static int send_value_to_mq(int value) +{ + if(mqd == -1) + { + attr.mq_flags = 0; + attr.mq_maxmsg = 10; + attr.mq_msgsize = sizeof(int); + attr.mq_curmsgs = 0; + + mqd = mq_open("/RFSniffer_MQ", O_WRONLY , 0777, &attr); + } + + if(mqd == -1) { + perror("mq_open"); + return -1; + } + + attr.mq_flags |= O_NONBLOCK; + mq_setattr(mqd, &attr, NULL); + if(mq_send(mqd,(char*) &value, sizeof(int), 0) == -1) + { + perror("mq_send: "); + mq_close(mqd); + mqd = -1; + return -1; + } + printf("Sent value %d\n", value); + + attr.mq_flags &= (~O_NONBLOCK); + mq_setattr(mqd, &attr, NULL); + + return 0; +} int main(int argc, char *argv[]) { @@ -36,26 +72,25 @@ int main(int argc, char *argv[]) { mySwitch = RCSwitch(); if (pulseLength != 0) mySwitch.setPulseLength(pulseLength); mySwitch.enableReceive(PIN); // Receiver on interrupt 0 => that is pin #2 - - + + while(1) { if (mySwitch.available()) { - + int value = mySwitch.getReceivedValue(); - + if (value == 0) { printf("Unknown encoding\n"); - } else { - - printf("Received %i\n", mySwitch.getReceivedValue() ); + } else { + printf("Received %i\n", value ); + send_value_to_mq(value); } fflush(stdout); mySwitch.resetAvailable(); } - usleep(100); - + usleep(100); } exit(0);