Driver.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  1. #include "Driver.h"
  2. #include <json.hpp>
  3. #include <Logging.h>
  4. #include <algorithm>
  5. #include <fstream>
  6. #include <sstream>
  7. namespace PresenceDetection {
  8. namespace WiFi {
  9. 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) :
  10. m_httpClient(5),
  11. m_loggedIn(false),
  12. m_hostname(hostname),
  13. m_port(port),
  14. m_username(username),
  15. m_password(password),
  16. m_cookieFile(cookieFile),
  17. m_timeout(timeout),
  18. m_checkInterval(5),
  19. m_inventoryURL(inventoryURL),
  20. m_target(target),
  21. m_staticDevices(staticDevices)
  22. {
  23. if (!m_inventoryURL.empty())
  24. UpdateDevicesFromInventory();
  25. ClearDevices();
  26. Start();
  27. }
  28. Driver::~Driver()
  29. {
  30. Logout();
  31. }
  32. void Driver::Start()
  33. {
  34. int checkInterval = m_checkInterval * 1000;
  35. m_deviceTimer.StartContinuous(checkInterval, static_cast<std::function<void()>>(std::bind(&Driver::UpdatePresentDevices, this)));
  36. if (!m_inventoryURL.empty())
  37. m_inventoryTimer.StartContinuous(300000, static_cast<std::function<void()>>(std::bind(&Driver::UpdateDevicesFromInventory, this)));
  38. }
  39. void Driver::Stop()
  40. {
  41. m_deviceTimer.Stop();
  42. if (!m_inventoryURL.empty())
  43. m_inventoryTimer.Stop();
  44. }
  45. void Driver::Wait()
  46. {
  47. m_deviceTimer.Wait();
  48. if (!m_inventoryURL.empty())
  49. m_inventoryTimer.Stop();
  50. }
  51. bool Driver::Login()
  52. {
  53. std::stringstream url;
  54. url << "https://" << m_hostname << ":" << m_port << "/api/auth/login";
  55. nlohmann::json json;
  56. json["password"] = m_password;
  57. json["username"] = m_username;
  58. try
  59. {
  60. std::vector<std::string> headers;
  61. headers.push_back("Content-Type: application/json");
  62. std::stringstream output;
  63. Http::HttpRequest request(url.str());
  64. request.Method(Http::HttpRequest::Method::POST);
  65. request.Headers(headers);
  66. request.CookieFile(m_cookieFile);
  67. request.Data(json.dump());
  68. output << m_httpClient.Open(request);
  69. nlohmann::json outputJSON = nlohmann::json::parse(output);
  70. if (outputJSON["code"] == "AUTHENTICATION_FAILED_INVALID_CREDENTIALS")
  71. {
  72. std::stringstream error;
  73. error << "Login Failed - " << output.str();
  74. throw std::runtime_error(error.str());
  75. }
  76. }
  77. catch (const std::exception& e)
  78. {
  79. std::stringstream ss;
  80. ss << "WiFi::Driver::Login() - Error: " << e.what() << std::endl;
  81. Logging::Log(Logging::Severity::Error, ss.str());
  82. std::lock_guard<std::mutex> lock(m_mutex);
  83. m_loggedIn = false;
  84. return m_loggedIn;
  85. }
  86. std::lock_guard<std::mutex> lock(m_mutex);
  87. m_loggedIn = true;
  88. return m_loggedIn;
  89. }
  90. void Driver::Logout()
  91. {
  92. // std::stringstream url;
  93. // url << "https://" << m_hostname << ":" << m_port << "/api/auth/logout";
  94. std::lock_guard<std::mutex> lock(m_mutex);
  95. m_loggedIn = false;
  96. ClearCookiesFile();
  97. /*
  98. try
  99. {
  100. Http::HttpRequest request(url.str());
  101. request.ReturnType(Http::HttpRequest::ReturnType::None);
  102. request.CookieFile(m_cookieFile);
  103. m_httpClient.Open(request);
  104. }
  105. catch (const std::exception& e)
  106. {
  107. std::stringstream ss;
  108. ss << "WiFi::Driver::Logout() - Error: " << e.what() << std::endl;
  109. Logging::Log(Logging::Severity::Error, ss.str());
  110. }
  111. */
  112. }
  113. void Driver::ClearDevices()
  114. {
  115. for (std::vector<std::string>::iterator it = m_devices.begin(); it != m_devices.end(); ++it)
  116. {
  117. try
  118. {
  119. SendStateChange(false, *it);
  120. }
  121. catch (const std::exception& e)
  122. {
  123. std::stringstream ss;
  124. ss << "WiFi::Driver::ClearDevices() - Error: " << e.what() << std::endl;
  125. Logging::Log(Logging::Severity::Error, ss.str());
  126. }
  127. }
  128. for (std::vector<Util::StaticDevice>::iterator it = m_staticDevices.begin(); it != m_staticDevices.end(); ++it)
  129. {
  130. if (it->HasWifiMac())
  131. {
  132. try
  133. {
  134. SendStateChange(false, it->WifiMac());
  135. }
  136. catch (const std::exception& e)
  137. {
  138. std::stringstream ss;
  139. ss << "WiFi::Driver::ClearDevices() - Error: " << e.what() << std::endl;
  140. Logging::Log(Logging::Severity::Error, ss.str());
  141. }
  142. }
  143. }
  144. }
  145. void Driver::UpdateDevicesFromInventory()
  146. {
  147. try
  148. {
  149. Http::HttpRequest request(m_inventoryURL);
  150. std::string devices = m_httpClient.Open(request);
  151. nlohmann::json json = nlohmann::json::parse(devices);
  152. m_devices.clear();
  153. for (auto& element : json)
  154. if (element["macaddress"] != "")
  155. {
  156. std::string macAddress = element["macaddress"];
  157. std::transform(macAddress.begin(), macAddress.end(), macAddress.begin(), ::tolower);
  158. m_devices.push_back(macAddress);
  159. }
  160. }
  161. catch (const std::exception& e)
  162. {
  163. std::stringstream ss;
  164. ss << "WiFi::Driver::GetDevicesFromInventory() - Error: " << e.what() << std::endl;
  165. Logging::Log(Logging::Severity::Error, ss.str());
  166. }
  167. }
  168. void Driver::UpdatePresentDevices()
  169. {
  170. bool loggedIn;
  171. {
  172. std::lock_guard<std::mutex> lock(m_mutex);
  173. loggedIn = m_loggedIn;
  174. }
  175. if (!loggedIn)
  176. if (!Login())
  177. return;
  178. std::stringstream url;
  179. url << "https://" << m_hostname << ":" << m_port << "/proxy/network/api/s/default/stat/sta";
  180. std::time_t timeStamp = std::time(nullptr);
  181. std::vector<PresentDevice> presentDevices;
  182. std::vector<std::string> addedDevices;
  183. std::vector<std::string> removedDevices;
  184. try
  185. {
  186. std::stringstream output;
  187. Http::HttpRequest request(url.str());
  188. request.CookieFile(m_cookieFile);
  189. output << m_httpClient.Open(request);
  190. nlohmann::json json = nlohmann::json::parse(output);
  191. //Logging::Log(Logging::Severity::Debug, output.str());
  192. if (json["meta"]["rc"] != "ok")
  193. {
  194. std::stringstream error;
  195. error << "Query Failed";
  196. throw std::runtime_error(error.str());
  197. }
  198. for (auto& device : json["data"])
  199. {
  200. std::string macAddress = device["mac"];
  201. std::transform(macAddress.begin(), macAddress.end(), macAddress.begin(), ::tolower);
  202. int lastSeen = device["last_seen"];
  203. if (std::find(m_devices.begin(), m_devices.end(), macAddress) != m_devices.end())
  204. {
  205. if ((timeStamp - lastSeen) < m_timeout)
  206. {
  207. if (std::find(m_presentDevices.begin(), m_presentDevices.end(), macAddress) == m_presentDevices.end())
  208. {
  209. addedDevices.push_back(macAddress);
  210. std::stringstream ss;
  211. ss << "Device Added: " << device.dump() << std::endl;
  212. Logging::Log(Logging::Severity::Info, ss.str());
  213. }
  214. presentDevices.push_back(PresentDevice(macAddress, 0));
  215. }
  216. else
  217. {
  218. if (std::find(m_presentDevices.begin(), m_presentDevices.end(), macAddress) != m_presentDevices.end())
  219. {
  220. std::stringstream ss;
  221. ss << "TimeOut (" << m_timeout << "): " << macAddress << std::endl;
  222. Logging::Log(Logging::Severity::Info, ss.str());
  223. }
  224. }
  225. }
  226. for (std::vector<Util::StaticDevice>::iterator it = m_staticDevices.begin(); it != m_staticDevices.end(); ++it)
  227. {
  228. if ((timeStamp - lastSeen) < m_timeout)
  229. {
  230. if (it->HasWifiMac() && it->WifiMac() == macAddress)
  231. {
  232. if (std::find(m_presentDevices.begin(), m_presentDevices.end(), macAddress) == m_presentDevices.end())
  233. addedDevices.push_back(macAddress);
  234. presentDevices.push_back(PresentDevice(macAddress, 0));
  235. }
  236. }
  237. else
  238. {
  239. if (std::find(m_presentDevices.begin(), m_presentDevices.end(), macAddress) != m_presentDevices.end())
  240. {
  241. std::stringstream ss;
  242. ss << "TimeOut (" << m_timeout << "): " << macAddress << std::endl;
  243. Logging::Log(Logging::Severity::Info, ss.str());
  244. }
  245. }
  246. }
  247. }
  248. }
  249. catch (const std::exception& e)
  250. {
  251. std::stringstream ss;
  252. ss << "WiFi::Driver::UpdatePresentDevices() - Error: " << e.what() << std::endl;
  253. Logging::Log(Logging::Severity::Error, ss.str());
  254. Logout();
  255. return;
  256. }
  257. for (std::vector<PresentDevice>::iterator it = m_presentDevices.begin(); it != m_presentDevices.end(); ++it)
  258. {
  259. if (std::find(presentDevices.begin(), presentDevices.end(), *it) == presentDevices.end())
  260. {
  261. removedDevices.push_back((*it).MacAddress);
  262. std::stringstream ss;
  263. ss << "Device Removed: " << (*it).MacAddress << std::endl;
  264. Logging::Log(Logging::Severity::Info, ss.str());
  265. }
  266. }
  267. for (std::vector<std::string>::iterator it = addedDevices.begin(); it != addedDevices.end(); ++it)
  268. SendStateChange(true, *it);
  269. for (std::vector<std::string>::iterator it = removedDevices.begin(); it != removedDevices.end(); ++it)
  270. SendStateChange(false, *it);
  271. m_presentDevices.assign(presentDevices.begin(), presentDevices.end());
  272. }
  273. void Driver::SendStateChange(bool present, const std::string& macAddress)
  274. {
  275. char sign;
  276. if (present)
  277. sign = '+';
  278. else
  279. sign = '-';
  280. std::stringstream ss;
  281. ss << "WiFi: " << sign << " " << macAddress;
  282. Logging::Log(Logging::Severity::Info, ss.str());
  283. if (!m_target.empty())
  284. {
  285. std::stringstream url;
  286. url << m_target << "/WiFi/" << sign << "/" << macAddress;
  287. try
  288. {
  289. Http::HttpRequest request(url.str());
  290. request.ReturnType(Http::HttpRequest::ReturnType::None);
  291. m_httpClient.Open(request);
  292. }
  293. catch (const std::exception& e)
  294. {
  295. std::stringstream ss;
  296. ss << "WiFi::Driver::SendStateChange() - Error: " << e.what() << std::endl;
  297. Logging::Log(Logging::Severity::Error, ss.str());
  298. }
  299. }
  300. for (std::vector<Util::StaticDevice>::iterator it = m_staticDevices.begin(); it != m_staticDevices.end(); ++it)
  301. {
  302. if (it->HasWifiMac() && it->WifiMac() == macAddress)
  303. {
  304. it->SetWifiState(present);
  305. std::vector<std::string> urls;
  306. if (present)
  307. {
  308. if (!it->GetBluetoothState() && it->HasOnlineURL())
  309. urls.push_back(it->OnlineURL());
  310. if (it->HasWifiOnlineURL())
  311. urls.push_back(it->WifiOnlineURL());
  312. }
  313. else if (!present)
  314. {
  315. if (!it->GetBluetoothState() && it->HasOfflineURL())
  316. urls.push_back(it->OfflineURL());
  317. if (it->HasWifiOfflineURL())
  318. urls.push_back(it->WifiOfflineURL());
  319. }
  320. for (auto& url : urls)
  321. {
  322. try
  323. {
  324. Http::HttpRequest request(url);
  325. request.ReturnType(Http::HttpRequest::ReturnType::None);
  326. m_httpClient.Open(request);
  327. }
  328. catch (const std::exception& e)
  329. {
  330. std::stringstream ss;
  331. ss << "WiFi::Driver::SendStateChange() - Error: " << e.what() << std::endl;
  332. Logging::Log(Logging::Severity::Error, ss.str());
  333. }
  334. }
  335. }
  336. }
  337. }
  338. void Driver::ClearCookiesFile()
  339. {
  340. std::ifstream file;
  341. file.open(m_cookieFile.c_str(), std::ifstream::out | std::ifstream::trunc);
  342. if (!file.is_open() || file.fail())
  343. {
  344. file.close();
  345. std::stringstream ss;
  346. ss << "WiFi::Driver::ClearCookiesFile() - Error: Failed to erase file content." << std::endl;
  347. Logging::Log(Logging::Severity::Error, ss.str());
  348. }
  349. file.close();
  350. }
  351. Driver::PresentDevice::PresentDevice(const std::string& macAddress) :
  352. MacAddress(macAddress)
  353. {
  354. }
  355. Driver::PresentDevice::PresentDevice(const std::string& macAddress, int lastSeen) :
  356. MacAddress(macAddress),
  357. LastSeen(lastSeen)
  358. {
  359. }
  360. bool Driver::PresentDevice::operator==(const Driver::PresentDevice& other) const
  361. {
  362. return MacAddress == other.MacAddress;
  363. }
  364. bool Driver::PresentDevice::operator!=(const Driver::PresentDevice& other) const
  365. {
  366. return !(*this == other);
  367. }
  368. bool Driver::PresentDevice::operator==(const std::string& other) const
  369. {
  370. return MacAddress == other;
  371. }
  372. bool Driver::PresentDevice::operator!=(const std::string& other) const
  373. {
  374. return !(*this == other);
  375. }
  376. } // namespace WiFi
  377. } // namespace PresenceDetection