Driver.cpp 9.5 KB

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