From 5231974255477b9744102f114855d7725ed0590e Mon Sep 17 00:00:00 2001 From: Henrique Lustosa Date: Tue, 9 Feb 2021 20:02:47 -0300 Subject: [PATCH 1/5] Creating http client app + adding MQ to communicate between processes --- RPi_utils/HttpClient.cpp | 145 +++++++++++++++++++++++++++++++++++ RPi_utils/HttpClient.h | 57 ++++++++++++++ RPi_utils/HttpClientMain.cpp | 91 ++++++++++++++++++++++ RPi_utils/Makefile | 8 +- RPi_utils/RFSniffer.cpp | 44 +++++++++-- 5 files changed, 337 insertions(+), 8 deletions(-) create mode 100644 RPi_utils/HttpClient.cpp create mode 100644 RPi_utils/HttpClient.h create mode 100644 RPi_utils/HttpClientMain.cpp diff --git a/RPi_utils/HttpClient.cpp b/RPi_utils/HttpClient.cpp new file mode 100644 index 0000000..cb2d289 --- /dev/null +++ b/RPi_utils/HttpClient.cpp @@ -0,0 +1,145 @@ +#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; + cout << "Curl Header == " << header << endl; + 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) + { + //handle memory problem + 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 reponse = ""; + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWrite_CallbackFunc_StdString); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &reponse); + + 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..8631e2c --- /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", 8080); + HttpRequest req("PUT", "/signal"); + char body[32]; + + signal(SIGINT, intHandler); + + sprintf(body, "Received %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) *10, NULL)) == -1) + { + perror ("Failed to receive message\n"); + + continue; + } + + int value = *((int*)buffer); + //rfs_message.message.value = 12; + printf(" Received message 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/RFSniffer.cpp b/RPi_utils/RFSniffer.cpp index 286ab3d..88732cb 100644 --- a/RPi_utils/RFSniffer.cpp +++ b/RPi_utils/RFSniffer.cpp @@ -12,11 +12,45 @@ #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; + } + attr.mq_flags &= (~O_NONBLOCK); + mq_setattr(mqd, &attr, NULL); + + return 0; +} int main(int argc, char *argv[]) { @@ -48,14 +82,14 @@ int main(int argc, char *argv[]) { printf("Unknown encoding\n"); } else { - printf("Received %i\n", mySwitch.getReceivedValue() ); + attr.mq_flags |= O_NONBLOCK; + send_value_to_mq(value); } fflush(stdout); mySwitch.resetAvailable(); } - usleep(100); - + usleep(100); } exit(0); From a92a41b55eecd81ee27f097201a492facef66dd6 Mon Sep 17 00:00:00 2001 From: Henrique Lustosa Date: Tue, 9 Feb 2021 20:10:58 -0300 Subject: [PATCH 2/5] Updating README.md --- RPi_utils/README.md | 4 ++++ 1 file changed, 4 insertions(+) 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``` From 463252a3d86b1d0b78adff5e778d475c9935a87b Mon Sep 17 00:00:00 2001 From: Henrique Lustosa Date: Mon, 15 Feb 2021 12:20:30 -0300 Subject: [PATCH 3/5] Changint server to Python Flask --- RPi_utils/HttpClient.cpp | 6 ++---- RPi_utils/HttpClientMain.cpp | 7 +++---- RPi_utils/RFSniffer.cpp | 8 ++++---- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/RPi_utils/HttpClient.cpp b/RPi_utils/HttpClient.cpp index cb2d289..6ae1cc2 100644 --- a/RPi_utils/HttpClient.cpp +++ b/RPi_utils/HttpClient.cpp @@ -85,7 +85,6 @@ struct curl_slist * HttpRequest::GetCurlHeaders() for(auto it = m_headers.begin(); it != m_headers.end(); it++) { string header = it->first + ": " + it->second; - cout << "Curl Header == " << header << endl; headers = curl_slist_append(headers, header.c_str()); } return headers; @@ -113,7 +112,6 @@ static size_t CurlWrite_CallbackFunc_StdString(void *contents, size_t size, size } catch(std::bad_alloc &e) { - //handle memory problem return 0; } return newLength; @@ -134,9 +132,9 @@ HttpStatusCode HttpClient::DoRequest(HttpRequest& request) if(curl) { - string reponse = ""; + string response = ""; curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWrite_CallbackFunc_StdString); - curl_easy_setopt(curl, CURLOPT_WRITEDATA, &reponse); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response); CURLcode res = curl_easy_perform(curl); } diff --git a/RPi_utils/HttpClientMain.cpp b/RPi_utils/HttpClientMain.cpp index 8631e2c..c6be329 100644 --- a/RPi_utils/HttpClientMain.cpp +++ b/RPi_utils/HttpClientMain.cpp @@ -32,13 +32,13 @@ static void intHandler(int dummy) { static int32_t send_value_http(int32_t value) { - HttpClient client("http://192.168.15.9", 8080); - HttpRequest req("PUT", "/signal"); + HttpClient client("http://192.168.15.9", 5000); + HttpRequest req("POST", "/value"); char body[32]; signal(SIGINT, intHandler); - sprintf(body, "Received %d", value); + sprintf(body, "%d", value); req.AddHeader("Content-Type", "text/*"); @@ -78,7 +78,6 @@ int main(int argc, char * argv[]) int value = *((int*)buffer); //rfs_message.message.value = 12; - printf(" Received message value [%d]\n", value); send_value_http(value); diff --git a/RPi_utils/RFSniffer.cpp b/RPi_utils/RFSniffer.cpp index 88732cb..f3d5e20 100644 --- a/RPi_utils/RFSniffer.cpp +++ b/RPi_utils/RFSniffer.cpp @@ -36,7 +36,7 @@ static int send_value_to_mq(int value) 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) @@ -46,6 +46,7 @@ static int send_value_to_mq(int value) mqd = -1; return -1; } + attr.mq_flags &= (~O_NONBLOCK); mq_setattr(mqd, &attr, NULL); @@ -71,6 +72,7 @@ int main(int argc, char *argv[]) { if (pulseLength != 0) mySwitch.setPulseLength(pulseLength); mySwitch.enableReceive(PIN); // Receiver on interrupt 0 => that is pin #2 + send_value_to_mq(10); while(1) { @@ -80,9 +82,7 @@ int main(int argc, char *argv[]) { if (value == 0) { printf("Unknown encoding\n"); - } else { - - attr.mq_flags |= O_NONBLOCK; + } else { send_value_to_mq(value); } From e5f079544918b42aa9588de64d1ef1f9532efb0f Mon Sep 17 00:00:00 2001 From: Henrique Lustosa Date: Mon, 15 Feb 2021 12:24:48 -0300 Subject: [PATCH 4/5] Removing unecessary line --- RPi_utils/RFSniffer.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/RPi_utils/RFSniffer.cpp b/RPi_utils/RFSniffer.cpp index f3d5e20..a7a174f 100644 --- a/RPi_utils/RFSniffer.cpp +++ b/RPi_utils/RFSniffer.cpp @@ -71,9 +71,7 @@ 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 - - send_value_to_mq(10); - + while(1) { if (mySwitch.available()) { From 1e8fce5b263b78d79f6b1a128003bf1f51f15e25 Mon Sep 17 00:00:00 2001 From: Henrique Lustosa Date: Wed, 24 Feb 2021 20:52:30 -0300 Subject: [PATCH 5/5] Adjusts to help debug --- RPi_utils/HttpClientMain.cpp | 3 ++- RPi_utils/RFSniffer.cpp | 9 ++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/RPi_utils/HttpClientMain.cpp b/RPi_utils/HttpClientMain.cpp index c6be329..b488c6a 100644 --- a/RPi_utils/HttpClientMain.cpp +++ b/RPi_utils/HttpClientMain.cpp @@ -69,7 +69,7 @@ int main(int argc, char * argv[]) char *buffer = (char*) calloc (sizeof(int), 10); unsigned int priority = 0; - if ((mq_receive (mqd, buffer, sizeof(int) *10, NULL)) == -1) + if ((mq_receive (mqd, buffer, sizeof(int) *50, NULL)) == -1) { perror ("Failed to receive message\n"); @@ -78,6 +78,7 @@ int main(int argc, char * argv[]) int value = *((int*)buffer); //rfs_message.message.value = 12; + printf("Received value [%d]\n", value); send_value_http(value); diff --git a/RPi_utils/RFSniffer.cpp b/RPi_utils/RFSniffer.cpp index a7a174f..c8ec75f 100644 --- a/RPi_utils/RFSniffer.cpp +++ b/RPi_utils/RFSniffer.cpp @@ -46,6 +46,7 @@ static int send_value_to_mq(int value) mqd = -1; return -1; } + printf("Sent value %d\n", value); attr.mq_flags &= (~O_NONBLOCK); mq_setattr(mqd, &attr, NULL); @@ -71,16 +72,18 @@ 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", value ); send_value_to_mq(value); }