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-*
|
core-*
|
||||||
PresenceDetection*
|
PresenceDetection*
|
||||||
!PresenceDetection.cc
|
!PresenceDetection.cc
|
||||||
|
!PresenceDetection.ini
|
||||||
test*
|
test*
|
||||||
!test.cc
|
!test.cc
|
||||||
|
Test*
|
||||||
fixPermissions.sh
|
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 <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
#include <sys/types.h>
|
#include <vector>
|
||||||
#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"
|
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
setlogmask(LOG_UPTO(LOG_INFO));
|
Logging::OpenLog();
|
||||||
openlog("PresenceDetection", LOG_CONS | LOG_NDELAY | LOG_PERROR | LOG_PID, LOG_USER);
|
Logging::SetLogMask(Logging::Severity::Info);
|
||||||
|
|
||||||
boost::program_options::options_description description("Options");
|
bool daemon = false;
|
||||||
description.add_options()
|
clipp::group cli {
|
||||||
("help,h", "Provide Help Message")
|
clipp::option("-d", "--daemon").set(daemon).doc("Run the process as Daemon")
|
||||||
("daemon,d", "Run the process as Daemon");
|
};
|
||||||
|
|
||||||
boost::program_options::variables_map vm;
|
if (!clipp::parse(argc, argv, cli))
|
||||||
boost::program_options::store(boost::program_options::parse_command_line(argc, argv, description), vm);
|
|
||||||
boost::program_options::notify(vm);
|
|
||||||
|
|
||||||
if (vm.count("help"))
|
|
||||||
{
|
{
|
||||||
std::cerr << description << std::endl;
|
std::cout << clipp::make_man_page(cli, argv[0]) << std::endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool daemon = false;
|
INIReader iniReader("PresenceDetection.ini");
|
||||||
if (vm.count("daemon"))
|
if (iniReader.ParseError() != 0)
|
||||||
daemon = true;
|
{
|
||||||
|
std::cerr << "Can't read PresenceDetection.ini" << std::endl;
|
||||||
boost::property_tree::ptree pt;
|
return 1;
|
||||||
boost::property_tree::ini_parser::read_ini("PresenceDetection.ini", pt);
|
}
|
||||||
|
|
||||||
if (daemon)
|
if (daemon)
|
||||||
{
|
{
|
||||||
syslog(LOG_INFO, "Starting Daemon");
|
Logging::Log(Logging::Severity::Info, "Starting PresenceDetection Daemon");
|
||||||
pid_t pid, sid;
|
pid_t pid, sid;
|
||||||
pid = fork();
|
pid = fork();
|
||||||
|
|
||||||
@@ -64,76 +62,103 @@ int main(int argc, char** argv)
|
|||||||
close(STDOUT_FILENO);
|
close(STDOUT_FILENO);
|
||||||
close(STDERR_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
|
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;
|
Logging::Log(Logging::Severity::Info, "Starting PresenceDetection");
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
if (bluetooth)
|
||||||
{
|
{
|
||||||
std::string inventoryURL;
|
int timeout = iniReader.GetInteger("Bluetooth", "Timeout", 150);
|
||||||
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.");
|
|
||||||
|
|
||||||
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;
|
sigset_t wset;
|
||||||
@@ -144,21 +169,21 @@ int main(int argc, char** argv)
|
|||||||
int sig;
|
int sig;
|
||||||
sigwait(&wset,&sig);
|
sigwait(&wset,&sig);
|
||||||
|
|
||||||
syslog(LOG_INFO, "Stopping...");
|
Logging::Log(Logging::Severity::Info, "Stopping PresenceDetection...");
|
||||||
|
|
||||||
if (pUniFiDevice)
|
if (pWiFiDriver)
|
||||||
pUniFiDevice->Stop();
|
pWiFiDriver->Stop();
|
||||||
|
|
||||||
if (pBluetoothDevice)
|
if (pBluetoothDriver)
|
||||||
pBluetoothDevice->Stop();
|
pBluetoothDriver->Stop();
|
||||||
|
|
||||||
if (pUniFiDevice)
|
if (pWiFiDriver)
|
||||||
pUniFiDevice->Wait();
|
pWiFiDriver->Wait();
|
||||||
|
|
||||||
if (pBluetoothDevice)
|
if (pBluetoothDriver)
|
||||||
pBluetoothDevice->Wait();
|
pBluetoothDriver->Wait();
|
||||||
|
|
||||||
closelog();
|
Logging::CloseLog();
|
||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
@@ -166,9 +191,9 @@ int main(int argc, char** argv)
|
|||||||
ss << "ERROR: " << e.what() << std::endl;
|
ss << "ERROR: " << e.what() << std::endl;
|
||||||
|
|
||||||
std::cerr << ss.str() << 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;
|
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 <iostream>
|
||||||
|
#include <signal.h>
|
||||||
#include <string>
|
#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()
|
void print()
|
||||||
{
|
{
|
||||||
std::cout << "Print" << std::endl;
|
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[]*/)
|
int main(int /*argc*/, char** /*argv[]*/)
|
||||||
{
|
{
|
||||||
//std::string address = "48:4B:AA:85:30:C5";
|
//TestINIReader();
|
||||||
//ping(address.c_str());
|
//TestLogic();
|
||||||
|
//TestPing();
|
||||||
//address = "d0:c5:f3:84:99:de";
|
TestUniFi();
|
||||||
//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;
|
|
||||||
|
|
||||||
return 0;
|
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 "Functions.h"
|
||||||
#include <vector>
|
#include "Socket.h"
|
||||||
#include <stdexcept>
|
#include <fcntl.h>
|
||||||
#include <syslog.h>
|
#include <unistd.h>
|
||||||
#include <bluetooth/bluetooth.h>
|
#include <bluetooth/bluetooth.h>
|
||||||
#include <bluetooth/hci.h>
|
#include <bluetooth/hci.h>
|
||||||
#include <bluetooth/l2cap.h>
|
#include <bluetooth/l2cap.h>
|
||||||
|
#include <poll.h>
|
||||||
#include <fcntl.h>
|
#include <sstream>
|
||||||
#include <unistd.h>
|
#include <stdexcept>
|
||||||
#include <sys/poll.h>
|
#include <sys/time.h>
|
||||||
#include "Socket.h"
|
#include <vector>
|
||||||
#include "Functions.h"
|
|
||||||
|
|
||||||
|
|
||||||
namespace PresenceDetection {
|
namespace PresenceDetection {
|
||||||
@@ -44,8 +43,8 @@ bool Functions::Ping(const std::string& macAddress)
|
|||||||
str2ba(macAddress.c_str(), &socketAddress.l2_bdaddr);
|
str2ba(macAddress.c_str(), &socketAddress.l2_bdaddr);
|
||||||
|
|
||||||
struct timeval timeoutStruct;
|
struct timeval timeoutStruct;
|
||||||
timeoutStruct.tv_sec = 3;
|
timeoutStruct.tv_sec = 1;
|
||||||
timeoutStruct.tv_usec = 0;
|
timeoutStruct.tv_usec = 0; //500000;
|
||||||
|
|
||||||
fd_set writeDescriptor, errorDescriptor;
|
fd_set writeDescriptor, errorDescriptor;
|
||||||
FD_ZERO(&writeDescriptor);
|
FD_ZERO(&writeDescriptor);
|
||||||
@@ -69,7 +68,7 @@ bool Functions::Ping(const std::string& macAddress)
|
|||||||
|
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
{
|
{
|
||||||
if (select(socketDescriptor + 1, &errorDescriptor, &writeDescriptor, NULL, &timeoutStruct) < 0)
|
if (select(socketDescriptor + 1, &errorDescriptor, &writeDescriptor, NULL, &timeoutStruct) <= 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
int error = 0;
|
int error = 0;
|
||||||
@@ -126,7 +125,7 @@ bool Functions::Ping(const std::string& macAddress)
|
|||||||
pf[0].events = POLLIN;
|
pf[0].events = POLLIN;
|
||||||
|
|
||||||
int err;
|
int err;
|
||||||
int timeout = 500;
|
int timeout = 200;
|
||||||
if ((err = poll(pf, 1, timeout)) < 0)
|
if ((err = poll(pf, 1, timeout)) < 0)
|
||||||
throw std::runtime_error("Poll failed");
|
throw std::runtime_error("Poll failed");
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
#include <stdexcept>
|
#include "Socket.h"
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <bluetooth/bluetooth.h>
|
#include <bluetooth/bluetooth.h>
|
||||||
#include <bluetooth/hci.h>
|
#include <bluetooth/hci.h>
|
||||||
#include "Socket.h"
|
#include <stdexcept>
|
||||||
|
|
||||||
|
|
||||||
namespace PresenceDetection {
|
namespace PresenceDetection {
|
||||||
@@ -27,4 +27,3 @@ int Socket::Descriptor() const
|
|||||||
|
|
||||||
} // namespace Bluetooth
|
} // namespace Bluetooth
|
||||||
} // namespace PresenceDetection
|
} // 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
+17
-4
@@ -1,14 +1,27 @@
|
|||||||
[PresenceDetection]
|
[PresenceDetection]
|
||||||
Target =
|
Target =
|
||||||
UniFi = On
|
UniFi =
|
||||||
Bluetooth = On
|
Bluetooth =
|
||||||
|
|
||||||
[UniFi]
|
[WiFi]
|
||||||
Hostname = UniFi
|
Hostname = UniFi
|
||||||
|
Port =
|
||||||
Username =
|
Username =
|
||||||
Password =
|
Password =
|
||||||
CookieFile = /tmp/UniFi_Cookies
|
CookieFile =
|
||||||
|
Timeout =
|
||||||
Inventory =
|
Inventory =
|
||||||
|
|
||||||
[Bluetooth]
|
[Bluetooth]
|
||||||
|
Timeout =
|
||||||
Inventory =
|
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