Browse Source

Add Static Devices, Timeout and UniFi Port Directive

JDierkse 5 năm trước cách đây
mục cha
commit
7b8fcc9722
8 tập tin đã thay đổi với 554 bổ sung33 xóa
  1. 59 8
      Application/PresenceDetection.cc
  2. 120 9
      Bluetooth/Device.cpp
  3. 5 1
      Bluetooth/Device.h
  4. 14 0
      PresenceDetection.ini
  5. 118 13
      UniFi/Device.cpp
  6. 6 2
      UniFi/Device.h
  7. 167 0
      Util/Device.cpp
  8. 65 0
      Util/Device.h

+ 59 - 8
Application/PresenceDetection.cc

@@ -3,9 +3,11 @@
 #include <signal.h>
 #include <syslog.h>
 #include <unistd.h>
+#include <vector>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include "Util/clipp.h"
+#include "Util/Device.h"
 #include "Util/INIh.h"
 #include "Util/Logger.h"
 #include "UniFi/Device.h"
@@ -62,13 +64,60 @@ int main(int argc, char** argv)
 		}
 
 		std::string target = iniReader.Get("PresenceDetection", "Target", "");
-		if (target.empty())
-			throw std::runtime_error("Target directive missing in ini file.");
 
 		bool unifi = iniReader.GetBoolean("PresenceDetection", "UniFi", false);
 
 		bool bluetooth = iniReader.GetBoolean("PresenceDetection", "Bluetooth", false);
 
+		std::vector<PresenceDetection::Util::Device> devices;
+
+		auto sections = iniReader.Sections();
+		for (auto section : sections)
+		{
+			if (section != "PresenceDetection" &&
+			    section != "UniFi" &&
+			    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 device = PresenceDetection::Util::Device(WifiMac, BluetoothMac);
+
+				std::string OnlineURL = iniReader.Get(section, "OnlineURL", "");
+				if (!OnlineURL.empty())
+					device.SetOnlineURL(OnlineURL);
+
+				std::string WifiOnlineURL = iniReader.Get(section, "WifiOnlineURL", "");
+				if (!WifiOnlineURL.empty())
+					device.SetWifiOnlineURL(WifiOnlineURL);
+
+				std::string BluetoothOnlineURL = iniReader.Get(section, "BluetoothOnlineURL", "");
+				if (!BluetoothOnlineURL.empty())
+					device.SetBluetoothOnlineURL(BluetoothOnlineURL);
+
+				std::string OfflineURL = iniReader.Get(section, "OfflineURL", "");
+				if (!OfflineURL.empty())
+					device.SetOfflineURL(OfflineURL);
+
+				std::string WifiOfflineURL = iniReader.Get(section, "WifiOfflineURL", "");
+				if (!WifiOfflineURL.empty())
+					device.SetWifiOfflineURL(WifiOfflineURL);
+
+				std::string BluetoothOfflineURL = iniReader.Get(section, "BluetoothOfflineURL", "");
+				if (!BluetoothOfflineURL.empty())
+					device.SetBluetoothOfflineURL(BluetoothOfflineURL);
+
+				devices.push_back(device);
+			}
+		}
+
 		std::shared_ptr<PresenceDetection::UniFi::Device> pUniFiDevice;
 		if (unifi)
 		{
@@ -76,6 +125,8 @@ int main(int argc, char** argv)
 			if (hostname.empty())
 				throw std::runtime_error("UniFi Hostname directive missing in ini file.");
 
+			int port = iniReader.GetInteger("UniFi", "Port", 8443);
+
 			std::string username = iniReader.Get("UniFi", "Username", "");
 			if (username.empty())
 				throw std::runtime_error("UniFi Username directive missing in ini file.");
@@ -88,21 +139,21 @@ int main(int argc, char** argv)
 			if (cookiefile.empty())
 				throw std::runtime_error("UniFi CookieFile directive missing in ini file.");
 
+			int timeout = iniReader.GetInteger("UniFi", "Timeout", 150);
+
 			std::string inventoryURL = iniReader.Get("UniFi", "Inventory", "");
-			if (inventoryURL.empty())
-				throw std::runtime_error("UniFi Inventory directive missing in ini file.");
 
-			pUniFiDevice = std::make_shared<PresenceDetection::UniFi::Device>(hostname, username, password, cookiefile, inventoryURL, target);
+			pUniFiDevice = std::make_shared<PresenceDetection::UniFi::Device>(hostname, port, username, password, cookiefile, timeout, inventoryURL, target, devices);
 		}
 
 		std::shared_ptr<PresenceDetection::Bluetooth::Device> pBluetoothDevice;
 		if (bluetooth)
 		{
+			int timeout = iniReader.GetInteger("Bluetooth", "Timeout", 150);
+
 			std::string inventoryURL = iniReader.Get("Bluetooth", "Inventory", "");
-			if (inventoryURL.empty())
-				throw std::runtime_error("Bluetooth Inventory directive missing in ini file.");
 
-			pBluetoothDevice = std::make_shared<PresenceDetection::Bluetooth::Device>(inventoryURL, target);
+			pBluetoothDevice = std::make_shared<PresenceDetection::Bluetooth::Device>(timeout, inventoryURL, target, devices);
 		}
 
 		sigset_t wset;

+ 120 - 9
Bluetooth/Device.cpp

@@ -9,11 +9,15 @@
 namespace PresenceDetection {
 namespace Bluetooth {
 
-Device::Device(const std::string& inventoryURL, const std::string& target) :
+Device::Device(int timeout, const std::string& inventoryURL, const std::string& target, const std::vector<Util::Device>& devices) :
+	m_timeout(timeout),
 	m_inventoryURL(inventoryURL),
-	m_target(target)
+	m_target(target),
+	m_staticDevices(devices)
 {
-	UpdateDevicesFromInventory();
+	if (!m_inventoryURL.empty())
+		UpdateDevicesFromInventory();
+	ClearDevices();
 	Start();
 }
 
@@ -35,6 +39,38 @@ void Device::Stop()
 void Device::Wait()
 {
 	m_deviceTimer.Wait();
+void Device::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 << "Bluetooth::Device::ClearDevices() - Error: " << e.what() << std::endl;
+			Util::Logger::Log(Util::Logger::Severity::Error, ss.str());
+		}
+	}
+
+	for (std::vector<Util::Device>::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::Device::ClearDevices() - Error: " << e.what() << std::endl;
+				Util::Logger::Log(Util::Logger::Severity::Error, ss.str());
+			}
+		}
+	}
 }
 
 void Device::UpdateDevicesFromInventory()
@@ -86,6 +122,36 @@ void Device::UpdatePresentDevices()
 		}
 	}
 
+	for (std::vector<Util::Device>::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
+					pollDevice = updateOnlineDevices;
+
+				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());
+				}
+
+				if (!pollDevice)
+					ignoredDevices.push_back(it->BluetoothMac());
+			}
+			catch (const std::exception& e)
+			{
+				std::stringstream ss;
+				ss << "Bluetooth::Device::UpdatePresentDevices() - Error: " << e.what() << std::endl;
+				Util::Logger::Log(Util::Logger::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())
 			SendStateChange(false, *it);
@@ -105,15 +171,60 @@ void Device::SendStateChange(bool present, const std::string& macAddress)
 	ss << "Bluetooth: " << sign << " " << macAddress;
 	Util::Logger::Log(Util::Logger::Severity::Info, ss.str());
 
-	std::stringstream url;
-	url << m_target << "/Bluetooth/" << sign << "/" << macAddress;
-
-	try
+	if (!m_target.empty())
 	{
-		m_httpClient.GetUrlSilent(url.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;
+			Util::Logger::Log(Util::Logger::Severity::Error, ss.str());
+		}
 	}
-	catch (const std::exception& e)
+
+	for (std::vector<Util::Device>::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
+				{
+					m_httpClient.GetUrlSilent(url);
+				}
+				catch (const std::exception& e)
+				{
+					std::stringstream ss;
+					ss << "Bluetooth::Device::SendStateChange() - Error: " << e.what() << std::endl;
+					Util::Logger::Log(Util::Logger::Severity::Error, ss.str());
+				}
+			}
+		}
 	}
 }
 

+ 5 - 1
Bluetooth/Device.h

@@ -3,6 +3,7 @@
 
 #include <string>
 #include <vector>
+#include "Util/Device.h"
 #include "Util/Timer.h"
 #include "Util/HttpClient.h"
 
@@ -13,7 +14,7 @@ namespace Bluetooth {
 class Device
 {
 public:
-	Device(const std::string& inventoryURL, const std::string& target);
+	Device(int timeout, const std::string& inventoryURL, const std::string& target, const std::vector<Util::Device>& devices);
 	~Device();
 
 	void Start();
@@ -21,6 +22,7 @@ public:
 	void Wait();
 
 private:
+	void ClearDevices();
 	void UpdateDevicesFromInventory();
 	void UpdatePresentDevices();
 	void SendStateChange(bool present, const std::string& macAddress);
@@ -32,8 +34,10 @@ private:
 
 	std::vector<std::string> m_devices;
 
+	int m_timeout;
 	std::string m_inventoryURL;
 	std::string m_target;
+	std::vector<Util::Device> m_staticDevices;
 
 	std::vector<std::string> m_presentDevices;
 };

+ 14 - 0
PresenceDetection.ini

@@ -5,10 +5,24 @@ Bluetooth = On
 
 [UniFi]
 Hostname = UniFi
+Port = 
 Username = 
 Password = 
 CookieFile = /tmp/UniFi_Cookies
+Timeout = 
 Inventory = 
 
 [Bluetooth]
+Timeout = 
 Inventory = 
+
+[Device]
+WifiMac = 
+BluetoothMac = 
+OnlineURL = 
+WifiOnlineURL = 
+BluetoothOnlineURL = 
+OfflineURL = 
+WifiOfflineURL = 
+BluetoothOfflineURL = 
+

+ 118 - 13
UniFi/Device.cpp

@@ -1,3 +1,4 @@
+#include <algorithm>
 #include <sstream>
 #include "Util/JSON.h"
 #include "Util/Logger.h"
@@ -7,17 +8,21 @@
 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) :
+Device::Device(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::Device>& devices) :
 	m_loggedIn(false),
 	m_hostname(hostname),
+	m_port(port),
 	m_username(username),
 	m_password(password),
 	m_cookieFile(cookieFile),
+	m_timeout(timeout),
 	m_inventoryURL(inventoryURL),
 	m_target(target),
-	m_offlineTimeout(120)
+	m_staticDevices(devices)
 {
-	UpdateDevicesFromInventory();
+	if (!m_inventoryURL.empty())
+		UpdateDevicesFromInventory();
+	ClearDevices();
 	Start();
 }
 
@@ -29,23 +34,28 @@ Device::~Device()
 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)));
+	if (!m_inventoryURL.empty())
+		m_inventoryTimer.StartContinuous(300000, static_cast<std::function<void()>>(std::bind(&Device::UpdateDevicesFromInventory, this)));
 }
 
 void Device::Stop()
 {
 	m_deviceTimer.Stop();
+	if (!m_inventoryURL.empty())
+		m_inventoryTimer.Stop();
 }
 
 void Device::Wait()
 {
 	m_deviceTimer.Wait();
+	if (!m_inventoryURL.empty())
+		m_inventoryTimer.Stop();
 }
 
 bool Device::Login()
 {
 	std::stringstream url;
-	url << "https://" << m_hostname << "/api/login";
+	url << "https://" << m_hostname << ":" << m_port << "/api/login";
 
 	Util::JSON json;
 	json["password"] = m_password;
@@ -83,7 +93,7 @@ bool Device::Login()
 void Device::Logout()
 {
 	std::stringstream url;
-	url << "https://" << m_hostname << "/logout";
+	url << "https://" << m_hostname << ":" << m_port << "/logout";
 
 	std::lock_guard<std::mutex> lock(m_mutex);
 	m_loggedIn = false;
@@ -100,6 +110,40 @@ void Device::Logout()
 	}
 }
 
+void Device::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 << "UniFi::Device::ClearDevices() - Error: " << e.what() << std::endl;
+			Util::Logger::Log(Util::Logger::Severity::Error, ss.str());
+		}
+	}
+
+	for (std::vector<Util::Device>::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 << "UniFi::Device::ClearDevices() - Error: " << e.what() << std::endl;
+				Util::Logger::Log(Util::Logger::Severity::Error, ss.str());
+			}
+		}
+	}
+}
+
 void Device::UpdateDevicesFromInventory()
 {
 	try
@@ -137,7 +181,7 @@ void Device::UpdatePresentDevices()
 			return;
 
 	std::stringstream url;
-	url << "https://" << m_hostname << "/api/s/default/stat/sta";
+	url << "https://" << m_hostname << ":" << m_port << "/api/s/default/stat/sta";
 
 	std::time_t timeStamp = std::time(nullptr);
 	std::vector<std::string> presentDevices;
@@ -161,17 +205,31 @@ void Device::UpdatePresentDevices()
 		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 ((timeStamp - lastSeen) < m_offlineTimeout)
+			if (std::find(m_devices.begin(), m_devices.end(), macAddress) != m_devices.end())
 			{
-				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);
 					presentDevices.push_back(macAddress);
 				}
 			}
+
+			for (std::vector<Util::Device>::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(macAddress);
+					}
+				}
+			}
 		}
 	}
 	catch (const std::exception& e)
@@ -208,13 +266,60 @@ void Device::SendStateChange(bool present, const std::string& macAddress)
 	ss << "UniFi: " << sign << " " << macAddress;
 	Util::Logger::Log(Util::Logger::Severity::Info, ss.str());
 
-
-	try
+	if (!m_target.empty())
 	{
-		m_httpClient.GetUrlSilent(url.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;
+			Util::Logger::Log(Util::Logger::Severity::Error, ss.str());
+		}
 	}
-	catch (const std::exception& e)
+
+	for (std::vector<Util::Device>::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
+				{
+					m_httpClient.GetUrlSilent(url);
+				}
+				catch (const std::exception& e)
+				{
+					std::stringstream ss;
+					ss << "UniFi::Device::SendStateChange() - Error: " << e.what() << std::endl;
+					Util::Logger::Log(Util::Logger::Severity::Error, ss.str());
+				}
+			}
+		}
 	}
 }
 

+ 6 - 2
UniFi/Device.h

@@ -4,6 +4,7 @@
 #include <mutex>
 #include <string>
 #include <vector>
+#include "Util/Device.h"
 #include "Util/Timer.h"
 #include "Util/HttpClient.h"
 
@@ -14,7 +15,7 @@ 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(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::Device>& devices);
 	~Device();
 
 	void Start();
@@ -25,6 +26,7 @@ private:
 	bool Login();
 	void Logout();
 
+	void ClearDevices();
 	void UpdateDevicesFromInventory();
 	void UpdatePresentDevices();
 	void SendStateChange(bool present, const std::string& macAddress);
@@ -37,15 +39,17 @@ private:
 	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;
 	std::string m_inventoryURL;
 	std::string m_target;
-	int m_offlineTimeout;
+	std::vector<Util::Device> m_staticDevices;
 
 	std::vector<std::string> m_presentDevices;
 };

+ 167 - 0
Util/Device.cpp

@@ -0,0 +1,167 @@
+#include <algorithm>
+#include "Device.h"
+
+
+namespace PresenceDetection {
+namespace Util {
+
+Device::Device(const std::string& wifiMac, const std::string& bluetoothMac) :
+	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);
+}
+
+Device::Device(const Device &other) :
+	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)
+{
+}
+
+Device::~Device()
+{
+}
+
+bool Device::HasWifiMac() const
+{
+	return !m_wifiMac.empty();
+}
+
+std::string Device::WifiMac() const
+{
+	return m_wifiMac;
+}
+
+void Device::SetWifiState(bool present)
+{
+	m_wifiState = present;
+}
+
+bool Device::GetWifiState() const
+{
+	return m_wifiState;
+}
+
+bool Device::HasBluetoothMac() const
+{
+	return !m_bluetoothMac.empty();
+}
+
+std::string Device::BluetoothMac() const
+{
+	return m_bluetoothMac;
+}
+
+void Device::SetBluetoothState(bool present)
+{
+	m_bluetoothState = present;
+}
+
+bool Device::GetBluetoothState() const
+{
+	return m_bluetoothState;
+}
+
+bool Device::HasOnlineURL() const
+{
+	return !m_onlineURL.empty();
+}
+
+void Device::SetOnlineURL(const std::string& url)
+{
+	m_onlineURL = url;
+}
+
+std::string Device::OnlineURL() const
+{
+	return m_onlineURL;
+}
+
+bool Device::HasWifiOnlineURL() const
+{
+	return !m_wifiOnlineURL.empty();
+}
+
+void Device::SetWifiOnlineURL(const std::string& url)
+{
+	m_wifiOnlineURL = url;
+}
+
+std::string Device::WifiOnlineURL() const
+{
+	return m_wifiOnlineURL;
+}
+
+bool Device::HasBluetoothOnlineURL() const
+{
+	return !m_bluetoothOnlineURL.empty();
+}
+
+void Device::SetBluetoothOnlineURL(const std::string& url)
+{
+	m_bluetoothOnlineURL = url;
+}
+
+std::string Device::BluetoothOnlineURL() const
+{
+	return m_bluetoothOnlineURL;
+}
+
+bool Device::HasOfflineURL() const
+{
+	return !m_offlineURL.empty();
+}
+
+void Device::SetOfflineURL(const std::string& url)
+{
+	m_offlineURL = url;
+}
+
+std::string Device::OfflineURL() const
+{
+	return m_offlineURL;
+}
+
+bool Device::HasWifiOfflineURL() const
+{
+	return !m_wifiOfflineURL.empty();
+}
+
+void Device::SetWifiOfflineURL(const std::string& url)
+{
+	m_wifiOfflineURL = url;
+}
+
+std::string Device::WifiOfflineURL() const
+{
+	return m_wifiOfflineURL;
+}
+
+bool Device::HasBluetoothOfflineURL() const
+{
+	return !m_bluetoothOfflineURL.empty();
+}
+
+void Device::SetBluetoothOfflineURL(const std::string& url)
+{
+	m_bluetoothOfflineURL = url;
+}
+
+std::string Device::BluetoothOfflineURL() const
+{
+	return m_bluetoothOfflineURL;
+}
+
+} // namespace Util
+} // namespace PresenceDetection

+ 65 - 0
Util/Device.h

@@ -0,0 +1,65 @@
+#ifndef UTIL_DEVICE_H
+#define UTIL_DEVICE_H
+
+#include <string>
+
+
+namespace PresenceDetection {
+namespace Util {
+
+class Device
+{
+public:
+	Device(const std::string& wifiMac, const std::string& bluetoothMac);
+	Device(const Device &other);
+	~Device();
+
+	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:
+	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_DEVICE_H