Compare commits
25
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
434eb25dda | ||
|
|
dc17bbe535 | ||
|
|
9f0ff10abc | ||
|
|
59771c3901 | ||
|
|
44f9b0cd15 | ||
|
|
bd19b8745e | ||
|
|
deb9b419d4 | ||
|
|
03b00fa6de | ||
|
|
f03e90f5b9 | ||
|
|
654fc94d12 | ||
|
|
86af7f0eb8 | ||
|
|
a8381614e8 | ||
|
|
2d9621f1f1 | ||
|
|
dd7ae1cb73 | ||
|
|
56cc5fa02d | ||
|
|
21dbdd41d9 | ||
|
|
157b1ceb51 | ||
|
|
3b7491f57d | ||
|
|
8440b0d0e9 | ||
|
|
b41bbcb2ff | ||
|
|
7b8fcc9722 | ||
|
|
2fbec833a2 | ||
|
|
b4f9aa4cb2 | ||
|
|
96d4dc0be9 | ||
|
|
f96a45e3a2 |
@@ -9,6 +9,8 @@ gdb*
|
||||
core-*
|
||||
PresenceDetection*
|
||||
!PresenceDetection.cc
|
||||
!PresenceDetection.ini
|
||||
test*
|
||||
!test.cc
|
||||
Test*
|
||||
fixPermissions.sh
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
[submodule "Makefiles"]
|
||||
path = Makefiles
|
||||
url = https://gogs.dierkse.nl/JDierkse/Makefiles.git
|
||||
+127
-102
@@ -1,49 +1,47 @@
|
||||
#include "Bluetooth/Driver.h"
|
||||
#include "Util/StaticDevice.h"
|
||||
#include "WiFi/Driver.h"
|
||||
#include <clipp.h>
|
||||
#include <INIReader.h>
|
||||
#include <Logging.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <signal.h>
|
||||
#include <syslog.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/program_options.hpp>
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
#include <boost/property_tree/ini_parser.hpp>
|
||||
#include "UniFi/Device.h"
|
||||
#include "Bluetooth/Device.h"
|
||||
#include <vector>
|
||||
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
try
|
||||
{
|
||||
setlogmask(LOG_UPTO(LOG_INFO));
|
||||
openlog("PresenceDetection", LOG_CONS | LOG_NDELAY | LOG_PERROR | LOG_PID, LOG_USER);
|
||||
Logging::OpenLog();
|
||||
Logging::SetLogMask(Logging::Severity::Info);
|
||||
|
||||
boost::program_options::options_description description("Options");
|
||||
description.add_options()
|
||||
("help,h", "Provide Help Message")
|
||||
("daemon,d", "Run the process as Daemon");
|
||||
bool daemon = false;
|
||||
clipp::group cli {
|
||||
clipp::option("-d", "--daemon").set(daemon).doc("Run the process as Daemon")
|
||||
};
|
||||
|
||||
boost::program_options::variables_map vm;
|
||||
boost::program_options::store(boost::program_options::parse_command_line(argc, argv, description), vm);
|
||||
boost::program_options::notify(vm);
|
||||
|
||||
if (vm.count("help"))
|
||||
if (!clipp::parse(argc, argv, cli))
|
||||
{
|
||||
std::cerr << description << std::endl;
|
||||
std::cout << clipp::make_man_page(cli, argv[0]) << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool daemon = false;
|
||||
if (vm.count("daemon"))
|
||||
daemon = true;
|
||||
|
||||
boost::property_tree::ptree pt;
|
||||
boost::property_tree::ini_parser::read_ini("PresenceDetection.ini", pt);
|
||||
INIReader iniReader("PresenceDetection.ini");
|
||||
if (iniReader.ParseError() != 0)
|
||||
{
|
||||
std::cerr << "Can't read PresenceDetection.ini" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (daemon)
|
||||
{
|
||||
syslog(LOG_INFO, "Starting Daemon");
|
||||
Logging::Log(Logging::Severity::Info, "Starting PresenceDetection Daemon");
|
||||
pid_t pid, sid;
|
||||
pid = fork();
|
||||
|
||||
@@ -64,76 +62,103 @@ int main(int argc, char** argv)
|
||||
close(STDOUT_FILENO);
|
||||
close(STDERR_FILENO);
|
||||
}
|
||||
|
||||
std::string target;
|
||||
boost::optional<boost::property_tree::ptree&> presenceDetectionTarget = pt.get_child_optional("PresenceDetection.Target");
|
||||
if (presenceDetectionTarget)
|
||||
target = pt.get<std::string>("PresenceDetection.Target");
|
||||
else
|
||||
throw std::runtime_error("Target directive missing in ini file.");
|
||||
|
||||
bool unifi = false;
|
||||
boost::optional<boost::property_tree::ptree&> presenceDetectionUniFi = pt.get_child_optional("PresenceDetection.UniFi");
|
||||
if (presenceDetectionUniFi)
|
||||
unifi = (pt.get<std::string>("PresenceDetection.UniFi") == "On");
|
||||
|
||||
bool bluetooth = false;
|
||||
boost::optional<boost::property_tree::ptree&> presenceDetectionBluetooth = pt.get_child_optional("PresenceDetection.Bluetooth");
|
||||
if (presenceDetectionBluetooth)
|
||||
bluetooth = (pt.get<std::string>("PresenceDetection.Bluetooth") == "On");
|
||||
|
||||
std::shared_ptr<PresenceDetection::UniFi::Device> pUniFiDevice;
|
||||
if (unifi)
|
||||
{
|
||||
std::string hostname;
|
||||
boost::optional<boost::property_tree::ptree&> unifiHostname = pt.get_child_optional("UniFi.Hostname");
|
||||
if (unifiHostname)
|
||||
hostname = pt.get<std::string>("UniFi.Hostname");
|
||||
else
|
||||
throw std::runtime_error("UniFi Hostname directive missing in ini file.");
|
||||
|
||||
std::string username;
|
||||
boost::optional<boost::property_tree::ptree&> unifiUsername = pt.get_child_optional("UniFi.Username");
|
||||
if (unifiUsername)
|
||||
username = pt.get<std::string>("UniFi.Username");
|
||||
else
|
||||
throw std::runtime_error("UniFi Username directive missing in ini file.");
|
||||
|
||||
std::string password;
|
||||
boost::optional<boost::property_tree::ptree&> unifiPassword = pt.get_child_optional("UniFi.Password");
|
||||
if (unifiPassword)
|
||||
password = pt.get<std::string>("UniFi.Password");
|
||||
else
|
||||
throw std::runtime_error("UniFi Password directive missing in ini file.");
|
||||
|
||||
std::string cookiefile;
|
||||
boost::optional<boost::property_tree::ptree&> unifiCookieFile = pt.get_child_optional("UniFi.CookieFile");
|
||||
if (unifiCookieFile)
|
||||
cookiefile = pt.get<std::string>("UniFi.CookieFile");
|
||||
else
|
||||
throw std::runtime_error("UniFi CookieFile directive missing in ini file.");
|
||||
|
||||
std::string inventoryURL;
|
||||
boost::optional<boost::property_tree::ptree&> bluetoothInventoryURL = pt.get_child_optional("UniFi.Inventory");
|
||||
if (bluetoothInventoryURL)
|
||||
inventoryURL = pt.get<std::string>("UniFi.Inventory");
|
||||
else
|
||||
throw std::runtime_error("UniFi Inventory directive missing in ini file.");
|
||||
|
||||
pUniFiDevice = std::make_shared<PresenceDetection::UniFi::Device>(hostname, username, password, cookiefile, inventoryURL, target);
|
||||
Logging::Log(Logging::Severity::Info, "Starting PresenceDetection");
|
||||
}
|
||||
|
||||
std::shared_ptr<PresenceDetection::Bluetooth::Device> pBluetoothDevice;
|
||||
|
||||
std::string target = iniReader.Get("PresenceDetection", "Target", "");
|
||||
|
||||
bool wifi = iniReader.GetBoolean("PresenceDetection", "WiFi", false);
|
||||
|
||||
bool bluetooth = iniReader.GetBoolean("PresenceDetection", "Bluetooth", false);
|
||||
|
||||
std::vector<PresenceDetection::Util::StaticDevice> staticDevices;
|
||||
|
||||
auto sections = iniReader.Sections();
|
||||
for (auto section : sections)
|
||||
{
|
||||
if (section != "PresenceDetection" &&
|
||||
section != "WiFi" &&
|
||||
section != "Bluetooth")
|
||||
{
|
||||
std::string WifiMac = iniReader.Get(section, "WifiMac", "");
|
||||
std::string BluetoothMac = iniReader.Get(section, "BluetoothMac", "");
|
||||
|
||||
if (WifiMac.empty() && BluetoothMac.empty())
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << section << ": No Wifi or Bluetooth Mac address defined" << std::endl;
|
||||
throw std::runtime_error(ss.str());
|
||||
}
|
||||
|
||||
auto staticDevice = PresenceDetection::Util::StaticDevice(WifiMac, BluetoothMac);
|
||||
|
||||
std::string OnlineURL = iniReader.Get(section, "OnlineURL", "");
|
||||
if (!OnlineURL.empty())
|
||||
staticDevice.SetOnlineURL(OnlineURL);
|
||||
|
||||
std::string WifiOnlineURL = iniReader.Get(section, "WifiOnlineURL", "");
|
||||
if (!WifiOnlineURL.empty())
|
||||
staticDevice.SetWifiOnlineURL(WifiOnlineURL);
|
||||
|
||||
std::string BluetoothOnlineURL = iniReader.Get(section, "BluetoothOnlineURL", "");
|
||||
if (!BluetoothOnlineURL.empty())
|
||||
staticDevice.SetBluetoothOnlineURL(BluetoothOnlineURL);
|
||||
|
||||
std::string OfflineURL = iniReader.Get(section, "OfflineURL", "");
|
||||
if (!OfflineURL.empty())
|
||||
staticDevice.SetOfflineURL(OfflineURL);
|
||||
|
||||
std::string WifiOfflineURL = iniReader.Get(section, "WifiOfflineURL", "");
|
||||
if (!WifiOfflineURL.empty())
|
||||
staticDevice.SetWifiOfflineURL(WifiOfflineURL);
|
||||
|
||||
std::string BluetoothOfflineURL = iniReader.Get(section, "BluetoothOfflineURL", "");
|
||||
if (!BluetoothOfflineURL.empty())
|
||||
staticDevice.SetBluetoothOfflineURL(BluetoothOfflineURL);
|
||||
|
||||
staticDevices.push_back(staticDevice);
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<PresenceDetection::WiFi::Driver> pWiFiDriver;
|
||||
if (wifi)
|
||||
{
|
||||
std::string hostname = iniReader.Get("WiFi", "Hostname", "");
|
||||
if (hostname.empty())
|
||||
throw std::runtime_error("WiFi Hostname directive missing in ini file.");
|
||||
|
||||
int port = iniReader.GetInteger("WiFi", "Port", 8443);
|
||||
|
||||
std::string username = iniReader.Get("WiFi", "Username", "");
|
||||
if (username.empty())
|
||||
throw std::runtime_error("WiFi Username directive missing in ini file.");
|
||||
|
||||
std::string password = iniReader.Get("WiFi", "Password", "");
|
||||
if (password.empty())
|
||||
throw std::runtime_error("WiFi Password directive missing in ini file.");
|
||||
|
||||
std::string cookiefile = iniReader.Get("WiFi", "CookieFile", "");
|
||||
if (cookiefile.empty())
|
||||
throw std::runtime_error("WiFi CookieFile directive missing in ini file.");
|
||||
|
||||
int timeout = iniReader.GetInteger("WiFi", "Timeout", 150);
|
||||
|
||||
std::string inventoryURL = iniReader.Get("WiFi", "Inventory", "");
|
||||
|
||||
pWiFiDriver = std::make_shared<PresenceDetection::WiFi::Driver>(hostname, port, username, password, cookiefile, timeout, inventoryURL, target, staticDevices);
|
||||
}
|
||||
|
||||
std::shared_ptr<PresenceDetection::Bluetooth::Driver> pBluetoothDriver;
|
||||
if (bluetooth)
|
||||
{
|
||||
std::string inventoryURL;
|
||||
boost::optional<boost::property_tree::ptree&> bluetoothInventoryURL = pt.get_child_optional("Bluetooth.Inventory");
|
||||
if (bluetoothInventoryURL)
|
||||
inventoryURL = pt.get<std::string>("Bluetooth.Inventory");
|
||||
else
|
||||
throw std::runtime_error("Bluetooth Inventory directive missing in ini file.");
|
||||
int timeout = iniReader.GetInteger("Bluetooth", "Timeout", 150);
|
||||
|
||||
pBluetoothDevice = std::make_shared<PresenceDetection::Bluetooth::Device>(inventoryURL, target);
|
||||
std::string inventoryURL = iniReader.Get("Bluetooth", "Inventory", "");
|
||||
|
||||
pBluetoothDriver = std::make_shared<PresenceDetection::Bluetooth::Driver>(timeout, inventoryURL, target, staticDevices);
|
||||
}
|
||||
|
||||
sigset_t wset;
|
||||
@@ -144,21 +169,21 @@ int main(int argc, char** argv)
|
||||
int sig;
|
||||
sigwait(&wset,&sig);
|
||||
|
||||
syslog(LOG_INFO, "Stopping...");
|
||||
Logging::Log(Logging::Severity::Info, "Stopping PresenceDetection...");
|
||||
|
||||
if (pUniFiDevice)
|
||||
pUniFiDevice->Stop();
|
||||
if (pWiFiDriver)
|
||||
pWiFiDriver->Stop();
|
||||
|
||||
if (pBluetoothDevice)
|
||||
pBluetoothDevice->Stop();
|
||||
if (pBluetoothDriver)
|
||||
pBluetoothDriver->Stop();
|
||||
|
||||
if (pUniFiDevice)
|
||||
pUniFiDevice->Wait();
|
||||
if (pWiFiDriver)
|
||||
pWiFiDriver->Wait();
|
||||
|
||||
if (pBluetoothDevice)
|
||||
pBluetoothDevice->Wait();
|
||||
if (pBluetoothDriver)
|
||||
pBluetoothDriver->Wait();
|
||||
|
||||
closelog();
|
||||
Logging::CloseLog();
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
@@ -166,9 +191,9 @@ int main(int argc, char** argv)
|
||||
ss << "ERROR: " << e.what() << std::endl;
|
||||
|
||||
std::cerr << ss.str() << std::endl;
|
||||
syslog(LOG_ERR, "%s", ss.str().c_str());
|
||||
Logging::Log(Logging::Severity::Error, ss.str());
|
||||
|
||||
closelog();
|
||||
Logging::CloseLog();
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
+114
-253
@@ -1,267 +1,128 @@
|
||||
#include "Bluetooth/Functions.h"
|
||||
#include "Logic/Logic.h"
|
||||
#include "Util/StaticDevice.h"
|
||||
#include "WiFi/Driver.h"
|
||||
#include "WiFi/Functions.h"
|
||||
#include <INIReader.h>
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <signal.h>
|
||||
#include <string>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <getopt.h>
|
||||
#include <signal.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/poll.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <bluetooth/bluetooth.h>
|
||||
#include <bluetooth/hci.h>
|
||||
#include <bluetooth/hci_lib.h>
|
||||
#include <bluetooth/l2cap.h>
|
||||
|
||||
#include "Util/Timer.h"
|
||||
|
||||
/* Defaults */
|
||||
static bdaddr_t bdaddr;
|
||||
static int size = 44;
|
||||
static int ident = 200;
|
||||
static int delay = 1;
|
||||
static int count = -1;
|
||||
static int timeout = 10;
|
||||
static int reverse = 0;
|
||||
static int verify = 0;
|
||||
|
||||
/* Stats */
|
||||
static int sent_pkt = 0;
|
||||
static int recv_pkt = 0;
|
||||
|
||||
static float tv2fl(struct timeval tv)
|
||||
{
|
||||
return (float)(tv.tv_sec*1000.0) + (float)(tv.tv_usec/1000.0);
|
||||
}
|
||||
|
||||
static void stat(int /*sig*/)
|
||||
{
|
||||
int loss = sent_pkt ? (float)((sent_pkt-recv_pkt)/(sent_pkt/100.0)) : 0;
|
||||
printf("%d sent, %d received, %d%% loss\n", sent_pkt, recv_pkt, loss);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static void ping(const char* svr)
|
||||
{
|
||||
struct sigaction sa;
|
||||
struct sockaddr_l2 addr;
|
||||
socklen_t optlen;
|
||||
unsigned char *send_buf;
|
||||
unsigned char *recv_buf;
|
||||
char str[18];
|
||||
int i, sk, lost;
|
||||
uint8_t id;
|
||||
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sa.sa_handler = stat;
|
||||
sigaction(SIGINT, &sa, NULL);
|
||||
|
||||
send_buf = static_cast<unsigned char*>(malloc(L2CAP_CMD_HDR_SIZE + size));
|
||||
recv_buf = static_cast<unsigned char*>(malloc(L2CAP_CMD_HDR_SIZE + size));
|
||||
if (!send_buf || !recv_buf) {
|
||||
perror("Can't allocate buffer");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Create socket */
|
||||
sk = socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_L2CAP);
|
||||
if (sk < 0) {
|
||||
perror("Can't create socket");
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Bind to local address */
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.l2_family = AF_BLUETOOTH;
|
||||
bacpy(&addr.l2_bdaddr, &bdaddr);
|
||||
|
||||
if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
|
||||
perror("Can't bind socket");
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Connect to remote device */
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.l2_family = AF_BLUETOOTH;
|
||||
str2ba(svr, &addr.l2_bdaddr);
|
||||
|
||||
if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
|
||||
perror("Can't connect");
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Get local address */
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
optlen = sizeof(addr);
|
||||
|
||||
if (getsockname(sk, (struct sockaddr *) &addr, &optlen) < 0) {
|
||||
perror("Can't get local address");
|
||||
goto error;
|
||||
}
|
||||
|
||||
ba2str(&addr.l2_bdaddr, str);
|
||||
printf("Ping: %s from %s (data size %d) ...\n", svr, str, size);
|
||||
|
||||
/* Initialize send buffer */
|
||||
for (i = 0; i < size; i++)
|
||||
send_buf[L2CAP_CMD_HDR_SIZE + i] = (i % 40) + 'A';
|
||||
|
||||
id = ident;
|
||||
|
||||
while (count == -1 || count-- > 0) {
|
||||
struct timeval tv_send, tv_recv, tv_diff;
|
||||
l2cap_cmd_hdr *send_cmd = (l2cap_cmd_hdr *) send_buf;
|
||||
l2cap_cmd_hdr *recv_cmd = (l2cap_cmd_hdr *) recv_buf;
|
||||
|
||||
/* Build command header */
|
||||
send_cmd->ident = id;
|
||||
send_cmd->len = htobs(size);
|
||||
|
||||
if (reverse)
|
||||
send_cmd->code = L2CAP_ECHO_RSP;
|
||||
else
|
||||
send_cmd->code = L2CAP_ECHO_REQ;
|
||||
|
||||
gettimeofday(&tv_send, NULL);
|
||||
|
||||
/* Send Echo Command */
|
||||
if (send(sk, send_buf, L2CAP_CMD_HDR_SIZE + size, 0) <= 0) {
|
||||
perror("Send failed");
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Wait for Echo Response */
|
||||
lost = 0;
|
||||
while (1) {
|
||||
struct pollfd pf[1];
|
||||
int err;
|
||||
|
||||
pf[0].fd = sk;
|
||||
pf[0].events = POLLIN;
|
||||
|
||||
if ((err = poll(pf, 1, timeout * 1000)) < 0) {
|
||||
perror("Poll failed");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!err) {
|
||||
lost = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((err = recv(sk, recv_buf, L2CAP_CMD_HDR_SIZE + size, 0)) < 0) {
|
||||
perror("Recv failed");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!err){
|
||||
printf("Disconnected\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
recv_cmd->len = btohs(recv_cmd->len);
|
||||
|
||||
/* Check for our id */
|
||||
if (recv_cmd->ident != id)
|
||||
continue;
|
||||
|
||||
/* Check type */
|
||||
if (!reverse && recv_cmd->code == L2CAP_ECHO_RSP)
|
||||
break;
|
||||
|
||||
if (recv_cmd->code == L2CAP_COMMAND_REJ) {
|
||||
printf("Peer doesn't support Echo packets\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
}
|
||||
sent_pkt++;
|
||||
|
||||
if (!lost) {
|
||||
recv_pkt++;
|
||||
|
||||
gettimeofday(&tv_recv, NULL);
|
||||
timersub(&tv_recv, &tv_send, &tv_diff);
|
||||
|
||||
if (verify) {
|
||||
/* Check payload length */
|
||||
if (recv_cmd->len != size) {
|
||||
fprintf(stderr, "Received %d bytes, expected %d\n",
|
||||
recv_cmd->len, size);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Check payload */
|
||||
if (memcmp(&send_buf[L2CAP_CMD_HDR_SIZE],
|
||||
&recv_buf[L2CAP_CMD_HDR_SIZE], size)) {
|
||||
fprintf(stderr, "Response payload different.\n");
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
printf("%d bytes from %s id %d time %.2fms\n", recv_cmd->len, svr,
|
||||
id - ident, tv2fl(tv_diff));
|
||||
|
||||
if (delay)
|
||||
sleep(delay);
|
||||
} else {
|
||||
printf("no response from %s: id %d\n", svr, id - ident);
|
||||
}
|
||||
|
||||
if (++id > 254)
|
||||
id = ident;
|
||||
}
|
||||
stat(0);
|
||||
free(send_buf);
|
||||
free(recv_buf);
|
||||
return;
|
||||
|
||||
error:
|
||||
close(sk);
|
||||
free(send_buf);
|
||||
free(recv_buf);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void print()
|
||||
{
|
||||
std::cout << "Print" << std::endl;
|
||||
}
|
||||
|
||||
void TestINIReader()
|
||||
{
|
||||
std::cout << "--------------------------------" << std::endl;
|
||||
std::cout << "TestINIReader" << std::endl << std::endl;
|
||||
|
||||
INIReader reader("PresenceDetection.ini");
|
||||
|
||||
std::string target = reader.Get("PresenceDetection", "Target", "");
|
||||
if (!target.empty())
|
||||
std::cout << "Error" << std::endl;
|
||||
std::cout << target.size() << " " << target << std::endl;
|
||||
|
||||
bool wifi = reader.GetBoolean("PresenceDetection", "WiFi", false);
|
||||
if (wifi)
|
||||
std::cout << "WiFi On" << std::endl;
|
||||
else
|
||||
std::cout << "WiFi Off" << std::endl;
|
||||
|
||||
bool test = reader.GetBoolean("PresenceDetection", "Test", false);
|
||||
if (test)
|
||||
std::cout << "Test On" << std::endl;
|
||||
else
|
||||
std::cout << "Test Off" << std::endl;
|
||||
|
||||
std::cout << "--------------------------------" << std::endl << std::endl;
|
||||
}
|
||||
|
||||
void TestLogic()
|
||||
{
|
||||
std::cout << "--------------------------------" << std::endl;
|
||||
std::cout << "TestLogic" << std::endl << std::endl;
|
||||
|
||||
PresenceDetection::Logic::Logic logic("http://DomoticaPi:8080/api/inventory/WirelessDevice");
|
||||
|
||||
logic.LoadDevicesFromConfiguration();
|
||||
logic.UpdateDevicesFromInventory();
|
||||
|
||||
logic.DumpDevices();
|
||||
|
||||
std::cout << "--------------------------------" << std::endl << std::endl;
|
||||
}
|
||||
|
||||
void TestPing()
|
||||
{
|
||||
std::cout << "--------------------------------" << std::endl;
|
||||
std::cout << "TestPing" << std::endl << std::endl;
|
||||
|
||||
bool wifi = PresenceDetection::WiFi::Functions::Ping("192.168.1.174");
|
||||
if (wifi)
|
||||
std::cout << "192.168.1.174 Online" << std::endl;
|
||||
else
|
||||
std::cout << "192.168.1.174 Offline" << std::endl;
|
||||
|
||||
bool bluetooth = PresenceDetection::Bluetooth::Functions::Ping("64:C7:53:77:2A:32");
|
||||
if (bluetooth)
|
||||
std::cout << "64:C7:53:77:2A:32 Online" << std::endl;
|
||||
else
|
||||
std::cout << "64:C7:53:77:2A:32 Offline" << std::endl;
|
||||
|
||||
bluetooth = PresenceDetection::Bluetooth::Functions::Ping("C8:BC:C8:22:94:68");
|
||||
if (bluetooth)
|
||||
std::cout << "C8:BC:C8:22:94:68 Online" << std::endl;
|
||||
else
|
||||
std::cout << "C8:BC:C8:22:94:68 Offline" << std::endl;
|
||||
|
||||
bluetooth = PresenceDetection::Bluetooth::Functions::Ping("E8:9E:B4:25:E1:E8");
|
||||
if (bluetooth)
|
||||
std::cout << "E8:9E:B4:25:E1:E8 Online" << std::endl;
|
||||
else
|
||||
std::cout << "E8:9E:B4:25:E1:E8 Offline" << std::endl;
|
||||
|
||||
std::cout << "--------------------------------" << std::endl << std::endl;
|
||||
}
|
||||
|
||||
void TestUniFi()
|
||||
{
|
||||
std::shared_ptr<PresenceDetection::WiFi::Driver> pWiFiDriver;
|
||||
|
||||
std::string hostname = "UniFi-Controller";
|
||||
int port = 8443;
|
||||
std::string username = "admin";
|
||||
std::string password = "Wh1sK3y196909";
|
||||
std::string cookiefile = "UniFi_Cookies";
|
||||
int timeout = 60;
|
||||
std::string inventoryURL = "http://DomoticaPi:8080/api/inventory/WirelessDevice";
|
||||
std::string target = "";
|
||||
std::vector<PresenceDetection::Util::StaticDevice> staticDevices;
|
||||
|
||||
pWiFiDriver = std::make_shared<PresenceDetection::WiFi::Driver>(hostname, port, username, password, cookiefile, timeout, inventoryURL, target, staticDevices);
|
||||
|
||||
sigset_t wset;
|
||||
sigemptyset(&wset);
|
||||
sigaddset(&wset,SIGHUP);
|
||||
sigaddset(&wset,SIGINT);
|
||||
sigaddset(&wset,SIGTERM);
|
||||
int sig;
|
||||
sigwait(&wset,&sig);
|
||||
|
||||
pWiFiDriver->Stop();
|
||||
pWiFiDriver->Wait();
|
||||
}
|
||||
|
||||
int main(int /*argc*/, char** /*argv[]*/)
|
||||
{
|
||||
//std::string address = "48:4B:AA:85:30:C5";
|
||||
//ping(address.c_str());
|
||||
|
||||
//address = "d0:c5:f3:84:99:de";
|
||||
//ping(address.c_str());
|
||||
|
||||
PresenceDetection::Util::Timer timer;
|
||||
std::function<void()> f_print = print;
|
||||
|
||||
std::cout << "---" << std::endl;
|
||||
timer.StartContinuous(1000, f_print);
|
||||
timer.Stop();
|
||||
timer.Wait();
|
||||
std::cout << "---" << std::endl << std::endl;
|
||||
|
||||
std::cout << "---" << std::endl;
|
||||
timer.StartContinuous(3000, f_print);
|
||||
timer.Abort();
|
||||
timer.Wait();
|
||||
std::cout << "---" << std::endl << std::endl;
|
||||
|
||||
std::cout << "---" << std::endl;
|
||||
timer.StartContinuous(3000, f_print);
|
||||
sleep(1);
|
||||
timer.Abort();
|
||||
timer.Wait();
|
||||
std::cout << "---" << std::endl << std::endl;
|
||||
//TestINIReader();
|
||||
//TestLogic();
|
||||
//TestPing();
|
||||
TestUniFi();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,124 +0,0 @@
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
#include <syslog.h>
|
||||
#include "Util/JSON.h"
|
||||
#include "Functions.h"
|
||||
#include "Device.h"
|
||||
|
||||
|
||||
namespace PresenceDetection {
|
||||
namespace Bluetooth {
|
||||
|
||||
Device::Device(const std::string& inventoryURL, const std::string& target) :
|
||||
m_inventoryURL(inventoryURL),
|
||||
m_target(target)
|
||||
{
|
||||
UpdateDevicesFromInventory();
|
||||
Start();
|
||||
}
|
||||
|
||||
Device::~Device()
|
||||
{
|
||||
}
|
||||
|
||||
void Device::Start()
|
||||
{
|
||||
m_deviceTimer.StartContinuous(10000, static_cast<std::function<void()>>(std::bind(&Device::UpdatePresentDevices, this)));
|
||||
m_inventoryTimer.StartContinuous(300000, static_cast<std::function<void()>>(std::bind(&Device::UpdateDevicesFromInventory, this)));
|
||||
}
|
||||
|
||||
void Device::Stop()
|
||||
{
|
||||
m_deviceTimer.Stop();
|
||||
}
|
||||
|
||||
void Device::Wait()
|
||||
{
|
||||
m_deviceTimer.Wait();
|
||||
}
|
||||
|
||||
void Device::UpdateDevicesFromInventory()
|
||||
{
|
||||
try
|
||||
{
|
||||
std::string devices = m_httpClient.GetUrlContents(m_inventoryURL);
|
||||
Util::JSON json = Util::JSON::parse(devices);
|
||||
|
||||
m_devices.clear();
|
||||
for (auto& element : json)
|
||||
if (element["bluetooth"] != "")
|
||||
{
|
||||
std::string bluetooth = element["bluetooth"];
|
||||
std::transform(bluetooth.begin(), bluetooth.end(), bluetooth.begin(), ::tolower);
|
||||
m_devices.push_back(bluetooth);
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "Bluetooth::Device::GetDevicesFromInventory() - Error: " << e.what() << std::endl;
|
||||
syslog(LOG_ERR, "%s", ss.str().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void Device::UpdatePresentDevices()
|
||||
{
|
||||
std::vector<std::string> presentDevices;
|
||||
std::vector<std::string> addedDevices;
|
||||
std::vector<std::string> removedDevices;
|
||||
|
||||
for (std::vector<std::string>::iterator it = m_devices.begin(); it != m_devices.end(); ++it)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Functions::Ping(*it))
|
||||
{
|
||||
if (std::find(m_presentDevices.begin(), m_presentDevices.end(), *it) == m_presentDevices.end())
|
||||
SendStateChange(true, *it);
|
||||
presentDevices.push_back(*it);
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "Bluetooth::Device::UpdatePresentDevices() - Error: " << e.what() << std::endl;
|
||||
syslog(LOG_ERR, "%s", ss.str().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
for (std::vector<std::string>::iterator it = m_presentDevices.begin(); it != m_presentDevices.end(); ++it)
|
||||
if (std::find(presentDevices.begin(), presentDevices.end(), *it) == presentDevices.end())
|
||||
SendStateChange(false, *it);
|
||||
|
||||
m_presentDevices.assign(presentDevices.begin(), presentDevices.end());
|
||||
}
|
||||
|
||||
void Device::SendStateChange(bool present, const std::string& macAddress)
|
||||
{
|
||||
char sign;
|
||||
if (present)
|
||||
sign = '+';
|
||||
else
|
||||
sign = '-';
|
||||
|
||||
std::stringstream ss;
|
||||
ss << "Bluetooth: " << sign << " " << macAddress;
|
||||
syslog(LOG_INFO, "%s", ss.str().c_str());
|
||||
|
||||
std::stringstream url;
|
||||
url << m_target << "/Bluetooth/" << sign << "/" << macAddress;
|
||||
|
||||
try
|
||||
{
|
||||
m_httpClient.GetUrlSilent(url.str());
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "Bluetooth::Device::SendStateChange() - Error: " << e.what() << std::endl;
|
||||
syslog(LOG_ERR, "%s", ss.str().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Bluetooth
|
||||
} // namespace PresenceDetection
|
||||
@@ -1,44 +0,0 @@
|
||||
#ifndef BLUETOOTH_DEVICE_H
|
||||
#define BLUETOOTH_DEVICE_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "Util/Timer.h"
|
||||
#include "Util/HttpClient.h"
|
||||
|
||||
|
||||
namespace PresenceDetection {
|
||||
namespace Bluetooth {
|
||||
|
||||
class Device
|
||||
{
|
||||
public:
|
||||
Device(const std::string& inventoryURL, const std::string& target);
|
||||
~Device();
|
||||
|
||||
void Start();
|
||||
void Stop();
|
||||
void Wait();
|
||||
|
||||
private:
|
||||
void UpdateDevicesFromInventory();
|
||||
void UpdatePresentDevices();
|
||||
void SendStateChange(bool present, const std::string& macAddress);
|
||||
|
||||
private:
|
||||
Util::Timer m_deviceTimer;
|
||||
Util::Timer m_inventoryTimer;
|
||||
Util::HttpClient m_httpClient;
|
||||
|
||||
std::vector<std::string> m_devices;
|
||||
|
||||
std::string m_inventoryURL;
|
||||
std::string m_target;
|
||||
|
||||
std::vector<std::string> m_presentDevices;
|
||||
};
|
||||
|
||||
} // namespace Bluetooth
|
||||
} // namespace PresenceDetection
|
||||
|
||||
#endif // BLUETOOTH_DEVICE_H
|
||||
@@ -0,0 +1,288 @@
|
||||
#include "Driver.h"
|
||||
#include "Functions.h"
|
||||
#include <json.hpp>
|
||||
#include <Logging.h>
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
|
||||
|
||||
namespace PresenceDetection {
|
||||
namespace Bluetooth {
|
||||
|
||||
Driver::Driver(int timeout, const std::string& inventoryURL, const std::string& target, const std::vector<Util::StaticDevice>& staticDevices) :
|
||||
m_timeout(timeout),
|
||||
m_checkInterval(3),
|
||||
m_inventoryURL(inventoryURL),
|
||||
m_target(target),
|
||||
m_staticDevices(staticDevices)
|
||||
{
|
||||
if (!m_inventoryURL.empty())
|
||||
UpdateDevicesFromInventory();
|
||||
ClearDevices();
|
||||
Start();
|
||||
}
|
||||
|
||||
Driver::~Driver()
|
||||
{
|
||||
}
|
||||
|
||||
void Driver::Start()
|
||||
{
|
||||
int checkInterval = m_checkInterval * 1000;
|
||||
m_deviceTimer.StartContinuous(checkInterval, static_cast<std::function<void()>>(std::bind(&Driver::UpdatePresentDevices, this)));
|
||||
if (!m_inventoryURL.empty())
|
||||
m_inventoryTimer.StartContinuous(600000, static_cast<std::function<void()>>(std::bind(&Driver::UpdateDevicesFromInventory, this)));
|
||||
}
|
||||
|
||||
void Driver::Stop()
|
||||
{
|
||||
m_deviceTimer.Stop();
|
||||
if (!m_inventoryURL.empty())
|
||||
m_inventoryTimer.Stop();
|
||||
}
|
||||
|
||||
void Driver::Wait()
|
||||
{
|
||||
m_deviceTimer.Wait();
|
||||
if (!m_inventoryURL.empty())
|
||||
m_inventoryTimer.Wait();
|
||||
}
|
||||
|
||||
void Driver::ClearDevices()
|
||||
{
|
||||
for (std::vector<Util::DynamicDevice>::iterator it = m_dynamicDevices.begin(); it != m_dynamicDevices.end(); ++it)
|
||||
{
|
||||
try
|
||||
{
|
||||
SendStateChange(false, it->MacAddress());
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "Bluetooth::Driver::ClearDevices() - Error: " << e.what() << std::endl;
|
||||
Logging::Log(Logging::Severity::Error, ss.str());
|
||||
}
|
||||
}
|
||||
|
||||
for (std::vector<Util::StaticDevice>::iterator it = m_staticDevices.begin(); it != m_staticDevices.end(); ++it)
|
||||
{
|
||||
if (it->HasBluetoothMac())
|
||||
{
|
||||
try
|
||||
{
|
||||
SendStateChange(false, it->BluetoothMac());
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "Bluetooth::Driver::ClearDevices() - Error: " << e.what() << std::endl;
|
||||
Logging::Log(Logging::Severity::Error, ss.str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Driver::UpdateDevicesFromInventory()
|
||||
{
|
||||
try
|
||||
{
|
||||
Http::HttpRequest request(m_inventoryURL);
|
||||
std::string devices = m_httpClient.Open(request);
|
||||
nlohmann::json json = nlohmann::json::parse(devices);
|
||||
|
||||
m_dynamicDevices.clear();
|
||||
for (auto& element : json)
|
||||
if (element["bluetooth"] != "")
|
||||
{
|
||||
std::string bluetooth = element["bluetooth"];
|
||||
std::transform(bluetooth.begin(), bluetooth.end(), bluetooth.begin(), ::tolower);
|
||||
m_dynamicDevices.push_back(Util::DynamicDevice(bluetooth));
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "Bluetooth::Driver::GetDevicesFromInventory() - Error: " << e.what() << std::endl;
|
||||
Logging::Log(Logging::Severity::Error, ss.str());
|
||||
}
|
||||
}
|
||||
|
||||
void Driver::UpdatePresentDevices()
|
||||
{
|
||||
std::vector<std::string> presentDevices;
|
||||
std::vector<std::string> ignoredDevices;
|
||||
|
||||
for (std::vector<Util::DynamicDevice>::iterator it = m_dynamicDevices.begin(); it != m_dynamicDevices.end(); ++it)
|
||||
{
|
||||
try
|
||||
{
|
||||
bool pollDevice = false;
|
||||
if (std::find(m_presentDevices.begin(), m_presentDevices.end(), it->MacAddress()) == m_presentDevices.end())
|
||||
{
|
||||
pollDevice = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
it->IncrementProbeCounter();
|
||||
if (it->ProbeCounter() * m_checkInterval >= m_timeout)
|
||||
{
|
||||
pollDevice = true;
|
||||
it->ResetProbeCounter();
|
||||
}
|
||||
}
|
||||
|
||||
if (pollDevice && Functions::Ping(it->MacAddress()))
|
||||
{
|
||||
if (std::find(m_presentDevices.begin(), m_presentDevices.end(), it->MacAddress()) == m_presentDevices.end())
|
||||
SendStateChange(true, it->MacAddress());
|
||||
presentDevices.push_back(it->MacAddress());
|
||||
}
|
||||
else if (pollDevice)
|
||||
{
|
||||
it->ResetProbeCounter();
|
||||
}
|
||||
else
|
||||
{
|
||||
ignoredDevices.push_back(it->MacAddress());
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "Bluetooth::Driver::UpdatePresentDevices() - Error: " << e.what() << std::endl;
|
||||
Logging::Log(Logging::Severity::Error, ss.str());
|
||||
}
|
||||
}
|
||||
|
||||
for (std::vector<Util::StaticDevice>::iterator it = m_staticDevices.begin(); it != m_staticDevices.end(); ++it)
|
||||
{
|
||||
if (it->HasBluetoothMac())
|
||||
{
|
||||
try
|
||||
{
|
||||
bool pollDevice = false;
|
||||
if (std::find(m_presentDevices.begin(), m_presentDevices.end(), it->BluetoothMac()) == m_presentDevices.end())
|
||||
{
|
||||
pollDevice = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
it->IncrementProbeCounter();
|
||||
if (it->ProbeCounter() * m_checkInterval >= m_timeout)
|
||||
{
|
||||
pollDevice = true;
|
||||
it->ResetProbeCounter();
|
||||
}
|
||||
}
|
||||
|
||||
if (pollDevice && Functions::Ping(it->BluetoothMac()))
|
||||
{
|
||||
if (std::find(m_presentDevices.begin(), m_presentDevices.end(), it->BluetoothMac()) == m_presentDevices.end())
|
||||
SendStateChange(true, it->BluetoothMac());
|
||||
presentDevices.push_back(it->BluetoothMac());
|
||||
}
|
||||
else if (pollDevice)
|
||||
{
|
||||
it->ResetProbeCounter();
|
||||
}
|
||||
else
|
||||
{
|
||||
ignoredDevices.push_back(it->BluetoothMac());
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "Bluetooth::Driver::UpdatePresentDevices() - Error: " << e.what() << std::endl;
|
||||
Logging::Log(Logging::Severity::Error, ss.str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (std::vector<std::string>::iterator it = m_presentDevices.begin(); it != m_presentDevices.end(); ++it)
|
||||
if (std::find(presentDevices.begin(), presentDevices.end(), *it) == presentDevices.end() &&
|
||||
std::find(ignoredDevices.begin(), ignoredDevices.end(), *it) == ignoredDevices.end())
|
||||
SendStateChange(false, *it);
|
||||
|
||||
for (std::vector<std::string>::iterator it = m_presentDevices.begin(); it != m_presentDevices.end(); ++it)
|
||||
if (std::find(ignoredDevices.begin(), ignoredDevices.end(), *it) != ignoredDevices.end())
|
||||
presentDevices.push_back(*it);
|
||||
|
||||
m_presentDevices.assign(presentDevices.begin(), presentDevices.end());
|
||||
}
|
||||
|
||||
void Driver::SendStateChange(bool present, const std::string& macAddress)
|
||||
{
|
||||
char sign;
|
||||
if (present)
|
||||
sign = '+';
|
||||
else
|
||||
sign = '-';
|
||||
|
||||
std::stringstream ss;
|
||||
ss << "Bluetooth: " << sign << " " << macAddress;
|
||||
Logging::Log(Logging::Severity::Info, ss.str());
|
||||
|
||||
if (!m_target.empty())
|
||||
{
|
||||
std::stringstream url;
|
||||
url << m_target << "/Bluetooth/" << sign << "/" << macAddress;
|
||||
|
||||
try
|
||||
{
|
||||
Http::HttpRequest request(url.str());
|
||||
request.ReturnType(Http::HttpRequest::ReturnType::None);
|
||||
m_httpClient.Open(request);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "Bluetooth::Driver::SendStateChange() - Error: " << e.what() << std::endl;
|
||||
Logging::Log(Logging::Severity::Error, ss.str());
|
||||
}
|
||||
}
|
||||
|
||||
for (std::vector<Util::StaticDevice>::iterator it = m_staticDevices.begin(); it != m_staticDevices.end(); ++it)
|
||||
{
|
||||
if (it->HasBluetoothMac() && it->BluetoothMac() == macAddress)
|
||||
{
|
||||
it->SetBluetoothState(present);
|
||||
|
||||
std::vector<std::string> urls;
|
||||
|
||||
if (present)
|
||||
{
|
||||
if (!it->GetWifiState() && it->HasOnlineURL())
|
||||
urls.push_back(it->OnlineURL());
|
||||
if (it->HasBluetoothOnlineURL())
|
||||
urls.push_back(it->BluetoothOnlineURL());
|
||||
}
|
||||
else if (!present)
|
||||
{
|
||||
if (!it->GetWifiState() && it->HasOfflineURL())
|
||||
urls.push_back(it->OfflineURL());
|
||||
if (it->HasBluetoothOfflineURL())
|
||||
urls.push_back(it->BluetoothOfflineURL());
|
||||
}
|
||||
|
||||
for (auto& url : urls)
|
||||
{
|
||||
try
|
||||
{
|
||||
Http::HttpRequest request(url);
|
||||
request.ReturnType(Http::HttpRequest::ReturnType::None);
|
||||
m_httpClient.Open(request);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "Bluetooth::Driver::SendStateChange() - Error: " << e.what() << std::endl;
|
||||
Logging::Log(Logging::Severity::Error, ss.str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Bluetooth
|
||||
} // namespace PresenceDetection
|
||||
@@ -0,0 +1,50 @@
|
||||
#ifndef BLUETOOTH_DRIVER_H
|
||||
#define BLUETOOTH_DRIVER_H
|
||||
|
||||
#include "Util/DynamicDevice.h"
|
||||
#include "Util/StaticDevice.h"
|
||||
#include <HttpClient.h>
|
||||
#include <Timer.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace PresenceDetection {
|
||||
namespace Bluetooth {
|
||||
|
||||
class Driver
|
||||
{
|
||||
public:
|
||||
Driver(int timeout, const std::string& inventoryURL, const std::string& target, const std::vector<Util::StaticDevice>& staticDevices);
|
||||
~Driver();
|
||||
|
||||
void Start();
|
||||
void Stop();
|
||||
void Wait();
|
||||
|
||||
private:
|
||||
void ClearDevices();
|
||||
void UpdateDevicesFromInventory();
|
||||
void UpdatePresentDevices();
|
||||
void SendStateChange(bool present, const std::string& macAddress);
|
||||
|
||||
private:
|
||||
Timer::Timer m_deviceTimer;
|
||||
Timer::Timer m_inventoryTimer;
|
||||
Http::HttpClient m_httpClient;
|
||||
|
||||
std::vector<Util::DynamicDevice> m_dynamicDevices;
|
||||
|
||||
int m_timeout;
|
||||
int m_checkInterval;
|
||||
std::string m_inventoryURL;
|
||||
std::string m_target;
|
||||
std::vector<Util::StaticDevice> m_staticDevices;
|
||||
|
||||
std::vector<std::string> m_presentDevices;
|
||||
};
|
||||
|
||||
} // namespace Bluetooth
|
||||
} // namespace PresenceDetection
|
||||
|
||||
#endif // BLUETOOTH_DRIVER_H
|
||||
+13
-14
@@ -1,16 +1,15 @@
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <stdexcept>
|
||||
#include <syslog.h>
|
||||
#include "Functions.h"
|
||||
#include "Socket.h"
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <bluetooth/bluetooth.h>
|
||||
#include <bluetooth/hci.h>
|
||||
#include <bluetooth/l2cap.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/poll.h>
|
||||
#include "Socket.h"
|
||||
#include "Functions.h"
|
||||
#include <poll.h>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <sys/time.h>
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace PresenceDetection {
|
||||
@@ -44,8 +43,8 @@ bool Functions::Ping(const std::string& macAddress)
|
||||
str2ba(macAddress.c_str(), &socketAddress.l2_bdaddr);
|
||||
|
||||
struct timeval timeoutStruct;
|
||||
timeoutStruct.tv_sec = 3;
|
||||
timeoutStruct.tv_usec = 0;
|
||||
timeoutStruct.tv_sec = 1;
|
||||
timeoutStruct.tv_usec = 0; //500000;
|
||||
|
||||
fd_set writeDescriptor, errorDescriptor;
|
||||
FD_ZERO(&writeDescriptor);
|
||||
@@ -69,7 +68,7 @@ bool Functions::Ping(const std::string& macAddress)
|
||||
|
||||
if (ret != 0)
|
||||
{
|
||||
if (select(socketDescriptor + 1, &errorDescriptor, &writeDescriptor, NULL, &timeoutStruct) < 0)
|
||||
if (select(socketDescriptor + 1, &errorDescriptor, &writeDescriptor, NULL, &timeoutStruct) <= 0)
|
||||
return false;
|
||||
|
||||
int error = 0;
|
||||
@@ -126,7 +125,7 @@ bool Functions::Ping(const std::string& macAddress)
|
||||
pf[0].events = POLLIN;
|
||||
|
||||
int err;
|
||||
int timeout = 500;
|
||||
int timeout = 200;
|
||||
if ((err = poll(pf, 1, timeout)) < 0)
|
||||
throw std::runtime_error("Poll failed");
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#include <stdexcept>
|
||||
#include "Socket.h"
|
||||
#include <unistd.h>
|
||||
#include <bluetooth/bluetooth.h>
|
||||
#include <bluetooth/hci.h>
|
||||
#include "Socket.h"
|
||||
#include <stdexcept>
|
||||
|
||||
|
||||
namespace PresenceDetection {
|
||||
@@ -27,4 +27,3 @@ int Socket::Descriptor() const
|
||||
|
||||
} // namespace Bluetooth
|
||||
} // namespace PresenceDetection
|
||||
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
#include "Device.h"
|
||||
|
||||
|
||||
namespace PresenceDetection {
|
||||
namespace Device {
|
||||
|
||||
Device::Device(int id, const std::string& wifiMacAddress, const std::string& bluetoothAddress) :
|
||||
m_id(id),
|
||||
m_wifiMacAddress(wifiMacAddress),
|
||||
m_bluetoothMacAddress(bluetoothAddress),
|
||||
m_online(false)
|
||||
{
|
||||
}
|
||||
|
||||
Device::~Device()
|
||||
{
|
||||
}
|
||||
|
||||
Device::Device(const Device& other)
|
||||
{
|
||||
m_id = other.m_id;
|
||||
m_wifiMacAddress = other.m_wifiMacAddress;
|
||||
m_bluetoothMacAddress = other.m_bluetoothMacAddress;
|
||||
m_online = other.m_online;
|
||||
}
|
||||
|
||||
int Device::ID() const
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
std::string Device::WifiMacAddress() const
|
||||
{
|
||||
return m_wifiMacAddress;
|
||||
}
|
||||
|
||||
std::string Device::BluetoothMacAddress() const
|
||||
{
|
||||
return m_bluetoothMacAddress;
|
||||
}
|
||||
|
||||
bool Device::Online() const
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
return m_online;
|
||||
}
|
||||
|
||||
void Device::Online(bool online)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
m_online = online;
|
||||
}
|
||||
|
||||
} // namespace Device
|
||||
} // namespace PresenceDetection
|
||||
@@ -0,0 +1,38 @@
|
||||
#ifndef DEVICE_DEVICE_H
|
||||
#define DEVICE_DEVICE_H
|
||||
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
|
||||
|
||||
namespace PresenceDetection {
|
||||
namespace Device {
|
||||
|
||||
class Device
|
||||
{
|
||||
public:
|
||||
Device(int id, const std::string& wifiMacAddress, const std::string& bluetoothAddress);
|
||||
~Device();
|
||||
|
||||
Device(const Device& other);
|
||||
|
||||
int ID() const;
|
||||
std::string WifiMacAddress() const;
|
||||
std::string BluetoothMacAddress() const;
|
||||
|
||||
bool Online() const;
|
||||
void Online(bool online);
|
||||
|
||||
private:
|
||||
int m_id;
|
||||
std::string m_wifiMacAddress;
|
||||
std::string m_bluetoothMacAddress;
|
||||
|
||||
mutable std::mutex m_mutex;
|
||||
bool m_online;
|
||||
};
|
||||
|
||||
} // namespace Device
|
||||
} // namespace PresenceDetection
|
||||
|
||||
#endif // DEVICE_DEVICE_H
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../Libraries/Http
|
||||
@@ -1 +0,0 @@
|
||||
../../Libraries/json/include
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../Libraries/Logging
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../Libraries/Timer
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../Libraries/Utilities
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../Libraries/clipp
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../Libraries/inih
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../Libraries/json
|
||||
+125
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
|
||||
Logic ->
|
||||
Contain all Configured Devices
|
||||
-> Retrieve Devices from Domotica API
|
||||
-> Retrieve Devices from Configuration
|
||||
|
||||
|
||||
WiFi -> Check for Devices
|
||||
Change to Offline
|
||||
-> Ping (Internal to WiFi)
|
||||
Fail
|
||||
-> Update Device to Offline
|
||||
Success
|
||||
-> NOOP
|
||||
Change to Online
|
||||
-> Ping (Internal to WiFi)
|
||||
Fail
|
||||
-> NOOP
|
||||
Success
|
||||
-> Update Device to Online
|
||||
|
||||
|
||||
Bluetooth -> Check for Devices
|
||||
Change to Offline
|
||||
Change to Online
|
||||
|
||||
|
||||
API -> Poll Devices
|
||||
|
||||
- Who keeps track of the devices?
|
||||
Logic?
|
||||
Driver?
|
||||
|
||||
//*/
|
||||
|
||||
#include "Logic.h"
|
||||
#include <Logging.h>
|
||||
#include <json.hpp>
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
|
||||
namespace PresenceDetection {
|
||||
namespace Logic {
|
||||
|
||||
Logic::Logic(const std::string& inventoryURL) :
|
||||
m_inventoryURL(inventoryURL)
|
||||
{
|
||||
}
|
||||
|
||||
Logic::~Logic()
|
||||
{
|
||||
}
|
||||
|
||||
void Logic::LoadDevicesFromConfiguration()
|
||||
{
|
||||
}
|
||||
|
||||
void Logic::UpdateDevicesFromInventory()
|
||||
{
|
||||
try
|
||||
{
|
||||
Http::HttpRequest request(m_inventoryURL);
|
||||
std::string devices = m_httpClient.Open(request);
|
||||
nlohmann::json json = nlohmann::json::parse(devices);
|
||||
|
||||
m_dynamicDevices.clear();
|
||||
for (auto& element : json)
|
||||
{
|
||||
int id = std::stoi(element["id"].get<std::string>());
|
||||
std::string wifi;
|
||||
std::string bluetooth;
|
||||
|
||||
//if (element["wifi"] != "")
|
||||
if (element["macaddress"] != "")
|
||||
{
|
||||
//wifi = element["wifi"];
|
||||
wifi = element["macaddress"];
|
||||
std::transform(wifi.begin(), wifi.end(), wifi.begin(), ::tolower);
|
||||
}
|
||||
|
||||
if (element["bluetooth"] != "")
|
||||
{
|
||||
bluetooth = element["bluetooth"];
|
||||
std::transform(bluetooth.begin(), bluetooth.end(), bluetooth.begin(), ::tolower);
|
||||
}
|
||||
|
||||
m_dynamicDevices.push_back(Device::Device(id, wifi, bluetooth));
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "Logic::GetDevicesFromInventory() - Error: " << e.what() << std::endl;
|
||||
Logging::Log(Logging::Severity::Error, ss.str());
|
||||
}
|
||||
}
|
||||
|
||||
void Logic::DumpDevices()
|
||||
{
|
||||
std::cout << "Static Devices:" << std::endl;
|
||||
for (auto& device : m_staticDevices)
|
||||
{
|
||||
std::cout << "ID: " << device.ID() << std::endl;
|
||||
std::cout << "Wifi: " << device.WifiMacAddress() << std::endl;
|
||||
std::cout << "Bluetooth: " << device.BluetoothMacAddress() << std::endl;
|
||||
std::cout << "Online: " << device.Online() << std::endl;
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
std::cout << "Dynamic Devices:" << std::endl;
|
||||
for (auto& device : m_dynamicDevices)
|
||||
{
|
||||
std::cout << "ID: " << device.ID() << std::endl;
|
||||
std::cout << "Wifi: " << device.WifiMacAddress() << std::endl;
|
||||
std::cout << "Bluetooth: " << device.BluetoothMacAddress() << std::endl;
|
||||
std::cout << "Online: " << device.Online() << std::endl;
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Logic
|
||||
} // namespace PresenceDetection
|
||||
@@ -0,0 +1,41 @@
|
||||
#ifndef LOGIC_LOGIC_H
|
||||
#define LOGIC_LOGIC_H
|
||||
|
||||
#include "Device/Device.h"
|
||||
#include <HttpClient.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace PresenceDetection {
|
||||
namespace Logic {
|
||||
|
||||
class Logic
|
||||
{
|
||||
public:
|
||||
Logic(const std::string& inventoryURL);
|
||||
~Logic();
|
||||
|
||||
void LoadDevicesFromConfiguration();
|
||||
void UpdateDevicesFromInventory();
|
||||
|
||||
void DumpDevices();
|
||||
|
||||
private:
|
||||
//void UpdatePresentDevices();
|
||||
void PollBluetoothDevices();
|
||||
void PollWiFiDevices();
|
||||
|
||||
private:
|
||||
Http::HttpClient m_httpClient;
|
||||
|
||||
std::string m_inventoryURL;
|
||||
std::vector<Device::Device> m_dynamicDevices;
|
||||
std::vector<Device::Device> m_staticDevices;
|
||||
|
||||
};
|
||||
|
||||
} // namespace Logic
|
||||
} // namespace PresenceDetection
|
||||
|
||||
#endif // LOGIC_LOGIC_H
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../Makefile
|
||||
@@ -1,234 +0,0 @@
|
||||
#
|
||||
# Makefile
|
||||
#
|
||||
|
||||
ROOTPATH := /opt/build/PresenceDetection
|
||||
COMMANDLINE := $(shell ps -o args= $$PPID)
|
||||
|
||||
ARCHS := $(shell ls $(ROOTPATH)/Makefile.conf.* | grep -v base | sed 's/.*Makefile\.conf\.//g')
|
||||
ARCHS += any
|
||||
ARCH := $(filter $(ARCHS),$(MAKECMDGOALS))
|
||||
MAKECMDGOALS := $(filter-out $(ARCH),$(MAKECMDGOALS))
|
||||
ARCHS := $(filter-out any,$(ARCHS))
|
||||
|
||||
ifeq ($(ARCH),)
|
||||
ARCH := x86-64
|
||||
endif
|
||||
|
||||
ifeq (,$(findstring -S,$(COMMANDLINE)))
|
||||
ifneq ($(ARCH),)
|
||||
$(info ARCH: $(ARCH))
|
||||
endif
|
||||
endif
|
||||
|
||||
-include $(ROOTPATH)/Makefile.conf.$(ARCH)
|
||||
-include $(ROOTPATH)/Makefile.conf.base
|
||||
|
||||
PID := $(shell echo $$$$)
|
||||
PREFIX = nice -n 19 /usr/bin/time --format='%E (%U)' -o /dev/shm/t-$(PID)
|
||||
POSTFIX = && cat /dev/shm/t-$(PID) | xargs -I "%" echo -en '\033[1A\033[100D\033[60C' "%\n" && rm -f /dev/shm/t-$(PID)
|
||||
|
||||
ARNAME = $(notdir $(CURDIR)).a.$(ARCH)
|
||||
|
||||
SUBDIRS := $(wildcard */.)
|
||||
SUBDIRS := $(foreach dir,$(SUBDIRS),$(subst /.,,$(dir)))
|
||||
FILTER = crash%
|
||||
SUBDIRS := $(filter-out $(FILTER),$(SUBDIRS))
|
||||
FILTER = doc%
|
||||
SUBDIRS := $(filter-out $(FILTER),$(SUBDIRS))
|
||||
FILTER = Libraries%
|
||||
SUBDIRS := $(filter-out $(FILTER),$(SUBDIRS))
|
||||
SUBDIRARS = $(foreach dir,$(SUBDIRS),$(dir)/$(dir).a)
|
||||
|
||||
LOCALSOURCES = $(wildcard *.cpp *.cc)
|
||||
LOCALOBJECTS := $(LOCALSOURCES:.cpp=.o.$(ARCH))
|
||||
LOCALOBJECTS := $(LOCALOBJECTS:.cc=.o.$(ARCH))
|
||||
LOCALDEPENDS = $(LOCALOBJECTS:.o.$(ARCH)=.d.$(ARCH))
|
||||
SOURCES = $(wildcard *.cpp */*.cpp */*/*.cpp */*/*/*.cpp)
|
||||
OBJECTS = $(SOURCES:.cpp=.o.$(ARCH))
|
||||
DEPENDS = $(OBJECTS:.o.$(ARCH)=.d.$(ARCH))
|
||||
TARGETS =
|
||||
|
||||
define build_target_arch
|
||||
$(eval $@_DATETIME := $(DATETIME))
|
||||
@echo -n " [LD] $(1)\n"
|
||||
@$(PREFIX) $(CC) -o $(1) $(2) $(LFLAGS) $(CFLAGS) $(POSTFIX)
|
||||
@$(OBJCOPY) --only-keep-debug $(1) $(DEBUGDIR)/$(1)-$($@_DATETIME).debug
|
||||
@$(STRIP) $(SFLAGS) $(1)
|
||||
@$(OBJCOPY) --add-gnu-debuglink="$(DEBUGDIR)/$(1)-$($@_DATETIME).debug" $(1)
|
||||
@chmod -x $(DEBUGDIR)/$(1)-$($@_DATETIME).debug
|
||||
endef
|
||||
|
||||
define build_target
|
||||
@if [ "$(ARCH)" = "any" ]; then \
|
||||
for arch in $(ARCHS); do \
|
||||
echo "ARCH: $$arch"; \
|
||||
$(MAKE) -s -S $(1) $$arch; \
|
||||
done; \
|
||||
true; \
|
||||
else \
|
||||
$(MAKE) -s -S $(1).$(ARCH) $(ARCH); \
|
||||
fi
|
||||
endef
|
||||
|
||||
$(LOCALOBJECTS): | $(SUBDIRS)
|
||||
$(OBJECTS): | $(SUBDIRS)
|
||||
|
||||
artifacts: $(LOCALOBJECTS)
|
||||
|
||||
.DEFAULT_GOAL := artifacts
|
||||
|
||||
-include Makefile.target
|
||||
|
||||
ifneq ($(MAKECMDGOALS),clean)
|
||||
-include $(LOCALDEPENDS)
|
||||
endif
|
||||
|
||||
%.d.$(ARCH): %.cpp
|
||||
@if [ "$(ARCH)" != "any" ]; then \
|
||||
depth=$(MAKELEVEL); \
|
||||
while [ $${depth} -gt 0 ] ; do \
|
||||
echo -n " "; \
|
||||
depth=`expr $$depth - 1`; \
|
||||
done; \
|
||||
true; \
|
||||
echo -n " [MM] $@\n"; \
|
||||
$(PREFIX) $(CC) $(CFLAGS) $< -MM -MT $(@:.d.$(ARCH)=.o.$(ARCH)) >$@ $(POSTFIX); \
|
||||
fi
|
||||
|
||||
%.o.$(ARCH): %.cpp
|
||||
@depth=$(MAKELEVEL); \
|
||||
while [ $${depth} -gt 0 ] ; do \
|
||||
echo -n " "; \
|
||||
depth=`expr $$depth - 1`; \
|
||||
done; \
|
||||
true
|
||||
@echo -n " [CC] $@\n"
|
||||
@$(PREFIX) $(CC) -c $(CFLAGS) $< -o $@ $(POSTFIX)
|
||||
|
||||
%.d.$(ARCH): %.cc
|
||||
@if [ "$(ARCH)" != "any" ]; then \
|
||||
depth=$(MAKELEVEL); \
|
||||
while [ $${depth} -gt 0 ] ; do \
|
||||
echo -n " "; \
|
||||
depth=`expr $$depth - 1`; \
|
||||
done; \
|
||||
true; \
|
||||
echo -n " [MM] $@\n"; \
|
||||
$(PREFIX) $(CC) $(CFLAGS) $< -MM -MT $(@:.d.$(ARCH)=.o.$(ARCH)) >$@ $(POSTFIX); \
|
||||
fi
|
||||
|
||||
%.o.$(ARCH): %.cc
|
||||
@depth=$(MAKELEVEL); \
|
||||
while [ $${depth} -gt 0 ] ; do \
|
||||
echo -n " "; \
|
||||
depth=`expr $$depth - 1`; \
|
||||
done; \
|
||||
true
|
||||
@echo -n " [CC] $@\n"
|
||||
@$(PREFIX) $(CC) -c $(CFLAGS) $< -o $@ $(POSTFIX)
|
||||
|
||||
$(ARNAME): $(SUBDIRS) $(LOCALOBJECTS)
|
||||
@depth=$(MAKELEVEL); \
|
||||
while [ $${depth} -gt 0 ] ; do \
|
||||
echo -n " "; \
|
||||
depth=`expr $$depth - 1`; \
|
||||
done; \
|
||||
true
|
||||
@echo -n " [AR] $@\n"
|
||||
@$(PREFIX) $(AR) rcuT $@ $(LOCALOBJECTS) $(SUBDIRARS) $(POSTFIX)
|
||||
|
||||
.PHONY: $(SUBDIRS)
|
||||
$(SUBDIRS):
|
||||
@depth=$(MAKELEVEL); \
|
||||
while [ $${depth} -gt 0 ] ; do \
|
||||
echo -n " "; \
|
||||
depth=`expr $$depth - 1`; \
|
||||
done; \
|
||||
true
|
||||
@echo " <$@>"
|
||||
@$(MAKE) -s -S -C $@ artifacts $(ARCH)
|
||||
@depth=$(MAKELEVEL); \
|
||||
while [ $${depth} -gt 0 ] ; do \
|
||||
echo -n " "; \
|
||||
depth=`expr $$depth - 1`; \
|
||||
done; \
|
||||
true
|
||||
@echo " </$@>"
|
||||
|
||||
.PHONY: all
|
||||
all: $(TARGETS)
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
@if [ "$(ARCH)" = "any" ]; then \
|
||||
for arch in $(ARCHS); do \
|
||||
echo "ARCH: $$arch"; \
|
||||
$(MAKE) -s -S $(MAKECMDGOALS) $$arch; \
|
||||
done; \
|
||||
true; \
|
||||
else \
|
||||
for dir in $(SUBDIRS); do \
|
||||
depth=$(MAKELEVEL); \
|
||||
while [ $${depth} -gt 0 ] ; do \
|
||||
echo -n " "; \
|
||||
depth=`expr $$depth - 1`; \
|
||||
done; \
|
||||
echo " <$$dir>"; \
|
||||
$(MAKE) -s -S -C $$dir $@ $(ARCH); \
|
||||
while [ $${depth} -gt 0 ] ; do \
|
||||
echo -n " "; \
|
||||
depth=`expr $$depth - 1`; \
|
||||
done; \
|
||||
echo " </$$dir>"; \
|
||||
done; \
|
||||
for target in $(TARGETS); do \
|
||||
rm -f $$target.$(ARCH); \
|
||||
done; \
|
||||
true; \
|
||||
fi
|
||||
@rm -f $(LOCALOBJECTS) $(LOCALDEPENDS) $(ARNAME) || true
|
||||
|
||||
.PHONY: cleandeps
|
||||
cleandeps:
|
||||
@if [ "$(ARCH)" = "any" ]; then \
|
||||
for arch in $(ARCHS); do \
|
||||
echo "ARCH: $$arch"; \
|
||||
$(MAKE) -s -S $(MAKECMDGOALS) $$arch; \
|
||||
done; \
|
||||
true; \
|
||||
else \
|
||||
for dir in $(SUBDIRS); do \
|
||||
depth=$(MAKELEVEL); \
|
||||
while [ $${depth} -gt 0 ] ; do \
|
||||
echo -n " "; \
|
||||
depth=`expr $$depth - 1`; \
|
||||
done; \
|
||||
echo " <$$dir>"; \
|
||||
$(MAKE) -s -S -C $$dir $@ $(ARCH); \
|
||||
while [ $${depth} -gt 0 ] ; do \
|
||||
echo -n " "; \
|
||||
depth=`expr $$depth - 1`; \
|
||||
done; \
|
||||
echo " </$$dir>"; \
|
||||
done; \
|
||||
for target in $(TARGETS); do \
|
||||
rm -f $$target.$(ARCH); \
|
||||
done; \
|
||||
true; \
|
||||
fi
|
||||
@rm -f $(LOCALDEPENDS) || true
|
||||
|
||||
.PHONY: $(ARCH)
|
||||
$(ARCH):
|
||||
@if [ "$(words $(MAKECMDGOALS))" = "0" ]; then \
|
||||
if [ "$(ARCH)" = "any" ]; then \
|
||||
for arch in $(ARCHS); do \
|
||||
echo "ARCH: $$arch"; \
|
||||
$(MAKE) -s -S $(.DEFAULT_GOAL) $$arch; \
|
||||
done; \
|
||||
true; \
|
||||
else \
|
||||
$(MAKE) -s -S $(.DEFAULT_GOAL) $(ARCH); \
|
||||
fi \
|
||||
fi
|
||||
@@ -0,0 +1,24 @@
|
||||
#
|
||||
# Makefile.conf
|
||||
#
|
||||
|
||||
LIBRARIES += Http
|
||||
LIBRARIES += Timer
|
||||
LIBRARIES += Logging
|
||||
LIBRARIES += Utilities
|
||||
|
||||
CFLAGS += -I$(ROOTPATH)/Libraries/clipp/include
|
||||
CFLAGS += -I$(ROOTPATH)/Libraries/inih
|
||||
CFLAGS += -I$(ROOTPATH)/Libraries/json/include/nlohmann -I$(ROOTPATH)/Libraries/json/include
|
||||
|
||||
LFLAGS += -lbluetooth
|
||||
LFLAGS += -lpthread
|
||||
|
||||
CFLAGS += -I$(ROOTPATH) -I$(ROOTPATH)/Libraries
|
||||
|
||||
DEBUGDIR := .debug
|
||||
|
||||
DEFAULTARCH := x86_64-alpine
|
||||
TARGETS += PresenceDetection
|
||||
TARGETS += Test
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
#
|
||||
# Makefile.conf.armv6
|
||||
#
|
||||
|
||||
ARCH := armv6
|
||||
CFLAGS := -marm -march=armv6
|
||||
|
||||
AR := /opt/build/rpi-armv6/tools/arm-bcm2708/arm-linux-gnueabihf/bin/arm-linux-gnueabihf-ar
|
||||
CC := /opt/build/rpi-armv6/tools/arm-bcm2708/arm-linux-gnueabihf/bin/arm-linux-gnueabihf-g++
|
||||
STRIP := /opt/build/rpi-armv6/tools/arm-bcm2708/arm-linux-gnueabihf/bin/arm-linux-gnueabihf-strip
|
||||
OBJCOPY := /opt/build/rpi-armv6/tools/arm-bcm2708/arm-linux-gnueabihf/bin/arm-linux-gnueabihf-objcopy
|
||||
|
||||
CFLAGS += -I/opt/build/rpi-armv6/include
|
||||
LFLAGS += -L/opt/build/rpi-armv6/lib --sysroot /opt/build/rpi-armv6/tools/arm-bcm2708/arm-linux-gnueabihf/arm-linux-gnueabihf/sysroot -Wl,-rpath,/opt/build/rpi-armv6/lib
|
||||
@@ -1,14 +0,0 @@
|
||||
#
|
||||
# Makefile.conf.armv8
|
||||
#
|
||||
|
||||
ARCH := armv8
|
||||
CFLAGS := -marm -march=armv8-a
|
||||
|
||||
AR := /opt/build/rpi-armv8/tools/arm-bcm2708/arm-linux-gnueabihf/bin/arm-linux-gnueabihf-ar
|
||||
CC := /opt/build/rpi-armv8/tools/arm-bcm2708/arm-linux-gnueabihf/bin/arm-linux-gnueabihf-g++
|
||||
STRIP := /opt/build/rpi-armv8/tools/arm-bcm2708/arm-linux-gnueabihf/bin/arm-linux-gnueabihf-strip
|
||||
OBJCOPY := /opt/build/rpi-armv8/tools/arm-bcm2708/arm-linux-gnueabihf/bin/arm-linux-gnueabihf-objcopy
|
||||
|
||||
CFLAGS += -I/opt/build/rpi-armv8/include
|
||||
LFLAGS += -L/opt/build/rpi-armv8/lib --sysroot /opt/build/rpi-armv8/tools/arm-bcm2708/arm-linux-gnueabihf/arm-linux-gnueabihf/sysroot -Wl,-rpath,/opt/build/rpi-armv8/lib
|
||||
@@ -1,18 +0,0 @@
|
||||
#
|
||||
# Makefile.conf.base
|
||||
#
|
||||
|
||||
CFLAGS += -g3 -O3 -fPIC -std=c++11
|
||||
CFLAGS += -Wall -Wextra -Wstrict-aliasing -fmax-errors=5 -Werror -Wunreachable-code -Wdisabled-optimization -Wformat=2 -Winit-self -Wlogical-op -Wmissing-include-dirs -Wnoexcept -Woverloaded-virtual -Wsign-promo -Wstrict-null-sentinel -Wswitch-default -Wno-unused -Wno-variadic-macros -Wno-parentheses -fdiagnostics-show-option
|
||||
# CFLAGS += -Wold-style-cast -pedantic -Wcast-qual -Wundef -Wshadow -Wctor-dtor-privacy -Wredundant-decls -Wstrict-overflow=5 -Wcast-align
|
||||
LFLAGS += -lpthread -lm -lboost_system -lboost_thread -lboost_program_options -lboost_date_time -lssl -lcrypto -lcurl -lz -ldl -lbluetooth
|
||||
|
||||
CFLAGS += -fpermissive
|
||||
CFLAGS += -I$(ROOTPATH) -I$(ROOTPATH)/Libraries/JSON
|
||||
|
||||
CFLAGS += -ffunction-sections -fdata-sections
|
||||
LFLAGS += -Wl,--gc-sections
|
||||
SFLAGS := -s -R .comment -R .gnu.version --strip-unneeded
|
||||
|
||||
DEBUGDIR := .debug
|
||||
DATETIME := `date +'%y%m%d-%H%M'`
|
||||
@@ -1,10 +0,0 @@
|
||||
#
|
||||
# Makefile.conf.x86-64
|
||||
#
|
||||
|
||||
ARCH := x86-64
|
||||
|
||||
AR := ar
|
||||
CC := g++
|
||||
STRIP := strip
|
||||
OBJCOPY := objcopy
|
||||
@@ -1,19 +0,0 @@
|
||||
#
|
||||
# Makefile.target
|
||||
#
|
||||
|
||||
PresenceDetection.$(ARCH): $(OBJECTS) Application/PresenceDetection.o.$(ARCH)
|
||||
$(call build_target_arch,$@,$^)
|
||||
|
||||
test.$(ARCH): $(OBJECTS) Application/Test.o.$(ARCH)
|
||||
$(call build_target_arch,$@,$^)
|
||||
|
||||
PresenceDetection:
|
||||
$(call build_target,$@)
|
||||
|
||||
test:
|
||||
$(call build_target,$@)
|
||||
|
||||
.DEFAULT_GOAL := PresenceDetection
|
||||
|
||||
TARGETS += PresenceDetection test
|
||||
Submodule
+1
Submodule Makefiles added at 2556879082
+22
-9
@@ -1,14 +1,27 @@
|
||||
[PresenceDetection]
|
||||
Target =
|
||||
UniFi = On
|
||||
Bluetooth = On
|
||||
Target =
|
||||
UniFi =
|
||||
Bluetooth =
|
||||
|
||||
[UniFi]
|
||||
[WiFi]
|
||||
Hostname = UniFi
|
||||
Username =
|
||||
Password =
|
||||
CookieFile = /tmp/UniFi_Cookies
|
||||
Inventory =
|
||||
Port =
|
||||
Username =
|
||||
Password =
|
||||
CookieFile =
|
||||
Timeout =
|
||||
Inventory =
|
||||
|
||||
[Bluetooth]
|
||||
Inventory =
|
||||
Timeout =
|
||||
Inventory =
|
||||
|
||||
[Device]
|
||||
WifiMac =
|
||||
BluetoothMac =
|
||||
OnlineURL =
|
||||
WifiOnlineURL =
|
||||
BluetoothOnlineURL =
|
||||
OfflineURL =
|
||||
WifiOfflineURL =
|
||||
BluetoothOfflineURL =
|
||||
|
||||
@@ -1,227 +0,0 @@
|
||||
#include <sstream>
|
||||
#include <syslog.h>
|
||||
#include "Util/JSON.h"
|
||||
#include "Device.h"
|
||||
|
||||
|
||||
namespace PresenceDetection {
|
||||
namespace UniFi {
|
||||
|
||||
Device::Device(const std::string& hostname, const std::string& username, const std::string& password, const std::string& cookieFile, const std::string& inventoryURL, const std::string& target) :
|
||||
m_loggedIn(false),
|
||||
m_hostname(hostname),
|
||||
m_username(username),
|
||||
m_password(password),
|
||||
m_cookieFile(cookieFile),
|
||||
m_inventoryURL(inventoryURL),
|
||||
m_target(target),
|
||||
m_offlineTimeout(120)
|
||||
{
|
||||
UpdateDevicesFromInventory();
|
||||
Start();
|
||||
}
|
||||
|
||||
Device::~Device()
|
||||
{
|
||||
Logout();
|
||||
}
|
||||
|
||||
void Device::Start()
|
||||
{
|
||||
m_deviceTimer.StartContinuous(5000, static_cast<std::function<void()>>(std::bind(&Device::UpdatePresentDevices, this)));
|
||||
m_inventoryTimer.StartContinuous(300000, static_cast<std::function<void()>>(std::bind(&Device::UpdateDevicesFromInventory, this)));
|
||||
}
|
||||
|
||||
void Device::Stop()
|
||||
{
|
||||
m_deviceTimer.Stop();
|
||||
}
|
||||
|
||||
void Device::Wait()
|
||||
{
|
||||
m_deviceTimer.Wait();
|
||||
}
|
||||
|
||||
bool Device::Login()
|
||||
{
|
||||
std::stringstream url;
|
||||
url << "https://" << m_hostname << "/api/login";
|
||||
|
||||
Util::JSON json;
|
||||
json["password"] = m_password;
|
||||
json["username"] = m_username;
|
||||
|
||||
try
|
||||
{
|
||||
std::stringstream output;
|
||||
output << m_httpClient.GetUrlPostContents(url.str(), m_cookieFile, json.dump(), "application/json");
|
||||
|
||||
Util::JSON outputJSON = Util::JSON::parse(output);
|
||||
|
||||
if (outputJSON["meta"]["rc"] != "ok")
|
||||
{
|
||||
std::stringstream error;
|
||||
error << "Login Failed - " << output.str();
|
||||
throw std::runtime_error(error.str());
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "UniFi::Device::Login() - Error: " << e.what() << std::endl;
|
||||
syslog(LOG_ERR, "%s", ss.str().c_str());
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
m_loggedIn = false;
|
||||
return m_loggedIn;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
m_loggedIn = true;
|
||||
return m_loggedIn;
|
||||
}
|
||||
|
||||
void Device::Logout()
|
||||
{
|
||||
std::stringstream url;
|
||||
url << "https://" << m_hostname << "/logout";
|
||||
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
m_loggedIn = false;
|
||||
|
||||
try
|
||||
{
|
||||
m_httpClient.GetUrlSilent(url.str(), m_cookieFile);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "UniFi::Device::Logout() - Error: " << e.what() << std::endl;
|
||||
syslog(LOG_ERR, "%s", ss.str().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void Device::UpdateDevicesFromInventory()
|
||||
{
|
||||
try
|
||||
{
|
||||
std::string devices = m_httpClient.GetUrlContents(m_inventoryURL);
|
||||
Util::JSON json = Util::JSON::parse(devices);
|
||||
|
||||
m_devices.clear();
|
||||
for (auto& element : json)
|
||||
if (element["macaddress"] != "")
|
||||
{
|
||||
std::string macAddress = element["macaddress"];
|
||||
std::transform(macAddress.begin(), macAddress.end(), macAddress.begin(), ::tolower);
|
||||
m_devices.push_back(macAddress);
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "UniFi::Device::GetDevicesFromInventory() - Error: " << e.what() << std::endl;
|
||||
syslog(LOG_ERR, "%s", ss.str().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void Device::UpdatePresentDevices()
|
||||
{
|
||||
bool loggedIn;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
loggedIn = m_loggedIn;
|
||||
}
|
||||
|
||||
if (!loggedIn)
|
||||
if (!Login())
|
||||
return;
|
||||
|
||||
std::stringstream url;
|
||||
url << "https://" << m_hostname << "/api/s/default/stat/sta";
|
||||
|
||||
std::time_t timeStamp = std::time(nullptr);
|
||||
std::vector<std::string> presentDevices;
|
||||
std::vector<std::string> addedDevices;
|
||||
std::vector<std::string> removedDevices;
|
||||
|
||||
try
|
||||
{
|
||||
std::stringstream output;
|
||||
output << m_httpClient.GetUrlContents(url.str(), m_cookieFile);
|
||||
|
||||
Util::JSON json = Util::JSON::parse(output);
|
||||
|
||||
if (json["meta"]["rc"] != "ok")
|
||||
{
|
||||
std::stringstream error;
|
||||
error << "Query Failed";
|
||||
throw std::runtime_error(error.str());
|
||||
}
|
||||
|
||||
for (auto& device : json["data"])
|
||||
{
|
||||
std::string macAddress = device["mac"];
|
||||
int lastSeen = device["last_seen"];
|
||||
|
||||
if ((timeStamp - lastSeen) < m_offlineTimeout)
|
||||
{
|
||||
if (std::find(m_devices.begin(), m_devices.end(), macAddress) != m_devices.end())
|
||||
{
|
||||
if (std::find(m_presentDevices.begin(), m_presentDevices.end(), macAddress) == m_presentDevices.end())
|
||||
addedDevices.push_back(macAddress);
|
||||
presentDevices.push_back(macAddress);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "UniFi::Device::IsDevicePresent() - Error: " << e.what() << std::endl;
|
||||
syslog(LOG_ERR, "%s", ss.str().c_str());
|
||||
Logout();
|
||||
return;
|
||||
}
|
||||
|
||||
for (std::vector<std::string>::iterator it = m_presentDevices.begin(); it != m_presentDevices.end(); ++it)
|
||||
if (std::find(presentDevices.begin(), presentDevices.end(), *it) == presentDevices.end())
|
||||
removedDevices.push_back(*it);
|
||||
|
||||
for (std::vector<std::string>::iterator it = addedDevices.begin(); it != addedDevices.end(); ++it)
|
||||
SendStateChange(true, *it);
|
||||
|
||||
for (std::vector<std::string>::iterator it = removedDevices.begin(); it != removedDevices.end(); ++it)
|
||||
SendStateChange(false, *it);
|
||||
|
||||
m_presentDevices.assign(presentDevices.begin(), presentDevices.end());
|
||||
}
|
||||
|
||||
void Device::SendStateChange(bool present, const std::string& macAddress)
|
||||
{
|
||||
char sign;
|
||||
if (present)
|
||||
sign = '+';
|
||||
else
|
||||
sign = '-';
|
||||
|
||||
std::stringstream ss;
|
||||
ss << "UniFi: " << sign << " " << macAddress;
|
||||
syslog(LOG_INFO, "%s", ss.str().c_str());
|
||||
|
||||
std::stringstream url;
|
||||
url << m_target << "/UniFi/" << sign << "/" << macAddress;
|
||||
|
||||
try
|
||||
{
|
||||
m_httpClient.GetUrlSilent(url.str());
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "UniFi::Device::SendStateChange() - Error: " << e.what() << std::endl;
|
||||
syslog(LOG_ERR, "%s", ss.str().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace UniFi
|
||||
} // namespace PresenceDetection
|
||||
@@ -1,56 +0,0 @@
|
||||
#ifndef UNIFI_DEVICE_H
|
||||
#define UNIFI_DEVICE_H
|
||||
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "Util/Timer.h"
|
||||
#include "Util/HttpClient.h"
|
||||
|
||||
|
||||
namespace PresenceDetection {
|
||||
namespace UniFi {
|
||||
|
||||
class Device
|
||||
{
|
||||
public:
|
||||
Device(const std::string& hostname, const std::string& username, const std::string& password, const std::string& cookieFile, const std::string& inventoryURL, const std::string& target);
|
||||
~Device();
|
||||
|
||||
void Start();
|
||||
void Stop();
|
||||
void Wait();
|
||||
|
||||
private:
|
||||
bool Login();
|
||||
void Logout();
|
||||
|
||||
void UpdateDevicesFromInventory();
|
||||
void UpdatePresentDevices();
|
||||
void SendStateChange(bool present, const std::string& macAddress);
|
||||
|
||||
private:
|
||||
Util::Timer m_deviceTimer;
|
||||
Util::Timer m_inventoryTimer;
|
||||
Util::HttpClient m_httpClient;
|
||||
|
||||
std::mutex m_mutex;
|
||||
bool m_loggedIn;
|
||||
std::string m_hostname;
|
||||
std::string m_username;
|
||||
std::string m_password;
|
||||
std::string m_cookieFile;
|
||||
|
||||
std::vector<std::string> m_devices;
|
||||
|
||||
std::string m_inventoryURL;
|
||||
std::string m_target;
|
||||
int m_offlineTimeout;
|
||||
|
||||
std::vector<std::string> m_presentDevices;
|
||||
};
|
||||
|
||||
} // namespace UniFi
|
||||
} // namespace PresenceDetection
|
||||
|
||||
#endif // UNIFI_DEVICE_H
|
||||
@@ -0,0 +1,35 @@
|
||||
#include "DynamicDevice.h"
|
||||
#include <StringAlgorithm.h>
|
||||
|
||||
|
||||
namespace PresenceDetection {
|
||||
namespace Util {
|
||||
|
||||
DynamicDevice::DynamicDevice(const std::string& macAddress) :
|
||||
m_probeCounter(0),
|
||||
m_macAddress(macAddress)
|
||||
{
|
||||
}
|
||||
|
||||
std::string DynamicDevice::MacAddress()
|
||||
{
|
||||
return m_macAddress;
|
||||
}
|
||||
|
||||
int DynamicDevice::ProbeCounter() const
|
||||
{
|
||||
return m_probeCounter;
|
||||
}
|
||||
|
||||
void DynamicDevice::IncrementProbeCounter()
|
||||
{
|
||||
++m_probeCounter;
|
||||
}
|
||||
|
||||
void DynamicDevice::ResetProbeCounter()
|
||||
{
|
||||
m_probeCounter = 0;
|
||||
}
|
||||
|
||||
} // namespace Util
|
||||
} // namespace PresenceDetection
|
||||
@@ -0,0 +1,31 @@
|
||||
#ifndef UTIL_DYNAMICDEVICE_H
|
||||
#define UTIL_DYNAMICDEVICE_H
|
||||
|
||||
#include "ProbeableDevice.h"
|
||||
#include <string>
|
||||
|
||||
|
||||
namespace PresenceDetection {
|
||||
namespace Util {
|
||||
|
||||
class DynamicDevice : public ProbeableDevice
|
||||
{
|
||||
public:
|
||||
DynamicDevice(const std::string& macAddress);
|
||||
|
||||
virtual int ProbeCounter() const override;
|
||||
virtual void IncrementProbeCounter() override;
|
||||
virtual void ResetProbeCounter() override;
|
||||
|
||||
std::string MacAddress();
|
||||
|
||||
private:
|
||||
int m_probeCounter;
|
||||
|
||||
std::string m_macAddress;
|
||||
};
|
||||
|
||||
} // namespace Util
|
||||
} // namespace PresenceDetection
|
||||
|
||||
#endif // UTIL_DYNAMICDEVICE_H
|
||||
@@ -1,36 +0,0 @@
|
||||
#ifndef UTIL_HELPERS_H
|
||||
#define UTIL_HELPERS_H
|
||||
|
||||
#include <functional>
|
||||
|
||||
|
||||
namespace PresenceDetection {
|
||||
namespace Util {
|
||||
namespace Helpers {
|
||||
|
||||
template <int... Is>
|
||||
struct index {};
|
||||
|
||||
template <int N, int... Is>
|
||||
struct gen_seq : gen_seq<N - 1, N - 1, Is...> {};
|
||||
|
||||
template <int... Is>
|
||||
struct gen_seq<0, Is...> : index<Is...> {};
|
||||
|
||||
template <typename ...FunctionArguments, typename ...Arguments, int... Is>
|
||||
void execute(std::function<void(FunctionArguments...)> const & function, std::tuple<Arguments...>& tuple, index<Is...>)
|
||||
{
|
||||
function(std::get<Is>(tuple)...);
|
||||
}
|
||||
|
||||
template <typename ...FunctionArguments, typename ...Arguments>
|
||||
void execute(std::function<void(FunctionArguments...)> const & function, std::tuple<Arguments...>& tuple)
|
||||
{
|
||||
execute(function, tuple, gen_seq<sizeof...(Arguments)>{});
|
||||
}
|
||||
|
||||
} // namespace Helpers
|
||||
} // namespace Util
|
||||
} // namespace PresenceDetection
|
||||
|
||||
#endif // UTIL_HELPERS_H
|
||||
@@ -1,629 +0,0 @@
|
||||
#include <fstream>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <curl/curl.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include "HttpClientHelpers.h"
|
||||
#include "HttpClient.h"
|
||||
|
||||
|
||||
namespace PresenceDetection {
|
||||
namespace Util {
|
||||
|
||||
HttpClient::HttpClient()
|
||||
{
|
||||
curl_global_init(CURL_GLOBAL_ALL);
|
||||
|
||||
m_userAgents.push_back("Opera/9.80 (X11; Linux i686; U; en) Presto/2.7.62 Version/11.00");
|
||||
|
||||
InitializeLocks();
|
||||
}
|
||||
|
||||
HttpClient::~HttpClient()
|
||||
{
|
||||
FreeLocks();
|
||||
curl_global_cleanup();
|
||||
}
|
||||
|
||||
std::string HttpClient::GetUrlContents(const std::string& url) const
|
||||
{
|
||||
std::string buffer;
|
||||
|
||||
CURL* curl = curl_easy_init();
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
|
||||
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
|
||||
curl_easy_setopt(curl, CURLOPT_USERAGENT, m_userAgents[rand() % m_userAgents.size()].c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &WriteCallback);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);
|
||||
|
||||
int code = 0;
|
||||
curl_easy_perform(curl);
|
||||
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code);
|
||||
curl_easy_cleanup(curl);
|
||||
|
||||
if (code != 200)
|
||||
{
|
||||
std::stringstream error;
|
||||
error << "Error (" << code << ") encountered while retrieving " << url << "\n";
|
||||
error << "Data: " << buffer;
|
||||
throw std::runtime_error(error.str());
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void HttpClient::GetUrlSilent(const std::string& url) const
|
||||
{
|
||||
CURL* curl = curl_easy_init();
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
|
||||
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
|
||||
curl_easy_setopt(curl, CURLOPT_USERAGENT, m_userAgents[rand() % m_userAgents.size()].c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &WriteCallback);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, nullptr);
|
||||
|
||||
int code = 0;
|
||||
curl_easy_perform(curl);
|
||||
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code);
|
||||
curl_easy_cleanup(curl);
|
||||
|
||||
if (code != 200)
|
||||
{
|
||||
std::stringstream error;
|
||||
error << "Error (" << code << ") encountered while retrieving " << url << "\n";
|
||||
throw std::runtime_error(error.str());
|
||||
}
|
||||
}
|
||||
|
||||
std::string HttpClient::GetUrlContents(const std::string& url, const std::string& cookieFile) const
|
||||
{
|
||||
std::string buffer;
|
||||
|
||||
CURL* curl = curl_easy_init();
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
|
||||
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
|
||||
curl_easy_setopt(curl, CURLOPT_USERAGENT, m_userAgents[rand() % m_userAgents.size()].c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_COOKIEFILE, cookieFile.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_COOKIEJAR, cookieFile.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &WriteCallback);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);
|
||||
|
||||
int code = 0;
|
||||
curl_easy_perform(curl);
|
||||
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code);
|
||||
curl_easy_cleanup(curl);
|
||||
|
||||
if (code != 200)
|
||||
{
|
||||
std::stringstream error;
|
||||
error << "Error (" << code << ") encountered while retrieving " << url << "\n";
|
||||
error << "Data: " << buffer;
|
||||
throw std::runtime_error(error.str());
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void HttpClient::GetUrlSilent(const std::string& url, const std::string& cookieFile) const
|
||||
{
|
||||
CURL* curl = curl_easy_init();
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
|
||||
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
|
||||
curl_easy_setopt(curl, CURLOPT_USERAGENT, m_userAgents[rand() % m_userAgents.size()].c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_COOKIEFILE, cookieFile.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_COOKIEJAR, cookieFile.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &WriteCallback);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, nullptr);
|
||||
|
||||
int code = 0;
|
||||
curl_easy_perform(curl);
|
||||
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code);
|
||||
curl_easy_cleanup(curl);
|
||||
|
||||
if (code != 200)
|
||||
{
|
||||
std::stringstream error;
|
||||
error << "Error (" << code << ") encountered while retrieving " << url << "\n";
|
||||
throw std::runtime_error(error.str());
|
||||
}
|
||||
}
|
||||
|
||||
std::string HttpClient::GetUrlPostContents(const std::string& url, const std::string& postData, const std::string& contentType) const
|
||||
{
|
||||
std::string buffer;
|
||||
|
||||
CURL* curl = curl_easy_init();
|
||||
|
||||
std::stringstream contentTypeString;
|
||||
contentTypeString << "Content-Type: " << contentType;
|
||||
|
||||
struct curl_slist *list = NULL;
|
||||
list = curl_slist_append(list, contentTypeString.str().c_str());
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
|
||||
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
|
||||
curl_easy_setopt(curl, CURLOPT_USERAGENT, m_userAgents[rand() % m_userAgents.size()].c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list);
|
||||
curl_easy_setopt(curl, CURLOPT_POST, 1);
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postData.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, postData.size());
|
||||
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &WriteCallback);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);
|
||||
|
||||
int code = 0;
|
||||
curl_easy_perform(curl);
|
||||
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code);
|
||||
curl_easy_cleanup(curl);
|
||||
|
||||
if (code != 200)
|
||||
{
|
||||
std::stringstream error;
|
||||
error << "Error (" << code << ") encountered while retrieving " << url << "\n";
|
||||
error << "Data: " << buffer;
|
||||
throw std::runtime_error(error.str());
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void HttpClient::GetUrlPostSilent(const std::string& url, const std::string& postData, const std::string& contentType) const
|
||||
{
|
||||
CURL* curl = curl_easy_init();
|
||||
|
||||
std::stringstream contentTypeString;
|
||||
contentTypeString << "Content-Type: " << contentType;
|
||||
|
||||
struct curl_slist *list = NULL;
|
||||
list = curl_slist_append(list, contentTypeString.str().c_str());
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
|
||||
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
|
||||
curl_easy_setopt(curl, CURLOPT_USERAGENT, m_userAgents[rand() % m_userAgents.size()].c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list);
|
||||
curl_easy_setopt(curl, CURLOPT_POST, 1);
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postData.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, postData.size());
|
||||
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &WriteCallback);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, nullptr);
|
||||
|
||||
int code = 0;
|
||||
curl_easy_perform(curl);
|
||||
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code);
|
||||
curl_easy_cleanup(curl);
|
||||
|
||||
if (code != 200)
|
||||
{
|
||||
std::stringstream error;
|
||||
error << "Error (" << code << ") encountered while retrieving " << url << "\n";
|
||||
throw std::runtime_error(error.str());
|
||||
}
|
||||
}
|
||||
|
||||
std::string HttpClient::GetUrlPostContents(const std::string& url, const std::string& cookieFile, const std::string& postData, const std::string& contentType) const
|
||||
{
|
||||
std::string buffer;
|
||||
|
||||
CURL* curl = curl_easy_init();
|
||||
|
||||
std::stringstream contentTypeString;
|
||||
contentTypeString << "Content-Type: " << contentType;
|
||||
|
||||
struct curl_slist *list = NULL;
|
||||
list = curl_slist_append(list, contentTypeString.str().c_str());
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
|
||||
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
|
||||
curl_easy_setopt(curl, CURLOPT_USERAGENT, m_userAgents[rand() % m_userAgents.size()].c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list);
|
||||
curl_easy_setopt(curl, CURLOPT_POST, 1);
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postData.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, postData.size());
|
||||
curl_easy_setopt(curl, CURLOPT_COOKIEFILE, cookieFile.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_COOKIEJAR, cookieFile.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &WriteCallback);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);
|
||||
|
||||
int code = 0;
|
||||
curl_easy_perform(curl);
|
||||
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code);
|
||||
curl_easy_cleanup(curl);
|
||||
|
||||
if (code != 200)
|
||||
{
|
||||
std::stringstream error;
|
||||
error << "Error (" << code << ") encountered while retrieving " << url << "\n";
|
||||
error << "Data: " << buffer;
|
||||
throw std::runtime_error(error.str());
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void HttpClient::GetUrlPostSilent(const std::string& url, const std::string& cookieFile, const std::string& postData, const std::string& contentType) const
|
||||
{
|
||||
CURL* curl = curl_easy_init();
|
||||
|
||||
std::stringstream contentTypeString;
|
||||
contentTypeString << "Content-Type: " << contentType;
|
||||
|
||||
struct curl_slist *list = NULL;
|
||||
list = curl_slist_append(list, contentTypeString.str().c_str());
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
|
||||
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
|
||||
curl_easy_setopt(curl, CURLOPT_USERAGENT, m_userAgents[rand() % m_userAgents.size()].c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list);
|
||||
curl_easy_setopt(curl, CURLOPT_POST, 1);
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postData.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, postData.size());
|
||||
curl_easy_setopt(curl, CURLOPT_COOKIEFILE, cookieFile.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_COOKIEJAR, cookieFile.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &WriteCallback);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, nullptr);
|
||||
|
||||
int code = 0;
|
||||
curl_easy_perform(curl);
|
||||
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code);
|
||||
curl_easy_cleanup(curl);
|
||||
|
||||
if (code != 200)
|
||||
{
|
||||
std::stringstream error;
|
||||
error << "Error (" << code << ") encountered while retrieving " << url << "\n";
|
||||
throw std::runtime_error(error.str());
|
||||
}
|
||||
}
|
||||
|
||||
std::string HttpClient::GetUrlPostAttachmentContents(const std::string& url, const std::string& postData, const std::string& filename, const std::string& fileFieldname) const
|
||||
{
|
||||
std::string buffer;
|
||||
std::string contents;
|
||||
std::ifstream fileStream(filename, std::ios::in | std::ios::binary);
|
||||
|
||||
if (fileStream)
|
||||
{
|
||||
fileStream.seekg(0, std::ios::end);
|
||||
contents.resize(fileStream.tellg());
|
||||
fileStream.seekg(0, std::ios::beg);
|
||||
fileStream.read(&contents[0], contents.size());
|
||||
fileStream.close();
|
||||
}
|
||||
|
||||
CURL* curl = curl_easy_init();
|
||||
CURLcode result;
|
||||
|
||||
struct curl_httppost *formpost = nullptr;
|
||||
struct curl_httppost *lastptr = nullptr;
|
||||
struct curl_slist *headerlist = nullptr;
|
||||
static const char headerBuffer[] = "Expect:";
|
||||
|
||||
curl_global_init(CURL_GLOBAL_ALL);
|
||||
|
||||
curl_formadd(&formpost, &lastptr,
|
||||
CURLFORM_COPYNAME, "cache-control:",
|
||||
CURLFORM_COPYCONTENTS, "no-cache",
|
||||
CURLFORM_END);
|
||||
|
||||
curl_formadd(&formpost, &lastptr,
|
||||
CURLFORM_COPYNAME, "content-type:",
|
||||
CURLFORM_COPYCONTENTS, "multipart/form-data",
|
||||
CURLFORM_END);
|
||||
|
||||
std::vector<std::string> postTokens;
|
||||
boost::split(postTokens, postData, boost::is_any_of("&"));
|
||||
|
||||
for (std::vector<std::string>::iterator it = postTokens.begin(); it != postTokens.end(); ++it)
|
||||
{
|
||||
std::vector<std::string> tokens;
|
||||
boost::split(tokens, *it, boost::is_any_of("="));
|
||||
|
||||
curl_formadd(&formpost, &lastptr,
|
||||
CURLFORM_COPYNAME, tokens[0].c_str(),
|
||||
CURLFORM_COPYCONTENTS, tokens[1].c_str(),
|
||||
CURLFORM_END);
|
||||
}
|
||||
|
||||
curl_formadd(&formpost, &lastptr,
|
||||
CURLFORM_COPYNAME, fileFieldname.c_str(),
|
||||
CURLFORM_BUFFER, "data",
|
||||
CURLFORM_BUFFERPTR, contents.data(),
|
||||
CURLFORM_BUFFERLENGTH, contents.size(),
|
||||
CURLFORM_END);
|
||||
|
||||
headerlist = curl_slist_append(headerlist, headerBuffer);
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &WriteCallback);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);
|
||||
|
||||
int code = 0;
|
||||
curl_easy_perform(curl);
|
||||
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code);
|
||||
curl_easy_cleanup(curl);
|
||||
curl_formfree(formpost);
|
||||
curl_slist_free_all(headerlist);
|
||||
|
||||
if (code != 200)
|
||||
{
|
||||
std::stringstream error;
|
||||
error << "Error (" << code << ") encountered while retrieving " << url << "\n";
|
||||
error << "Data: " << buffer;
|
||||
throw std::runtime_error(error.str());
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void HttpClient::GetUrlPostAttachmentSilent(const std::string& url, const std::string& postData, const std::string& filename, const std::string& fileFieldname) const
|
||||
{
|
||||
std::string contents;
|
||||
std::ifstream fileStream(filename, std::ios::in | std::ios::binary);
|
||||
|
||||
if (fileStream)
|
||||
{
|
||||
fileStream.seekg(0, std::ios::end);
|
||||
contents.resize(fileStream.tellg());
|
||||
fileStream.seekg(0, std::ios::beg);
|
||||
fileStream.read(&contents[0], contents.size());
|
||||
fileStream.close();
|
||||
}
|
||||
|
||||
CURL* curl = curl_easy_init();
|
||||
CURLcode result;
|
||||
|
||||
struct curl_httppost *formpost = nullptr;
|
||||
struct curl_httppost *lastptr = nullptr;
|
||||
struct curl_slist *headerlist = nullptr;
|
||||
static const char headerBuffer[] = "Expect:";
|
||||
|
||||
curl_global_init(CURL_GLOBAL_ALL);
|
||||
|
||||
curl_formadd(&formpost, &lastptr,
|
||||
CURLFORM_COPYNAME, "cache-control:",
|
||||
CURLFORM_COPYCONTENTS, "no-cache",
|
||||
CURLFORM_END);
|
||||
|
||||
curl_formadd(&formpost, &lastptr,
|
||||
CURLFORM_COPYNAME, "content-type:",
|
||||
CURLFORM_COPYCONTENTS, "multipart/form-data",
|
||||
CURLFORM_END);
|
||||
|
||||
std::vector<std::string> postTokens;
|
||||
boost::split(postTokens, postData, boost::is_any_of("&"));
|
||||
|
||||
for (std::vector<std::string>::iterator it = postTokens.begin(); it != postTokens.end(); ++it)
|
||||
{
|
||||
std::vector<std::string> tokens;
|
||||
boost::split(tokens, *it, boost::is_any_of("="));
|
||||
|
||||
curl_formadd(&formpost, &lastptr,
|
||||
CURLFORM_COPYNAME, tokens[0].c_str(),
|
||||
CURLFORM_COPYCONTENTS, tokens[1].c_str(),
|
||||
CURLFORM_END);
|
||||
}
|
||||
|
||||
curl_formadd(&formpost, &lastptr,
|
||||
CURLFORM_COPYNAME, fileFieldname.c_str(),
|
||||
CURLFORM_BUFFER, "data",
|
||||
CURLFORM_BUFFERPTR, contents.data(),
|
||||
CURLFORM_BUFFERLENGTH, contents.size(),
|
||||
CURLFORM_END);
|
||||
|
||||
headerlist = curl_slist_append(headerlist, headerBuffer);
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
|
||||
|
||||
int code = 0;
|
||||
curl_easy_perform(curl);
|
||||
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code);
|
||||
curl_easy_cleanup(curl);
|
||||
curl_formfree(formpost);
|
||||
curl_slist_free_all(headerlist);
|
||||
|
||||
if (code != 200)
|
||||
{
|
||||
std::stringstream error;
|
||||
error << "Error (" << code << ") encountered while retrieving " << url << "\n";
|
||||
throw std::runtime_error(error.str());
|
||||
}
|
||||
}
|
||||
|
||||
std::string HttpClient::GetUrlPostAttachmentContents(const std::string& url, const std::string& cookieFile, const std::string& postData, const std::string& filename, const std::string& fileFieldname) const
|
||||
{
|
||||
std::string buffer;
|
||||
std::string contents;
|
||||
std::ifstream fileStream(filename, std::ios::in | std::ios::binary);
|
||||
|
||||
if (fileStream)
|
||||
{
|
||||
fileStream.seekg(0, std::ios::end);
|
||||
contents.resize(fileStream.tellg());
|
||||
fileStream.seekg(0, std::ios::beg);
|
||||
fileStream.read(&contents[0], contents.size());
|
||||
fileStream.close();
|
||||
}
|
||||
|
||||
CURL* curl = curl_easy_init();
|
||||
CURLcode result;
|
||||
|
||||
struct curl_httppost *formpost = nullptr;
|
||||
struct curl_httppost *lastptr = nullptr;
|
||||
struct curl_slist *headerlist = nullptr;
|
||||
static const char headerBuffer[] = "Expect:";
|
||||
|
||||
curl_global_init(CURL_GLOBAL_ALL);
|
||||
|
||||
curl_formadd(&formpost, &lastptr,
|
||||
CURLFORM_COPYNAME, "cache-control:",
|
||||
CURLFORM_COPYCONTENTS, "no-cache",
|
||||
CURLFORM_END);
|
||||
|
||||
curl_formadd(&formpost, &lastptr,
|
||||
CURLFORM_COPYNAME, "content-type:",
|
||||
CURLFORM_COPYCONTENTS, "multipart/form-data",
|
||||
CURLFORM_END);
|
||||
|
||||
std::vector<std::string> postTokens;
|
||||
boost::split(postTokens, postData, boost::is_any_of("&"));
|
||||
|
||||
for (std::vector<std::string>::iterator it = postTokens.begin(); it != postTokens.end(); ++it)
|
||||
{
|
||||
std::vector<std::string> tokens;
|
||||
boost::split(tokens, *it, boost::is_any_of("="));
|
||||
|
||||
curl_formadd(&formpost, &lastptr,
|
||||
CURLFORM_COPYNAME, tokens[0].c_str(),
|
||||
CURLFORM_COPYCONTENTS, tokens[1].c_str(),
|
||||
CURLFORM_END);
|
||||
}
|
||||
|
||||
curl_formadd(&formpost, &lastptr,
|
||||
CURLFORM_COPYNAME, fileFieldname.c_str(),
|
||||
CURLFORM_BUFFER, "data",
|
||||
CURLFORM_BUFFERPTR, contents.data(),
|
||||
CURLFORM_BUFFERLENGTH, contents.size(),
|
||||
CURLFORM_END);
|
||||
|
||||
headerlist = curl_slist_append(headerlist, headerBuffer);
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
|
||||
curl_easy_setopt(curl, CURLOPT_COOKIEFILE, cookieFile.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_COOKIEJAR, cookieFile.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &WriteCallback);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);
|
||||
|
||||
int code = 0;
|
||||
curl_easy_perform(curl);
|
||||
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code);
|
||||
curl_easy_cleanup(curl);
|
||||
curl_formfree(formpost);
|
||||
curl_slist_free_all(headerlist);
|
||||
|
||||
if (code != 200)
|
||||
{
|
||||
std::stringstream error;
|
||||
error << "Error (" << code << ") encountered while retrieving " << url << "\n";
|
||||
error << "Data: " << buffer;
|
||||
throw std::runtime_error(error.str());
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void HttpClient::GetUrlPostAttachmentSilent(const std::string& url, const std::string& cookieFile, const std::string& postData, const std::string& filename, const std::string& fileFieldname) const
|
||||
{
|
||||
std::string contents;
|
||||
std::ifstream fileStream(filename, std::ios::in | std::ios::binary);
|
||||
|
||||
if (fileStream)
|
||||
{
|
||||
fileStream.seekg(0, std::ios::end);
|
||||
contents.resize(fileStream.tellg());
|
||||
fileStream.seekg(0, std::ios::beg);
|
||||
fileStream.read(&contents[0], contents.size());
|
||||
fileStream.close();
|
||||
}
|
||||
|
||||
CURL* curl = curl_easy_init();
|
||||
CURLcode result;
|
||||
|
||||
struct curl_httppost *formpost = nullptr;
|
||||
struct curl_httppost *lastptr = nullptr;
|
||||
struct curl_slist *headerlist = nullptr;
|
||||
static const char headerBuffer[] = "Expect:";
|
||||
|
||||
curl_global_init(CURL_GLOBAL_ALL);
|
||||
|
||||
curl_formadd(&formpost, &lastptr,
|
||||
CURLFORM_COPYNAME, "cache-control:",
|
||||
CURLFORM_COPYCONTENTS, "no-cache",
|
||||
CURLFORM_END);
|
||||
|
||||
curl_formadd(&formpost, &lastptr,
|
||||
CURLFORM_COPYNAME, "content-type:",
|
||||
CURLFORM_COPYCONTENTS, "multipart/form-data",
|
||||
CURLFORM_END);
|
||||
|
||||
std::vector<std::string> postTokens;
|
||||
boost::split(postTokens, postData, boost::is_any_of("&"));
|
||||
|
||||
for (std::vector<std::string>::iterator it = postTokens.begin(); it != postTokens.end(); ++it)
|
||||
{
|
||||
std::vector<std::string> tokens;
|
||||
boost::split(tokens, *it, boost::is_any_of("="));
|
||||
|
||||
curl_formadd(&formpost, &lastptr,
|
||||
CURLFORM_COPYNAME, tokens[0].c_str(),
|
||||
CURLFORM_COPYCONTENTS, tokens[1].c_str(),
|
||||
CURLFORM_END);
|
||||
}
|
||||
|
||||
curl_formadd(&formpost, &lastptr,
|
||||
CURLFORM_COPYNAME, fileFieldname.c_str(),
|
||||
CURLFORM_BUFFER, "data",
|
||||
CURLFORM_BUFFERPTR, contents.data(),
|
||||
CURLFORM_BUFFERLENGTH, contents.size(),
|
||||
CURLFORM_END);
|
||||
|
||||
headerlist = curl_slist_append(headerlist, headerBuffer);
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
|
||||
curl_easy_setopt(curl, CURLOPT_COOKIEFILE, cookieFile.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_COOKIEJAR, cookieFile.c_str());
|
||||
|
||||
int code = 0;
|
||||
curl_easy_perform(curl);
|
||||
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code);
|
||||
curl_easy_cleanup(curl);
|
||||
curl_formfree(formpost);
|
||||
curl_slist_free_all(headerlist);
|
||||
|
||||
if (code != 200)
|
||||
{
|
||||
std::stringstream error;
|
||||
error << "Error (" << code << ") encountered while retrieving " << url << "\n";
|
||||
throw std::runtime_error(error.str());
|
||||
}
|
||||
}
|
||||
|
||||
size_t HttpClient::WriteCallback(char* data, size_t size, size_t nmemb, std::string* writerData)
|
||||
{
|
||||
if (writerData == nullptr)
|
||||
return size * nmemb;
|
||||
|
||||
writerData->append(data, size * nmemb);
|
||||
return size * nmemb;
|
||||
}
|
||||
|
||||
} // namespace Util
|
||||
} // namespace PresenceDetection
|
||||
@@ -1,42 +0,0 @@
|
||||
#ifndef UTIL_HTTPCLIENT_H
|
||||
#define UTIL_HTTPCLIENT_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace PresenceDetection {
|
||||
namespace Util {
|
||||
|
||||
class HttpClient
|
||||
{
|
||||
public:
|
||||
HttpClient();
|
||||
~HttpClient();
|
||||
|
||||
HttpClient(const HttpClient&) = delete;
|
||||
|
||||
std::string GetUrlContents(const std::string& url) const;
|
||||
void GetUrlSilent(const std::string& url) const;
|
||||
std::string GetUrlContents(const std::string& url, const std::string& cookieFile) const;
|
||||
void GetUrlSilent(const std::string& url, const std::string& cookieFile) const;
|
||||
std::string GetUrlPostContents(const std::string& url, const std::string& postData, const std::string& contentType) const;
|
||||
void GetUrlPostSilent(const std::string& url, const std::string& postData, const std::string& contentType) const;
|
||||
std::string GetUrlPostContents(const std::string& url, const std::string& cookieFile, const std::string& postData, const std::string& contentType) const;
|
||||
void GetUrlPostSilent(const std::string& url, const std::string& cookieFile, const std::string& postData, const std::string& contentType) const;
|
||||
std::string GetUrlPostAttachmentContents(const std::string& url, const std::string& postData, const std::string& filename, const std::string& fileFieldname) const;
|
||||
void GetUrlPostAttachmentSilent(const std::string& url, const std::string& postData, const std::string& filename, const std::string& fileFieldname) const;
|
||||
std::string GetUrlPostAttachmentContents(const std::string& url, const std::string& cookieFile, const std::string& postData, const std::string& filename, const std::string& fileFieldname) const;
|
||||
void GetUrlPostAttachmentSilent(const std::string& url, const std::string& cookieFile, const std::string& postData, const std::string& filename, const std::string& fileFieldname) const;
|
||||
|
||||
private:
|
||||
static size_t WriteCallback(char* data, size_t size, size_t nmemb, std::string* writerData);
|
||||
|
||||
private:
|
||||
std::vector<std::string> m_userAgents;
|
||||
};
|
||||
|
||||
} // namespace Util
|
||||
} // namespace PresenceDetection
|
||||
|
||||
#endif // UTIL_HTTPCLIENT_H
|
||||
@@ -1,45 +0,0 @@
|
||||
#ifndef UTIL_HTTPCLIENTHELPERS_H
|
||||
#define UTIL_HTTPCLIENTHELPERS_H
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/thread.hpp>
|
||||
#include <openssl/crypto.h>
|
||||
|
||||
|
||||
namespace PresenceDetection {
|
||||
namespace Util {
|
||||
|
||||
static std::vector<boost::shared_ptr<boost::mutex> > g_mutexes;
|
||||
|
||||
static void LockCallback(int mode, int type, const char* /*file*/, int /*line*/)
|
||||
{
|
||||
if (mode & CRYPTO_LOCK)
|
||||
g_mutexes[type]->lock();
|
||||
else
|
||||
g_mutexes[type]->unlock();
|
||||
}
|
||||
|
||||
static unsigned long ThreadId(void)
|
||||
{
|
||||
return (unsigned long)pthread_self();
|
||||
}
|
||||
|
||||
static void InitializeLocks(void)
|
||||
{
|
||||
g_mutexes.resize(CRYPTO_num_locks());
|
||||
for (int i = 0; i < CRYPTO_num_locks(); ++i)
|
||||
g_mutexes[i] = boost::shared_ptr<boost::mutex>(new boost::mutex());
|
||||
|
||||
CRYPTO_set_id_callback(ThreadId);
|
||||
CRYPTO_set_locking_callback(LockCallback);
|
||||
}
|
||||
|
||||
static void FreeLocks(void)
|
||||
{
|
||||
CRYPTO_set_locking_callback(NULL);
|
||||
}
|
||||
|
||||
} // namespace Util
|
||||
} // namespace PresenceDetection
|
||||
|
||||
#endif // UTIL_HTTPCLIENTHELPERS_H
|
||||
-16
@@ -1,16 +0,0 @@
|
||||
#ifndef UTIL_JSON_H
|
||||
#define UTIL_JSON_H
|
||||
|
||||
#include "Libraries/JSON/nlohmann/json.hpp"
|
||||
|
||||
|
||||
namespace PresenceDetection {
|
||||
namespace Util {
|
||||
|
||||
using namespace nlohmann;
|
||||
typedef json JSON;
|
||||
|
||||
} // namespace Util
|
||||
} // namespace DomoticaServer
|
||||
|
||||
#endif // UTIL_JSON_H
|
||||
@@ -0,0 +1,21 @@
|
||||
#ifndef UTIL_PROBEABLEDEVICE_H
|
||||
#define UTIL_PROBEABLEDEVICE_H
|
||||
|
||||
#include <string>
|
||||
|
||||
|
||||
namespace PresenceDetection {
|
||||
namespace Util {
|
||||
|
||||
class ProbeableDevice
|
||||
{
|
||||
public:
|
||||
virtual int ProbeCounter() const = 0;
|
||||
virtual void IncrementProbeCounter() = 0;
|
||||
virtual void ResetProbeCounter() = 0;
|
||||
};
|
||||
|
||||
} // namespace Util
|
||||
} // namespace PresenceDetection
|
||||
|
||||
#endif // UTIL_PROBEABLEDEVICE_H
|
||||
@@ -0,0 +1,184 @@
|
||||
#include "StaticDevice.h"
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
namespace PresenceDetection {
|
||||
namespace Util {
|
||||
|
||||
StaticDevice::StaticDevice(const std::string& wifiMac, const std::string& bluetoothMac) :
|
||||
m_probeCounter(0),
|
||||
m_wifiMac(wifiMac),
|
||||
m_wifiState(false),
|
||||
m_bluetoothMac(bluetoothMac),
|
||||
m_bluetoothState(false)
|
||||
{
|
||||
std::transform(m_wifiMac.begin(), m_wifiMac.end(), m_wifiMac.begin(), ::tolower);
|
||||
std::transform(m_bluetoothMac.begin(), m_bluetoothMac.end(), m_bluetoothMac.begin(), ::tolower);
|
||||
}
|
||||
|
||||
StaticDevice::StaticDevice(const StaticDevice &other) :
|
||||
m_probeCounter(other.m_probeCounter),
|
||||
m_wifiMac(other.m_wifiMac),
|
||||
m_wifiState(other.m_wifiState),
|
||||
m_bluetoothMac(other.m_bluetoothMac),
|
||||
m_bluetoothState(other.m_bluetoothState),
|
||||
m_onlineURL(other.m_onlineURL),
|
||||
m_wifiOnlineURL(other.m_wifiOnlineURL),
|
||||
m_bluetoothOnlineURL(other.m_bluetoothOnlineURL),
|
||||
m_offlineURL(other.m_offlineURL),
|
||||
m_wifiOfflineURL(other.m_wifiOfflineURL),
|
||||
m_bluetoothOfflineURL(other.m_bluetoothOfflineURL)
|
||||
{
|
||||
}
|
||||
|
||||
StaticDevice::~StaticDevice()
|
||||
{
|
||||
}
|
||||
|
||||
int StaticDevice::ProbeCounter() const
|
||||
{
|
||||
return m_probeCounter;
|
||||
}
|
||||
|
||||
void StaticDevice::IncrementProbeCounter()
|
||||
{
|
||||
++m_probeCounter;
|
||||
}
|
||||
|
||||
void StaticDevice::ResetProbeCounter()
|
||||
{
|
||||
m_probeCounter = 0;
|
||||
}
|
||||
|
||||
bool StaticDevice::HasWifiMac() const
|
||||
{
|
||||
return !m_wifiMac.empty();
|
||||
}
|
||||
|
||||
std::string StaticDevice::WifiMac() const
|
||||
{
|
||||
return m_wifiMac;
|
||||
}
|
||||
|
||||
void StaticDevice::SetWifiState(bool present)
|
||||
{
|
||||
m_wifiState = present;
|
||||
}
|
||||
|
||||
bool StaticDevice::GetWifiState() const
|
||||
{
|
||||
return m_wifiState;
|
||||
}
|
||||
|
||||
bool StaticDevice::HasBluetoothMac() const
|
||||
{
|
||||
return !m_bluetoothMac.empty();
|
||||
}
|
||||
|
||||
std::string StaticDevice::BluetoothMac() const
|
||||
{
|
||||
return m_bluetoothMac;
|
||||
}
|
||||
|
||||
void StaticDevice::SetBluetoothState(bool present)
|
||||
{
|
||||
m_bluetoothState = present;
|
||||
}
|
||||
|
||||
bool StaticDevice::GetBluetoothState() const
|
||||
{
|
||||
return m_bluetoothState;
|
||||
}
|
||||
|
||||
bool StaticDevice::HasOnlineURL() const
|
||||
{
|
||||
return !m_onlineURL.empty();
|
||||
}
|
||||
|
||||
void StaticDevice::SetOnlineURL(const std::string& url)
|
||||
{
|
||||
m_onlineURL = url;
|
||||
}
|
||||
|
||||
std::string StaticDevice::OnlineURL() const
|
||||
{
|
||||
return m_onlineURL;
|
||||
}
|
||||
|
||||
bool StaticDevice::HasWifiOnlineURL() const
|
||||
{
|
||||
return !m_wifiOnlineURL.empty();
|
||||
}
|
||||
|
||||
void StaticDevice::SetWifiOnlineURL(const std::string& url)
|
||||
{
|
||||
m_wifiOnlineURL = url;
|
||||
}
|
||||
|
||||
std::string StaticDevice::WifiOnlineURL() const
|
||||
{
|
||||
return m_wifiOnlineURL;
|
||||
}
|
||||
|
||||
bool StaticDevice::HasBluetoothOnlineURL() const
|
||||
{
|
||||
return !m_bluetoothOnlineURL.empty();
|
||||
}
|
||||
|
||||
void StaticDevice::SetBluetoothOnlineURL(const std::string& url)
|
||||
{
|
||||
m_bluetoothOnlineURL = url;
|
||||
}
|
||||
|
||||
std::string StaticDevice::BluetoothOnlineURL() const
|
||||
{
|
||||
return m_bluetoothOnlineURL;
|
||||
}
|
||||
|
||||
bool StaticDevice::HasOfflineURL() const
|
||||
{
|
||||
return !m_offlineURL.empty();
|
||||
}
|
||||
|
||||
void StaticDevice::SetOfflineURL(const std::string& url)
|
||||
{
|
||||
m_offlineURL = url;
|
||||
}
|
||||
|
||||
std::string StaticDevice::OfflineURL() const
|
||||
{
|
||||
return m_offlineURL;
|
||||
}
|
||||
|
||||
bool StaticDevice::HasWifiOfflineURL() const
|
||||
{
|
||||
return !m_wifiOfflineURL.empty();
|
||||
}
|
||||
|
||||
void StaticDevice::SetWifiOfflineURL(const std::string& url)
|
||||
{
|
||||
m_wifiOfflineURL = url;
|
||||
}
|
||||
|
||||
std::string StaticDevice::WifiOfflineURL() const
|
||||
{
|
||||
return m_wifiOfflineURL;
|
||||
}
|
||||
|
||||
bool StaticDevice::HasBluetoothOfflineURL() const
|
||||
{
|
||||
return !m_bluetoothOfflineURL.empty();
|
||||
}
|
||||
|
||||
void StaticDevice::SetBluetoothOfflineURL(const std::string& url)
|
||||
{
|
||||
m_bluetoothOfflineURL = url;
|
||||
}
|
||||
|
||||
std::string StaticDevice::BluetoothOfflineURL() const
|
||||
{
|
||||
return m_bluetoothOfflineURL;
|
||||
}
|
||||
|
||||
} // namespace Util
|
||||
} // namespace PresenceDetection
|
||||
@@ -0,0 +1,72 @@
|
||||
#ifndef UTIL_STATICDEVICE_H
|
||||
#define UTIL_STATICDEVICE_H
|
||||
|
||||
#include "ProbeableDevice.h"
|
||||
#include <string>
|
||||
|
||||
|
||||
namespace PresenceDetection {
|
||||
namespace Util {
|
||||
|
||||
class StaticDevice : public ProbeableDevice
|
||||
{
|
||||
public:
|
||||
StaticDevice(const std::string& wifiMac, const std::string& bluetoothMac);
|
||||
StaticDevice(const StaticDevice &other);
|
||||
~StaticDevice();
|
||||
|
||||
virtual int ProbeCounter() const override;
|
||||
virtual void IncrementProbeCounter() override;
|
||||
virtual void ResetProbeCounter() override;
|
||||
|
||||
bool HasWifiMac() const;
|
||||
std::string WifiMac() const;
|
||||
void SetWifiState(bool present);
|
||||
bool GetWifiState() const;
|
||||
|
||||
bool HasBluetoothMac() const;
|
||||
std::string BluetoothMac() const;
|
||||
void SetBluetoothState(bool present);
|
||||
bool GetBluetoothState() const;
|
||||
|
||||
bool HasOnlineURL() const;
|
||||
void SetOnlineURL(const std::string& url);
|
||||
std::string OnlineURL() const;
|
||||
bool HasWifiOnlineURL() const;
|
||||
void SetWifiOnlineURL(const std::string& url);
|
||||
std::string WifiOnlineURL() const;
|
||||
bool HasBluetoothOnlineURL() const;
|
||||
void SetBluetoothOnlineURL(const std::string& url);
|
||||
std::string BluetoothOnlineURL() const;
|
||||
|
||||
bool HasOfflineURL() const;
|
||||
void SetOfflineURL(const std::string& url);
|
||||
std::string OfflineURL() const;
|
||||
bool HasWifiOfflineURL() const;
|
||||
void SetWifiOfflineURL(const std::string& url);
|
||||
std::string WifiOfflineURL() const;
|
||||
bool HasBluetoothOfflineURL() const;
|
||||
void SetBluetoothOfflineURL(const std::string& url);
|
||||
std::string BluetoothOfflineURL() const;
|
||||
|
||||
private:
|
||||
int m_probeCounter;
|
||||
|
||||
std::string m_wifiMac;
|
||||
bool m_wifiState;
|
||||
|
||||
std::string m_bluetoothMac;
|
||||
bool m_bluetoothState;
|
||||
|
||||
std::string m_onlineURL;
|
||||
std::string m_wifiOnlineURL;
|
||||
std::string m_bluetoothOnlineURL;
|
||||
std::string m_offlineURL;
|
||||
std::string m_wifiOfflineURL;
|
||||
std::string m_bluetoothOfflineURL;
|
||||
};
|
||||
|
||||
} // namespace Util
|
||||
} // namespace PresenceDetection
|
||||
|
||||
#endif // UTIL_STATICDEVICE_H
|
||||
@@ -1,87 +0,0 @@
|
||||
#include <iostream>
|
||||
|
||||
#include <chrono>
|
||||
#include "Util.h"
|
||||
#include "Timer.h"
|
||||
|
||||
|
||||
namespace PresenceDetection {
|
||||
namespace Util {
|
||||
|
||||
Timer::Timer() :
|
||||
m_run(false),
|
||||
m_aborted(false),
|
||||
m_identifier(CreateRandomString(10))
|
||||
{
|
||||
}
|
||||
|
||||
Timer::~Timer()
|
||||
{
|
||||
Abort();
|
||||
Wait();
|
||||
}
|
||||
|
||||
Timer::Timer(Timer&& other) :
|
||||
m_run(static_cast<bool>(other.m_run)),
|
||||
m_identifier(other.m_identifier),
|
||||
m_thread(std::move(other.m_thread))
|
||||
{
|
||||
}
|
||||
|
||||
Timer& Timer::operator=(Timer&& other)
|
||||
{
|
||||
m_run = static_cast<bool>(other.m_run);
|
||||
m_identifier = std::move(other.m_identifier);
|
||||
m_thread = std::move(other.m_thread);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool Timer::operator==(const Timer& other) const
|
||||
{
|
||||
return m_identifier == other.Identifier();
|
||||
}
|
||||
|
||||
bool Timer::operator==(const std::string& identifier) const
|
||||
{
|
||||
return m_identifier == identifier;
|
||||
}
|
||||
|
||||
bool Timer::operator==(bool running) const
|
||||
{
|
||||
return IsRunning() == running;
|
||||
}
|
||||
|
||||
std::string Timer::Identifier() const
|
||||
{
|
||||
return m_identifier;
|
||||
}
|
||||
|
||||
void Timer::Stop()
|
||||
{
|
||||
m_run.store(false, std::memory_order_release);
|
||||
}
|
||||
|
||||
void Timer::Abort()
|
||||
{
|
||||
std::cout << "Timer::Abort()" << std::endl;
|
||||
m_run.store(false, std::memory_order_release);
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
m_aborted = true;
|
||||
}
|
||||
m_conditionVariable.notify_all();
|
||||
}
|
||||
|
||||
bool Timer::IsRunning() const noexcept
|
||||
{
|
||||
return (m_run.load(std::memory_order_acquire) && m_thread.joinable());
|
||||
}
|
||||
|
||||
void Timer::Wait()
|
||||
{
|
||||
if (m_thread.joinable())
|
||||
m_thread.join();
|
||||
}
|
||||
|
||||
} // namespace Util
|
||||
} // namespace PresenceDetection
|
||||
-108
@@ -1,108 +0,0 @@
|
||||
#ifndef UTIL_TIMER_H
|
||||
#define UTIL_TIMER_H
|
||||
|
||||
#include <atomic>
|
||||
#include <condition_variable>
|
||||
#include <functional>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
#include "Helpers.h"
|
||||
|
||||
|
||||
namespace PresenceDetection {
|
||||
namespace Util {
|
||||
|
||||
class Timer
|
||||
{
|
||||
public:
|
||||
Timer();
|
||||
~Timer();
|
||||
|
||||
Timer(const Timer&) = delete;
|
||||
Timer& operator= (const Timer&) = delete;
|
||||
|
||||
Timer(Timer&& other);
|
||||
Timer& operator= (Timer&& other);
|
||||
|
||||
bool operator==(const Timer& other) const;
|
||||
bool operator==(const std::string& identifier) const;
|
||||
bool operator==(bool running) const;
|
||||
|
||||
public:
|
||||
std::string Identifier() const;
|
||||
|
||||
template <typename ...FunctionArguments, typename ...Arguments>
|
||||
void StartSingle(int milliSeconds, std::function<void(FunctionArguments...)> const & function, Arguments && ...arguments)
|
||||
{
|
||||
Start(TimerType::Single, milliSeconds, function, std::forward<Arguments>(arguments)...);
|
||||
}
|
||||
|
||||
template <typename ...FunctionArguments, typename ...Arguments>
|
||||
void StartContinuous(int milliSeconds, std::function<void(FunctionArguments...)> const & function, Arguments && ...arguments)
|
||||
{
|
||||
Start(TimerType::Continuous, milliSeconds, function, std::forward<Arguments>(arguments)...);
|
||||
}
|
||||
|
||||
void Stop();
|
||||
void Abort();
|
||||
bool IsRunning() const noexcept;
|
||||
void Wait();
|
||||
|
||||
private:
|
||||
class TimerType
|
||||
{
|
||||
public:
|
||||
enum type
|
||||
{
|
||||
Unknown,
|
||||
Single,
|
||||
Continuous
|
||||
};
|
||||
};
|
||||
|
||||
private:
|
||||
template <typename ...FunctionArguments, typename ...Arguments>
|
||||
void Start(TimerType::type type, int milliSeconds, std::function<void(FunctionArguments...)> const & function, Arguments && ...arguments)
|
||||
{
|
||||
if (type == TimerType::Unknown)
|
||||
return;
|
||||
|
||||
if (m_run.load(std::memory_order_acquire))
|
||||
Stop();
|
||||
|
||||
m_thread = std::thread([this, type, milliSeconds, function, &arguments...]()
|
||||
{
|
||||
auto argumentsCopy = std::make_tuple(std::forward<Arguments>(arguments)...);
|
||||
m_run.store(true, std::memory_order_release);
|
||||
m_aborted = false;
|
||||
|
||||
while (m_run.load(std::memory_order_acquire))
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
if (!m_conditionVariable.wait_for(lock, std::chrono::milliseconds(milliSeconds), [&]{return m_aborted;}))
|
||||
{
|
||||
Helpers::execute(function, argumentsCopy);
|
||||
if (type == TimerType::Single)
|
||||
m_run.store(false, std::memory_order_release);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
while (!IsRunning())
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::atomic<bool> m_run;
|
||||
bool m_aborted;
|
||||
std::mutex m_mutex;
|
||||
std::condition_variable m_conditionVariable;
|
||||
std::string m_identifier;
|
||||
std::thread m_thread;
|
||||
};
|
||||
|
||||
} // namespace Util
|
||||
} // namespace PresenceDetection
|
||||
|
||||
#endif // UTIL_TIMER_H
|
||||
@@ -1,25 +0,0 @@
|
||||
#include <algorithm>
|
||||
#include "Util.h"
|
||||
|
||||
|
||||
namespace PresenceDetection {
|
||||
namespace Util {
|
||||
|
||||
std::string CreateRandomString(size_t length)
|
||||
{
|
||||
auto randchar = []() -> char
|
||||
{
|
||||
const char charset[] =
|
||||
"0123456789"
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"abcdefghijklmnopqrstuvwxyz";
|
||||
const size_t max_index = (sizeof(charset) - 1);
|
||||
return charset[ rand() % max_index ];
|
||||
};
|
||||
std::string str(length,0);
|
||||
std::generate_n(str.begin(), length, randchar);
|
||||
return str;
|
||||
}
|
||||
|
||||
} // namespace Util
|
||||
} // namespace PresenceDetection
|
||||
-15
@@ -1,15 +0,0 @@
|
||||
#ifndef UTIL_UTIL_H
|
||||
#define UTIL_UTIL_H
|
||||
|
||||
#include <string>
|
||||
|
||||
|
||||
namespace PresenceDetection {
|
||||
namespace Util {
|
||||
|
||||
std::string CreateRandomString(size_t length);
|
||||
|
||||
} // namespace Util
|
||||
} // namespace PresenceDetection
|
||||
|
||||
#endif // UTIL_UTIL_H
|
||||
+430
@@ -0,0 +1,430 @@
|
||||
#include "Driver.h"
|
||||
#include <json.hpp>
|
||||
#include <Logging.h>
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
|
||||
namespace PresenceDetection {
|
||||
namespace WiFi {
|
||||
|
||||
Driver::Driver(const std::string& hostname, int port, const std::string& username, const std::string& password, const std::string& cookieFile, int timeout, const std::string& inventoryURL, const std::string& target, const std::vector<Util::StaticDevice>& staticDevices) :
|
||||
m_httpClient(5),
|
||||
m_loggedIn(false),
|
||||
m_hostname(hostname),
|
||||
m_port(port),
|
||||
m_username(username),
|
||||
m_password(password),
|
||||
m_cookieFile(cookieFile),
|
||||
m_timeout(timeout),
|
||||
m_checkInterval(5),
|
||||
m_inventoryURL(inventoryURL),
|
||||
m_target(target),
|
||||
m_staticDevices(staticDevices)
|
||||
{
|
||||
if (!m_inventoryURL.empty())
|
||||
UpdateDevicesFromInventory();
|
||||
ClearDevices();
|
||||
Start();
|
||||
}
|
||||
|
||||
Driver::~Driver()
|
||||
{
|
||||
Logout();
|
||||
}
|
||||
|
||||
void Driver::Start()
|
||||
{
|
||||
int checkInterval = m_checkInterval * 1000;
|
||||
m_deviceTimer.StartContinuous(checkInterval, static_cast<std::function<void()>>(std::bind(&Driver::UpdatePresentDevices, this)));
|
||||
if (!m_inventoryURL.empty())
|
||||
m_inventoryTimer.StartContinuous(300000, static_cast<std::function<void()>>(std::bind(&Driver::UpdateDevicesFromInventory, this)));
|
||||
}
|
||||
|
||||
void Driver::Stop()
|
||||
{
|
||||
m_deviceTimer.Stop();
|
||||
if (!m_inventoryURL.empty())
|
||||
m_inventoryTimer.Stop();
|
||||
}
|
||||
|
||||
void Driver::Wait()
|
||||
{
|
||||
m_deviceTimer.Wait();
|
||||
if (!m_inventoryURL.empty())
|
||||
m_inventoryTimer.Stop();
|
||||
}
|
||||
|
||||
bool Driver::Login()
|
||||
{
|
||||
std::stringstream url;
|
||||
url << "https://" << m_hostname << ":" << m_port << "/api/auth/login";
|
||||
|
||||
nlohmann::json json;
|
||||
json["password"] = m_password;
|
||||
json["username"] = m_username;
|
||||
|
||||
try
|
||||
{
|
||||
std::vector<std::string> headers;
|
||||
headers.push_back("Content-Type: application/json");
|
||||
|
||||
std::stringstream output;
|
||||
Http::HttpRequest request(url.str());
|
||||
request.Method(Http::HttpRequest::Method::POST);
|
||||
request.Headers(headers);
|
||||
request.CookieFile(m_cookieFile);
|
||||
request.Data(json.dump());
|
||||
output << m_httpClient.Open(request);
|
||||
|
||||
nlohmann::json outputJSON = nlohmann::json::parse(output);
|
||||
|
||||
if (outputJSON["code"] == "AUTHENTICATION_FAILED_INVALID_CREDENTIALS")
|
||||
{
|
||||
std::stringstream error;
|
||||
error << "Login Failed - " << output.str();
|
||||
throw std::runtime_error(error.str());
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "WiFi::Driver::Login() - Error: " << e.what() << std::endl;
|
||||
Logging::Log(Logging::Severity::Error, ss.str());
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
m_loggedIn = false;
|
||||
return m_loggedIn;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
m_loggedIn = true;
|
||||
return m_loggedIn;
|
||||
}
|
||||
|
||||
void Driver::Logout()
|
||||
{
|
||||
// std::stringstream url;
|
||||
// url << "https://" << m_hostname << ":" << m_port << "/api/auth/logout";
|
||||
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
m_loggedIn = false;
|
||||
|
||||
ClearCookiesFile();
|
||||
/*
|
||||
try
|
||||
{
|
||||
Http::HttpRequest request(url.str());
|
||||
request.ReturnType(Http::HttpRequest::ReturnType::None);
|
||||
request.CookieFile(m_cookieFile);
|
||||
m_httpClient.Open(request);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "WiFi::Driver::Logout() - Error: " << e.what() << std::endl;
|
||||
Logging::Log(Logging::Severity::Error, ss.str());
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void Driver::ClearDevices()
|
||||
{
|
||||
for (std::vector<std::string>::iterator it = m_devices.begin(); it != m_devices.end(); ++it)
|
||||
{
|
||||
try
|
||||
{
|
||||
SendStateChange(false, *it);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "WiFi::Driver::ClearDevices() - Error: " << e.what() << std::endl;
|
||||
Logging::Log(Logging::Severity::Error, ss.str());
|
||||
}
|
||||
}
|
||||
|
||||
for (std::vector<Util::StaticDevice>::iterator it = m_staticDevices.begin(); it != m_staticDevices.end(); ++it)
|
||||
{
|
||||
if (it->HasWifiMac())
|
||||
{
|
||||
try
|
||||
{
|
||||
SendStateChange(false, it->WifiMac());
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "WiFi::Driver::ClearDevices() - Error: " << e.what() << std::endl;
|
||||
Logging::Log(Logging::Severity::Error, ss.str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Driver::UpdateDevicesFromInventory()
|
||||
{
|
||||
try
|
||||
{
|
||||
Http::HttpRequest request(m_inventoryURL);
|
||||
std::string devices = m_httpClient.Open(request);
|
||||
nlohmann::json json = nlohmann::json::parse(devices);
|
||||
|
||||
m_devices.clear();
|
||||
for (auto& element : json)
|
||||
if (element["macaddress"] != "")
|
||||
{
|
||||
std::string macAddress = element["macaddress"];
|
||||
std::transform(macAddress.begin(), macAddress.end(), macAddress.begin(), ::tolower);
|
||||
m_devices.push_back(macAddress);
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "WiFi::Driver::GetDevicesFromInventory() - Error: " << e.what() << std::endl;
|
||||
Logging::Log(Logging::Severity::Error, ss.str());
|
||||
}
|
||||
}
|
||||
|
||||
void Driver::UpdatePresentDevices()
|
||||
{
|
||||
bool loggedIn;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
loggedIn = m_loggedIn;
|
||||
}
|
||||
|
||||
if (!loggedIn)
|
||||
if (!Login())
|
||||
return;
|
||||
|
||||
std::stringstream url;
|
||||
url << "https://" << m_hostname << ":" << m_port << "/proxy/network/api/s/default/stat/sta";
|
||||
|
||||
std::time_t timeStamp = std::time(nullptr);
|
||||
std::vector<PresentDevice> presentDevices;
|
||||
std::vector<std::string> addedDevices;
|
||||
std::vector<std::string> removedDevices;
|
||||
|
||||
try
|
||||
{
|
||||
std::stringstream output;
|
||||
Http::HttpRequest request(url.str());
|
||||
request.CookieFile(m_cookieFile);
|
||||
output << m_httpClient.Open(request);
|
||||
|
||||
nlohmann::json json = nlohmann::json::parse(output);
|
||||
//Logging::Log(Logging::Severity::Debug, output.str());
|
||||
|
||||
if (json["meta"]["rc"] != "ok")
|
||||
{
|
||||
std::stringstream error;
|
||||
error << "Query Failed";
|
||||
throw std::runtime_error(error.str());
|
||||
}
|
||||
|
||||
for (auto& device : json["data"])
|
||||
{
|
||||
std::string macAddress = device["mac"];
|
||||
std::transform(macAddress.begin(), macAddress.end(), macAddress.begin(), ::tolower);
|
||||
int lastSeen = device["last_seen"];
|
||||
|
||||
if (std::find(m_devices.begin(), m_devices.end(), macAddress) != m_devices.end())
|
||||
{
|
||||
if ((timeStamp - lastSeen) < m_timeout)
|
||||
{
|
||||
if (std::find(m_presentDevices.begin(), m_presentDevices.end(), macAddress) == m_presentDevices.end())
|
||||
{
|
||||
addedDevices.push_back(macAddress);
|
||||
std::stringstream ss;
|
||||
ss << "Device Added: " << device.dump() << std::endl;
|
||||
Logging::Log(Logging::Severity::Info, ss.str());
|
||||
}
|
||||
presentDevices.push_back(PresentDevice(macAddress, 0));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (std::find(m_presentDevices.begin(), m_presentDevices.end(), macAddress) != m_presentDevices.end())
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "TimeOut (" << m_timeout << "): " << macAddress << std::endl;
|
||||
Logging::Log(Logging::Severity::Info, ss.str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (std::vector<Util::StaticDevice>::iterator it = m_staticDevices.begin(); it != m_staticDevices.end(); ++it)
|
||||
{
|
||||
if ((timeStamp - lastSeen) < m_timeout)
|
||||
{
|
||||
if (it->HasWifiMac() && it->WifiMac() == macAddress)
|
||||
{
|
||||
if (std::find(m_presentDevices.begin(), m_presentDevices.end(), macAddress) == m_presentDevices.end())
|
||||
addedDevices.push_back(macAddress);
|
||||
presentDevices.push_back(PresentDevice(macAddress, 0));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (std::find(m_presentDevices.begin(), m_presentDevices.end(), macAddress) != m_presentDevices.end())
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "TimeOut (" << m_timeout << "): " << macAddress << std::endl;
|
||||
Logging::Log(Logging::Severity::Info, ss.str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "WiFi::Driver::UpdatePresentDevices() - Error: " << e.what() << std::endl;
|
||||
Logging::Log(Logging::Severity::Error, ss.str());
|
||||
Logout();
|
||||
return;
|
||||
}
|
||||
|
||||
for (std::vector<PresentDevice>::iterator it = m_presentDevices.begin(); it != m_presentDevices.end(); ++it)
|
||||
{
|
||||
if (std::find(presentDevices.begin(), presentDevices.end(), *it) == presentDevices.end())
|
||||
{
|
||||
removedDevices.push_back((*it).MacAddress);
|
||||
std::stringstream ss;
|
||||
ss << "Device Removed: " << (*it).MacAddress << std::endl;
|
||||
Logging::Log(Logging::Severity::Info, ss.str());
|
||||
}
|
||||
}
|
||||
|
||||
for (std::vector<std::string>::iterator it = addedDevices.begin(); it != addedDevices.end(); ++it)
|
||||
SendStateChange(true, *it);
|
||||
|
||||
for (std::vector<std::string>::iterator it = removedDevices.begin(); it != removedDevices.end(); ++it)
|
||||
SendStateChange(false, *it);
|
||||
|
||||
m_presentDevices.assign(presentDevices.begin(), presentDevices.end());
|
||||
}
|
||||
|
||||
void Driver::SendStateChange(bool present, const std::string& macAddress)
|
||||
{
|
||||
char sign;
|
||||
if (present)
|
||||
sign = '+';
|
||||
else
|
||||
sign = '-';
|
||||
|
||||
std::stringstream ss;
|
||||
ss << "WiFi: " << sign << " " << macAddress;
|
||||
Logging::Log(Logging::Severity::Info, ss.str());
|
||||
|
||||
if (!m_target.empty())
|
||||
{
|
||||
std::stringstream url;
|
||||
url << m_target << "/WiFi/" << sign << "/" << macAddress;
|
||||
|
||||
try
|
||||
{
|
||||
Http::HttpRequest request(url.str());
|
||||
request.ReturnType(Http::HttpRequest::ReturnType::None);
|
||||
m_httpClient.Open(request);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "WiFi::Driver::SendStateChange() - Error: " << e.what() << std::endl;
|
||||
Logging::Log(Logging::Severity::Error, ss.str());
|
||||
}
|
||||
}
|
||||
|
||||
for (std::vector<Util::StaticDevice>::iterator it = m_staticDevices.begin(); it != m_staticDevices.end(); ++it)
|
||||
{
|
||||
if (it->HasWifiMac() && it->WifiMac() == macAddress)
|
||||
{
|
||||
it->SetWifiState(present);
|
||||
|
||||
std::vector<std::string> urls;
|
||||
|
||||
if (present)
|
||||
{
|
||||
if (!it->GetBluetoothState() && it->HasOnlineURL())
|
||||
urls.push_back(it->OnlineURL());
|
||||
if (it->HasWifiOnlineURL())
|
||||
urls.push_back(it->WifiOnlineURL());
|
||||
}
|
||||
else if (!present)
|
||||
{
|
||||
if (!it->GetBluetoothState() && it->HasOfflineURL())
|
||||
urls.push_back(it->OfflineURL());
|
||||
if (it->HasWifiOfflineURL())
|
||||
urls.push_back(it->WifiOfflineURL());
|
||||
}
|
||||
|
||||
for (auto& url : urls)
|
||||
{
|
||||
try
|
||||
{
|
||||
Http::HttpRequest request(url);
|
||||
request.ReturnType(Http::HttpRequest::ReturnType::None);
|
||||
m_httpClient.Open(request);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "WiFi::Driver::SendStateChange() - Error: " << e.what() << std::endl;
|
||||
Logging::Log(Logging::Severity::Error, ss.str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Driver::ClearCookiesFile()
|
||||
{
|
||||
std::ifstream file;
|
||||
|
||||
file.open(m_cookieFile.c_str(), std::ifstream::out | std::ifstream::trunc);
|
||||
if (!file.is_open() || file.fail())
|
||||
{
|
||||
file.close();
|
||||
|
||||
std::stringstream ss;
|
||||
ss << "WiFi::Driver::ClearCookiesFile() - Error: Failed to erase file content." << std::endl;
|
||||
Logging::Log(Logging::Severity::Error, ss.str());
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
|
||||
Driver::PresentDevice::PresentDevice(const std::string& macAddress) :
|
||||
MacAddress(macAddress)
|
||||
{
|
||||
}
|
||||
|
||||
Driver::PresentDevice::PresentDevice(const std::string& macAddress, int lastSeen) :
|
||||
MacAddress(macAddress),
|
||||
LastSeen(lastSeen)
|
||||
{
|
||||
}
|
||||
|
||||
bool Driver::PresentDevice::operator==(const Driver::PresentDevice& other) const
|
||||
{
|
||||
return MacAddress == other.MacAddress;
|
||||
}
|
||||
|
||||
bool Driver::PresentDevice::operator!=(const Driver::PresentDevice& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
bool Driver::PresentDevice::operator==(const std::string& other) const
|
||||
{
|
||||
return MacAddress == other;
|
||||
}
|
||||
|
||||
bool Driver::PresentDevice::operator!=(const std::string& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
} // namespace WiFi
|
||||
} // namespace PresenceDetection
|
||||
@@ -0,0 +1,79 @@
|
||||
#ifndef WIFI_DRIVER_H
|
||||
#define WIFI_DRIVER_H
|
||||
|
||||
#include "Util/StaticDevice.h"
|
||||
#include <HttpClient.h>
|
||||
#include <Timer.h>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace PresenceDetection {
|
||||
namespace WiFi {
|
||||
|
||||
class Driver
|
||||
{
|
||||
public:
|
||||
Driver(const std::string& hostname, int port, const std::string& username, const std::string& password, const std::string& cookieFile, int timeout, const std::string& inventoryURL, const std::string& target, const std::vector<Util::StaticDevice>& staticDevices);
|
||||
~Driver();
|
||||
|
||||
void Start();
|
||||
void Stop();
|
||||
void Wait();
|
||||
|
||||
private:
|
||||
bool Login();
|
||||
void Logout();
|
||||
|
||||
void ClearDevices();
|
||||
void UpdateDevicesFromInventory();
|
||||
void UpdatePresentDevices();
|
||||
void SendStateChange(bool present, const std::string& macAddress);
|
||||
|
||||
void ClearCookiesFile();
|
||||
|
||||
private:
|
||||
struct PresentDevice
|
||||
{
|
||||
PresentDevice(const std::string& macAddress);
|
||||
PresentDevice(const std::string& macAddress, int lastSeen);
|
||||
|
||||
std::string MacAddress;
|
||||
int LastSeen;
|
||||
|
||||
bool operator==(const PresentDevice& other) const;
|
||||
bool operator!=(const PresentDevice& other) const;
|
||||
|
||||
bool operator==(const std::string& other) const;
|
||||
bool operator!=(const std::string& other) const;
|
||||
};
|
||||
|
||||
private:
|
||||
Timer::Timer m_deviceTimer;
|
||||
Timer::Timer m_inventoryTimer;
|
||||
Http::HttpClient m_httpClient;
|
||||
|
||||
std::mutex m_mutex;
|
||||
bool m_loggedIn;
|
||||
std::string m_hostname;
|
||||
int m_port;
|
||||
std::string m_username;
|
||||
std::string m_password;
|
||||
std::string m_cookieFile;
|
||||
|
||||
std::vector<std::string> m_devices;
|
||||
|
||||
int m_timeout;
|
||||
int m_checkInterval;
|
||||
std::string m_inventoryURL;
|
||||
std::string m_target;
|
||||
std::vector<Util::StaticDevice> m_staticDevices;
|
||||
|
||||
std::vector<PresentDevice> m_presentDevices;
|
||||
};
|
||||
|
||||
} // namespace WiFi
|
||||
} // namespace PresenceDetection
|
||||
|
||||
#endif // WIFI_DRIVER_H
|
||||
@@ -0,0 +1,122 @@
|
||||
#include "Functions.h"
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip_icmp.h>
|
||||
#include <unistd.h>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
|
||||
|
||||
namespace PresenceDetection {
|
||||
namespace WiFi {
|
||||
|
||||
#define DEFDATALEN (64-ICMP_MINLEN)
|
||||
#define MAXIPLEN 60
|
||||
#define MAXICMPLEN 76
|
||||
#define MAXPACKET (65536 - 60 - ICMP_MINLEN)
|
||||
|
||||
bool Functions::Ping(const std::string& ipAddress)
|
||||
{
|
||||
int s, i, cc, packlen, datalen = DEFDATALEN;
|
||||
struct hostent *hp;
|
||||
struct sockaddr_in to, from;
|
||||
struct ip *ip;
|
||||
u_char *packet, outpack[MAXPACKET];
|
||||
char hnamebuf[MAXHOSTNAMELEN];
|
||||
std::string hostname = ipAddress;
|
||||
struct icmp *icp;
|
||||
int ret, fromlen, hlen;
|
||||
fd_set rfds;
|
||||
struct timeval tv;
|
||||
int retval;
|
||||
|
||||
to.sin_family = AF_INET;
|
||||
to.sin_addr.s_addr = inet_addr(ipAddress.c_str());
|
||||
|
||||
packlen = datalen + MAXIPLEN + MAXICMPLEN;
|
||||
if ( (packet = (u_char *)malloc((u_int)packlen)) == NULL)
|
||||
throw std::runtime_error("Can't allocate Packet");
|
||||
|
||||
if ( (s = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0)
|
||||
throw std::runtime_error("Can't send on ICMP Socket");
|
||||
|
||||
icp = (struct icmp*)outpack;
|
||||
icp->icmp_type = ICMP_ECHO;
|
||||
icp->icmp_code = 0;
|
||||
icp->icmp_cksum = 0;
|
||||
icp->icmp_seq = 12345;
|
||||
icp->icmp_id = getpid();
|
||||
|
||||
cc = datalen + ICMP_MINLEN;
|
||||
icp->icmp_cksum = ICMPChecksum((unsigned short*)icp,cc);
|
||||
|
||||
i = sendto(s, (char*)outpack, cc, 0, (struct sockaddr*)&to, (socklen_t)sizeof(struct sockaddr_in));
|
||||
if (i < 0)
|
||||
throw std::runtime_error("Can't send on ICMP Packet");
|
||||
|
||||
FD_ZERO(&rfds);
|
||||
FD_SET(s, &rfds);
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 500000;
|
||||
|
||||
while(1)
|
||||
{
|
||||
retval = select(s+1, &rfds, NULL, NULL, &tv);
|
||||
if (retval == -1)
|
||||
throw std::runtime_error("Can't select file descriptor");
|
||||
|
||||
if (!retval)
|
||||
return false;
|
||||
|
||||
fromlen = sizeof(sockaddr_in);
|
||||
if ((ret = recvfrom(s, (char*)packet, packlen, 0,(struct sockaddr*)&from, (socklen_t*)&fromlen)) < 0)
|
||||
throw std::runtime_error("Can't receive message from socket");
|
||||
|
||||
ip = (struct ip*)((char*)packet);
|
||||
hlen = sizeof(struct ip);
|
||||
if (ret < (hlen + ICMP_MINLEN))
|
||||
throw std::runtime_error("Can't allocate memory for receiving packets");
|
||||
|
||||
icp = (struct icmp*)(packet + hlen);
|
||||
if (icp->icmp_type != ICMP_ECHOREPLY)
|
||||
continue;
|
||||
|
||||
if (icp->icmp_seq != 12345 || icp->icmp_id != getpid())
|
||||
continue;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
uint16_t Functions::ICMPChecksum(uint16_t* addr, unsigned len)
|
||||
{
|
||||
uint16_t answer = 0;
|
||||
uint32_t sum = 0;
|
||||
|
||||
while (len > 1)
|
||||
{
|
||||
sum += *addr++;
|
||||
len -= 2;
|
||||
}
|
||||
|
||||
if (len == 1)
|
||||
{
|
||||
*(unsigned char*)&answer = *(unsigned char*)addr ;
|
||||
sum += answer;
|
||||
}
|
||||
|
||||
sum = (sum >> 16) + (sum & 0xffff);
|
||||
sum += (sum >> 16);
|
||||
answer = ~sum;
|
||||
return answer;
|
||||
}
|
||||
|
||||
} // namespace WiFi
|
||||
} // namespace PresenceDetection
|
||||
@@ -0,0 +1,23 @@
|
||||
#ifndef WIFI_FUNCTIONS_H
|
||||
#define WIFI_FUNCTIONS_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
|
||||
namespace PresenceDetection {
|
||||
namespace WiFi {
|
||||
|
||||
class Functions
|
||||
{
|
||||
public:
|
||||
static bool Ping(const std::string& ipAddress);
|
||||
|
||||
private:
|
||||
static uint16_t ICMPChecksum(uint16_t* addr, unsigned len);
|
||||
};
|
||||
|
||||
} // namespace WiFi
|
||||
} // namespace PresenceDetection
|
||||
|
||||
#endif // WIFI_FUNCTIONS_H
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../Makefile
|
||||
@@ -0,0 +1,39 @@
|
||||
-xc++
|
||||
-I/source/PresenceDetection/Libraries/clipp/include
|
||||
-I/source/PresenceDetection/Libraries/inih
|
||||
-I/source/PresenceDetection/Libraries/json/include/nlohmann
|
||||
-I/source/PresenceDetection/Libraries/json/include
|
||||
-I/source/PresenceDetection
|
||||
-I/source/PresenceDetection/Libraries
|
||||
-g3
|
||||
-O3
|
||||
-fPIC
|
||||
-std=c++11
|
||||
-Wall
|
||||
-Wextra
|
||||
-Wstrict-aliasing
|
||||
-fmax-errors=5
|
||||
-Werror
|
||||
-Wunreachable-code
|
||||
-Wdisabled-optimization
|
||||
-Wformat=2
|
||||
-Winit-self
|
||||
-Wmissing-include-dirs
|
||||
-Woverloaded-virtual
|
||||
-Wsign-promo
|
||||
-Wstrict-null-sentinel
|
||||
-fdiagnostics-show-option
|
||||
-Wno-unused
|
||||
-Wno-variadic-macros
|
||||
-Wno-parentheses
|
||||
-Wno-unused-parameter
|
||||
-ffunction-sections
|
||||
-fdata-sections
|
||||
-I/alpine/include
|
||||
-I/alpine/x86_64-linux-musl/include
|
||||
-pedantic
|
||||
-Wno-stringop-truncation
|
||||
-I/source/PresenceDetection/Libraries/Http/include
|
||||
-I/source/PresenceDetection/Libraries/Timer/include
|
||||
-I/source/PresenceDetection/Libraries/Logging/include
|
||||
-I/source/PresenceDetection/Libraries/Utilities/include
|
||||
Reference in New Issue
Block a user