Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/send value via http curl #73

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
143 changes: 143 additions & 0 deletions RPi_utils/HttpClient.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
#include "HttpClient.h"

#include <time.h>
#include <unistd.h>
#include <curl/curl.h>
#include <iostream>

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<unsigned char> bytes)
{
m_body = bytes;
}

void HttpRequest::AddBody(const string body)
{
m_body = vector<unsigned char>(&body.c_str()[0], &body.c_str()[body.size()]);
}

vector<unsigned char> HttpRequest::GetBodyData()
{
return m_body;
}


map<string,string> 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;
}
57 changes: 57 additions & 0 deletions RPi_utils/HttpClient.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@

#include <string>
#include <vector>
#include <map>

#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<unsigned char> bytes);

void AddBody(const std::string body);

std::vector<unsigned char> GetBodyData();

std::map<std::string,std::string> GetHeaders();

CURL * GetCURL(const std::string& host, int port);

~HttpRequest();

private:
struct curl_slist * GetCurlHeaders();

std::map<std::string, std::string> m_headers;
std::string m_method;
std::string m_endpoint;
std::vector<unsigned char> 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;

};
91 changes: 91 additions & 0 deletions RPi_utils/HttpClientMain.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
#include <stdio.h>
#include <stdlib.h>
#include "HttpClient.h"

#include <stdint.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

#include <unistd.h>

#include <mqueue.h>

#include <string.h>

#include <signal.h>

#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;
}
8 changes: 5 additions & 3 deletions RPi_utils/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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

4 changes: 4 additions & 0 deletions RPi_utils/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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```
Loading