Author SHA1 Message Date
JDierkse 434eb25dda Update UniFi Login 2025-03-03 12:59:13 +01:00
JDierkse dc17bbe535 Update Makefiles 2025-03-03 12:57:18 +01:00
JDierkse 9f0ff10abc Update Makefiles 2025-01-16 15:06:53 +01:00
JDierkse 59771c3901 Add CompileFlags file 2023-07-12 15:53:40 +02:00
JDierkse 44f9b0cd15 Update Makefiles 2023-03-16 14:13:45 +01:00
JDierkse bd19b8745e Update Makefiles 2022-03-07 14:32:01 +01:00
JDierkse deb9b419d4 Update Makefiles 2021-07-28 16:24:06 +02:00
JDierkse 03b00fa6de Update Naming and Tests 2021-07-28 16:23:27 +02:00
JDierkse f03e90f5b9 Update Makefiles and add Default Architecture 2020-09-03 12:15:47 +02:00
JDierkse 654fc94d12 Update Makefiles 2020-08-25 09:42:54 +02:00
JDierkse 86af7f0eb8 Update Http Library 2020-06-14 16:39:11 +02:00
JDierkse a8381614e8 Update PresenceDetection.ini 2020-05-12 09:16:19 +02:00
JDierkse 2d9621f1f1 Update Makefile.conf and Libraries 2020-05-04 22:01:48 +02:00
JDierkse dd7ae1cb73 Update Makefiles 2020-05-01 11:40:45 +02:00
JDierkse 56cc5fa02d Improve portablity 2020-05-01 11:40:31 +02:00
JDierkse 21dbdd41d9 Add Static Devices 2020-05-01 11:39:46 +02:00
JDierkse 157b1ceb51 Update to use Libraries and fix include order 2020-03-07 14:46:26 +01:00
JDierkse 3b7491f57d Fix comment 2020-03-05 16:59:48 +01:00
JDierkse 8440b0d0e9 Add clipp Library 2020-03-05 16:59:31 +01:00
JDierkse b41bbcb2ff Update Bluetooth Detection Strategy 2020-03-05 16:57:14 +01:00
JDierkse 7b8fcc9722 Add Static Devices, Timeout and UniFi Port Directive 2020-03-05 16:56:12 +01:00
JDierkse 2fbec833a2 Change clipp include 2020-03-05 13:00:55 +01:00
JDierkse b4f9aa4cb2 Add Logger Class 2020-03-05 12:59:29 +01:00
JDierkse 96d4dc0be9 Fix Timer bug 2019-04-26 11:57:29 +02:00
JDierkse f96a45e3a2 Remove Boost Link Dependency 2019-04-26 11:56:54 +02:00
55 changed files with 1951 additions and 2145 deletions
+2
View File
@@ -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
+3
View File
@@ -0,0 +1,3 @@
[submodule "Makefiles"]
path = Makefiles
url = https://gogs.dierkse.nl/JDierkse/Makefiles.git
+127 -102
View File
@@ -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
View File
@@ -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;
} }
-124
View File
@@ -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
-44
View File
@@ -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
+288
View File
@@ -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
+50
View File
@@ -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
View File
@@ -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");
+2 -3
View File
@@ -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
+55
View File
@@ -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
+38
View File
@@ -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
View File
+1
View File
@@ -0,0 +1 @@
../../Libraries/Http
-1
View File
@@ -1 +0,0 @@
../../Libraries/json/include
+1
View File
@@ -0,0 +1 @@
../../Libraries/Logging
+1
View File
@@ -0,0 +1 @@
../../Libraries/Timer
+1
View File
@@ -0,0 +1 @@
../../Libraries/Utilities
+1
View File
@@ -0,0 +1 @@
../../Libraries/clipp
+1
View File
@@ -0,0 +1 @@
../../Libraries/inih
+1
View File
@@ -0,0 +1 @@
../../Libraries/json
+125
View File
@@ -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
+41
View File
@@ -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
+1
View File
@@ -0,0 +1 @@
../Makefile
-234
View File
@@ -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
Symlink
+1
View File
@@ -0,0 +1 @@
Makefiles/Makefile
+24
View File
@@ -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
-14
View File
@@ -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
-14
View File
@@ -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
-18
View File
@@ -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'`
-10
View File
@@ -1,10 +0,0 @@
#
# Makefile.conf.x86-64
#
ARCH := x86-64
AR := ar
CC := g++
STRIP := strip
OBJCOPY := objcopy
-19
View File
@@ -1,19 +0,0 @@
#
# Makefile.target
#
PresenceDetection.$(ARCH): $(OBJECTS) Application/PresenceDetection.o.$(ARCH)
$(call build_target_arch,$@,$^)
test.$(ARCH): $(OBJECTS) Application/Test.o.$(ARCH)
$(call build_target_arch,$@,$^)
PresenceDetection:
$(call build_target,$@)
test:
$(call build_target,$@)
.DEFAULT_GOAL := PresenceDetection
TARGETS += PresenceDetection test
Submodule
+1
Submodule Makefiles added at 2556879082
+22 -9
View File
@@ -1,14 +1,27 @@
[PresenceDetection] [PresenceDetection]
Target = Target =
UniFi = On UniFi =
Bluetooth = On Bluetooth =
[UniFi] [WiFi]
Hostname = UniFi Hostname = UniFi
Username = Port =
Password = Username =
CookieFile = /tmp/UniFi_Cookies Password =
Inventory = CookieFile =
Timeout =
Inventory =
[Bluetooth] [Bluetooth]
Inventory = Timeout =
Inventory =
[Device]
WifiMac =
BluetoothMac =
OnlineURL =
WifiOnlineURL =
BluetoothOnlineURL =
OfflineURL =
WifiOfflineURL =
BluetoothOfflineURL =
-227
View File
@@ -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
-56
View File
@@ -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
+35
View File
@@ -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
+31
View File
@@ -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
-36
View File
@@ -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
-629
View File
@@ -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
-42
View File
@@ -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
-45
View File
@@ -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
View File
@@ -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
+21
View File
@@ -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
+184
View File
@@ -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
+72
View File
@@ -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
-87
View File
@@ -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
View File
@@ -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
-25
View File
@@ -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
View File
@@ -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
View File
@@ -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
+79
View File
@@ -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
+122
View File
@@ -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
+23
View File
@@ -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
+1
View File
@@ -0,0 +1 @@
../Makefile
+39
View File
@@ -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