api.trassirserver.php 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035
  1. <?php
  2. /**
  3. * Basic low-level Trassir Server NVRs interraction class.
  4. * Based on: https://github.com/dglushakov/TrassirNVR
  5. */
  6. class TrassirServer {
  7. /**
  8. * Object instance debug flag
  9. *
  10. * @var bool/int
  11. */
  12. protected $debug = false;
  13. /**
  14. * Contains current instance Trassir Server hostname
  15. *
  16. * @var string $name
  17. */
  18. protected $name = '';
  19. /**
  20. * Contains IP address of Trassir server host
  21. *
  22. * @var string|null $ip
  23. */
  24. protected $ip = null;
  25. /**
  26. * Basic transport protocol for Trassir SDK interraction
  27. *
  28. * @var string
  29. */
  30. protected $sdkProtocol = 'https';
  31. /**
  32. * Contains Trassir server HTTPS port for further API requests
  33. *
  34. * @var int
  35. */
  36. protected $port = 8080;
  37. /**
  38. * HTTP Video Streaming port
  39. *
  40. * @var int
  41. */
  42. protected $httpVideoPort = 555;
  43. /**
  44. * Default http video streaming protocol
  45. *
  46. * @var string
  47. */
  48. protected $httpVideoProtocol = 'http';
  49. /**
  50. * Contains current instance GUID
  51. *
  52. * @var string $guid
  53. */
  54. protected $guid = '';
  55. /**
  56. * Current instance session ID
  57. *
  58. * @var string|false $sid
  59. */
  60. protected $sid = false;
  61. /**
  62. * Username for connecting Trassir Server NVR
  63. *
  64. * @var string $userName
  65. */
  66. protected $userName = '';
  67. /**
  68. * Password for connecting Trassir Server NVR
  69. *
  70. * @var string $password
  71. */
  72. protected $password = '';
  73. /**
  74. * Trassir SDK API key
  75. *
  76. * @var string $sdkPassword
  77. */
  78. protected $sdkPassword;
  79. /**
  80. * Caching object placeholder
  81. *
  82. * @var object
  83. */
  84. protected $cache = '';
  85. /**
  86. * Session caching interval in seconds
  87. *
  88. * @var int
  89. */
  90. protected $cacheTimeout = 900; //15 mins
  91. /**
  92. * Current instance server objects tree
  93. *
  94. * @var array
  95. */
  96. protected $serverObjects = array();
  97. /**
  98. * Available Trassir Server channels as index=>chandata
  99. *
  100. * @var array $channels
  101. */
  102. protected $channels = array();
  103. /**
  104. * Contains array of available channel names as guid=>name
  105. *
  106. * @var array
  107. */
  108. protected $channelNames = array();
  109. /**
  110. * Contains available users array as index=>username or guid
  111. *
  112. * @var array
  113. */
  114. protected $trassirUsers = array();
  115. /**
  116. * Contains default service users account names which will be ignored by some safe methods
  117. *
  118. * @var array
  119. */
  120. protected $serviceAccountNames = array('Admin', 'Operator', 'Script', 'Demo', 'user_add', 'Monitoring');
  121. /**
  122. * Stream context for working with self-signed certs
  123. *
  124. * @var resource
  125. */
  126. protected $stream_context;
  127. /**
  128. * Contains default log path
  129. */
  130. const LOG_PATH = 'exports/trassirdebug.log';
  131. /**
  132. * Creates new instance of TrassirServer object
  133. *
  134. * @param string $ip
  135. * @param string $userName
  136. * @param string $password
  137. * @param string $sdkPassword
  138. * @param int $port
  139. * @param bool/int debug: false/0/1/2/3
  140. *
  141. * @return void
  142. */
  143. public function __construct($ip, $userName = null, $password = null, $sdkPassword = null, $port = 8080, $debug = false) {
  144. $this->setDebug($debug);
  145. $this->initCache();
  146. $this->setIp($ip);
  147. $this->setUserName($userName);
  148. $this->setPassword($password);
  149. $this->setSdkPassword($sdkPassword);
  150. $this->setPort($port);
  151. $this->stream_context = stream_context_create(array('ssl' => array(//allowing self-signed certs for NVR
  152. 'verify_peer' => false,
  153. 'verify_peer_name' => false,
  154. 'allow_self_signed' => true,
  155. 'verify_depth' => 0)));
  156. $this->initialConnect(); // initalizing connection to server, setting some SIDs and other stuff
  157. }
  158. /**
  159. * Performs initial Server object connection
  160. *
  161. * @return bool
  162. */
  163. protected function initialConnect() {
  164. $result = true;
  165. $connnectCheck = $this->checkConnection();
  166. if ($connnectCheck) {
  167. $this->logDebug('HTTPS connection to IP ' . $this->ip . ' OK', 'success');
  168. } else {
  169. $this->logDebug('HTTPS connection to IP ' . $this->ip . ' Failed', 'error');
  170. }
  171. $loginCheck = $this->login();
  172. if ($loginCheck) {
  173. $this->logDebug('NVR login seems to be OK', 'success');
  174. } else {
  175. $this->logDebug('NVR login failed', 'error');
  176. }
  177. return($result);
  178. }
  179. /**
  180. * Inits system caching object for further usage and storing SID
  181. *
  182. * @return void
  183. */
  184. protected function initCache() {
  185. $this->cache = new UbillingCache();
  186. }
  187. /**
  188. * Sets current instance IP
  189. *
  190. * @param string $ip
  191. *
  192. * @return void
  193. */
  194. protected function setIp($ip) {
  195. $this->ip = $ip;
  196. }
  197. /**
  198. * Sets current instance HTTPS port
  199. *
  200. * @param int $port
  201. *
  202. * @return void
  203. */
  204. protected function setPort($port) {
  205. $this->port = $port;
  206. }
  207. /**
  208. * Sets current instance username
  209. *
  210. * @param string $userName
  211. *
  212. * @return void
  213. */
  214. protected function setUserName($userName) {
  215. $this->userName = $userName;
  216. }
  217. /**
  218. * Modify current instance debug flag
  219. *
  220. * @param bool/int $state
  221. *
  222. * @return void
  223. */
  224. protected function setDebug($state) {
  225. $this->debug = $state;
  226. }
  227. /**
  228. * Sets current instance password
  229. *
  230. * @param string $password
  231. *
  232. * @return void
  233. */
  234. protected function setPassword($password) {
  235. $this->password = $password;
  236. }
  237. /**
  238. * Sets Trassir SDK API key into current instance
  239. *
  240. * @param string $sdkpassword
  241. *
  242. * @return void
  243. */
  244. protected function setSdkPassword($sdkpassword) {
  245. $this->sdkPassword = $sdkpassword;
  246. }
  247. /**
  248. * Returns current instance server hostname
  249. *
  250. * @return string|null
  251. */
  252. public function getName() {
  253. return ($this->name);
  254. }
  255. /**
  256. * Returns curren instance GUID
  257. *
  258. * @return string
  259. */
  260. public function getGuid() {
  261. return $this->guid;
  262. }
  263. /**
  264. * Checking is NVR online or not to prevent further errors
  265. *
  266. *
  267. * @return bool
  268. */
  269. protected function checkConnection() {
  270. $status = false;
  271. $url = 'https://' . trim($this->ip) . ':' . $this->port . '/';
  272. $curlInit = curl_init($url);
  273. curl_setopt($curlInit, CURLOPT_CONNECTTIMEOUT, 2);
  274. curl_setopt($curlInit, CURLOPT_HEADER, true);
  275. curl_setopt($curlInit, CURLOPT_NOBODY, false);
  276. curl_setopt($curlInit, CURLOPT_SSL_VERIFYHOST, 0);
  277. curl_setopt($curlInit, CURLOPT_SSL_VERIFYPEER, 0);
  278. curl_setopt($curlInit, CURLOPT_RETURNTRANSFER, true);
  279. $response = curl_exec($curlInit);
  280. curl_close($curlInit);
  281. if ($response) {
  282. $status = true;
  283. }
  284. return ($status);
  285. }
  286. /**
  287. * Do some debug output and logging in the future
  288. *
  289. * @param string $data
  290. * @param string $type success/info/warning/error
  291. *
  292. * @return void
  293. */
  294. protected function logDebug($data, $type) {
  295. if ($this->debug) {
  296. $curDate = curdatetime();
  297. $dataDisplay = $curDate . ' ' . $data;
  298. if ($this->debug == 1 OR $this->debug == 2) {
  299. switch ($type) {
  300. case 'success':
  301. show_success($dataDisplay);
  302. break;
  303. case 'info':
  304. show_info($dataDisplay);
  305. break;
  306. case 'warning':
  307. show_warning($dataDisplay);
  308. break;
  309. case 'error':
  310. show_error($dataDisplay);
  311. break;
  312. }
  313. }
  314. $logData = $curDate . ' ' . $type . ' ' . $data . PHP_EOL;
  315. file_put_contents(self::LOG_PATH, $logData, FILE_APPEND);
  316. }
  317. }
  318. /**
  319. * Get current NVR session ID (sid) using login and password
  320. *
  321. * @return bool|string
  322. */
  323. protected function login() {
  324. ///trying get it from cache
  325. $cacheKey = 'TRASSIRSID_' . $this->ip;
  326. $cachedSid = $this->cache->get($cacheKey, $this->cacheTimeout);
  327. //SID found in cache and seems it may be ok
  328. if (!empty($cachedSid)) {
  329. $this->logDebug('SID from cache: ' . $cachedSid . ' from cache key ' . $cacheKey, 'success');
  330. $this->sid = $cachedSid;
  331. } else {
  332. $this->logDebug('No cached SID available. Trying to receive new one', 'warning');
  333. }
  334. if (isset($this->sid) AND ( $this->sid !== false)) {
  335. //updating SID in cache
  336. $this->cache->set($cacheKey, $this->sid, $this->cacheTimeout);
  337. $this->logDebug('Updating SID ' . $this->sid . ' in cache key', 'info');
  338. return ($this->sid);
  339. }
  340. //New SID receiving
  341. $url = 'https://' . trim($this->ip) . ':' . trim($this->port) . '/login?username=' . trim($this->userName) . '&password=' . trim($this->password);
  342. if (false === ($responseJson_str = @file_get_contents($url, NULL, $this->stream_context))) {
  343. return (false); //connection failed
  344. }
  345. $server_auth = json_decode($responseJson_str, true);
  346. if ($server_auth['success'] == 1) {
  347. $this->sid = $server_auth['sid'];
  348. $this->logDebug('New SID received: ' . $this->sid, 'success');
  349. //setting new SID to cache
  350. $this->cache->set($cacheKey, $this->sid, $this->cacheTimeout);
  351. } else {
  352. show_error(__('SDK reply') . ': ' . $responseJson_str);
  353. $this->sid = false;
  354. }
  355. return ($this->sid);
  356. }
  357. /**
  358. * Returns clean JSON data without shitty comments at the end
  359. *
  360. * @param string $data
  361. *
  362. * @return string
  363. */
  364. protected function clearReply($data) {
  365. $commentPosition = strripos($data, '/*');
  366. if ($commentPosition !== false) {
  367. $data = substr($data, 0, $commentPosition);
  368. }
  369. return($data);
  370. }
  371. /**
  372. * Performs SDK API request to connected Trassir Server
  373. *
  374. * @param string $request request string
  375. * @param string $authType possible: apikey, sid, sidamp
  376. *
  377. * @return array
  378. */
  379. protected function apiRequest($request, $authType) {
  380. $result = array();
  381. $authString = '';
  382. $host = $this->sdkProtocol . '://' . $this->ip . ':' . $this->port;
  383. switch ($authType) {
  384. case 'apikey':
  385. $authString = '?password=' . $this->sdkPassword;
  386. break;
  387. case 'sid':
  388. $authString = '?sid=' . $this->sid;
  389. break;
  390. case 'sidamp':
  391. $authString = '&sid=' . $this->sid;
  392. break;
  393. }
  394. $url = $host . $request . $authString;
  395. if ($this->debug >= 2) {
  396. $this->logDebug($url, 'lld');
  397. }
  398. $rawResponse = file_get_contents($url, null, $this->stream_context);
  399. $rawResponse = $this->clearReply($rawResponse);
  400. $result = json_decode($rawResponse, true);
  401. if ($this->debug >= 2) {
  402. $this->logDebug('Response: ' . print_r($result, true), 'lld');
  403. }
  404. return($result);
  405. }
  406. /**
  407. * Returns all of server objects (channels, IP-devices etc.)
  408. *
  409. * also fills $this->channels array
  410. *
  411. * @return array
  412. */
  413. public function getServerObjects() {
  414. $objects = $this->apiRequest('/objects/', 'apikey');
  415. foreach ($objects as $obj) {
  416. if ($obj['class'] == 'Server') {
  417. $this->name = $obj['name'];
  418. $this->guid = $obj['guid'];
  419. }
  420. if ($obj['class'] == 'Channel') {
  421. $this->channels[] = array(
  422. 'name' => $obj['name'],
  423. 'guid' => $obj ['guid'],
  424. 'parent' => $obj ['parent'],
  425. );
  426. $this->channelNames[$obj['guid']] = $obj['name'];
  427. }
  428. }
  429. $objects['Users'] = $this->getUsers();
  430. $objects['UserNames'] = $this->getUserNames();
  431. $this->serverObjects = $objects;
  432. return ($objects);
  433. }
  434. /**
  435. * Returns array of system health indicators. Also fills channels_health
  436. *
  437. * @return array
  438. */
  439. public function getHealth() {
  440. if (empty($this->channels)) {
  441. $this->getServerObjects();
  442. }
  443. $server_health = $this->apiRequest('/health', 'sid');
  444. $channelsHealth = array();
  445. $result = $server_health;
  446. if (!empty($this->channels)) {
  447. foreach ($this->channels as $channel) {
  448. $chanHealth = $this->apiRequest('/settings/channels/' . $channel['guid'] . '/flags/signal', 'sid');
  449. $channelsHealth[] = array(
  450. 'name' => $channel['name'],
  451. 'guid' => $channel['guid'],
  452. 'signal' => $chanHealth['value']
  453. );
  454. }
  455. if (isset($channelsHealth) AND ! empty($channelsHealth) AND is_array($channelsHealth)) {
  456. $result['channels_health'] = $channelsHealth;
  457. }
  458. }
  459. return ($result);
  460. }
  461. /**
  462. * Returns array of available channels as guid=>name
  463. *
  464. * @return array
  465. */
  466. public function getChannels() {
  467. if (empty($this->serverObjects)) {
  468. $this->getServerObjects();
  469. }
  470. return($this->channelNames);
  471. }
  472. /**
  473. * Returns server settings main tree
  474. *
  475. * @return array
  476. */
  477. public function getServerSettings() {
  478. $result = $this->apiRequest('/settings/', 'sid');
  479. return($result);
  480. }
  481. /**
  482. * Returns array of server users/their guids
  483. *
  484. * @return array
  485. */
  486. protected function getUsers() {
  487. $rawUsers = $this->apiRequest('/settings/users/', 'sid');
  488. $this->trassirUsers = $rawUsers['subdirs'];
  489. return ($this->trassirUsers);
  490. }
  491. /**
  492. * Creates user on Trassir Server.
  493. *
  494. * @param string $login
  495. * @param string $password
  496. *
  497. * @return bool
  498. */
  499. public function createUser($login, $password) {
  500. $result = false;
  501. $userExists = $this->getUserGuid($login);
  502. if (!$userExists) {
  503. $this->apiRequest('/settings/users/user_add/new_user_name=' . $login, 'sid');
  504. $this->apiRequest('/settings/users/user_add/new_user_password=' . $password, 'sid');
  505. $this->apiRequest('/settings/users/user_add/create_now=1', 'sid');
  506. $result = true;
  507. $this->getServerObjects(); //update object instance for preloading of some new users
  508. $this->logDebug('New user registered: ' . $login, 'info');
  509. //restricting new user rights
  510. $this->restrictUserRighs($login);
  511. } else {
  512. $this->logDebug('User already registered and found in server objects tree: ' . $login, 'warning');
  513. }
  514. return($result);
  515. }
  516. /**
  517. *
  518. * @param type $userLogin
  519. *
  520. * @return bool
  521. */
  522. protected function restrictUserRighs($userLogin) {
  523. $result = false;
  524. $guid = $this->getUserGuid($userLogin);
  525. if ($guid) {
  526. $this->setUserSettings($guid, 'base_rights', 0); //no rights at all
  527. $this->setUserSettings($guid, 'templates_managing', 0);
  528. $this->setUserSettings($guid, 'enable_web', 1);
  529. $this->setUserSettings($guid, 'enable_remote', 1);
  530. $this->setUserSettings($guid, 'view_button', 1);
  531. $this->setUserSettings($guid, 'settings_button', 0);
  532. $this->setUserSettings($guid, 'shutdown_button', 0);
  533. $this->setUserSettings($guid, 'enable_local', 0);
  534. $this->setUserSettings($guid, 'base_rights', 256); //no rights at all
  535. $result = true;
  536. $this->logDebug('User rights restricted on login: ' . $userLogin, 'info');
  537. } else {
  538. $this->logDebug('User not found in server objects tree: ' . $userLogin, 'error');
  539. }
  540. return($result);
  541. }
  542. /**
  543. * Sets user ACL for some channels permissions.
  544. * Use manual POST because of "cannot find 'acl=" issue.
  545. *
  546. * @param string $userGuid
  547. * @param string $acl
  548. *
  549. * @return bool/array
  550. */
  551. protected function setUserACL($userGuid, $acl = '') {
  552. $result = false;
  553. $post = 'acl=' . $acl;
  554. $url = $this->sdkProtocol . '://' . $this->ip . ':' . $this->port . '/settings/users/' . $userGuid . '/?sid=' . $this->sid;
  555. $curl = curl_init($url);
  556. curl_setopt($curl, CURLOPT_HEADER, 0);
  557. curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
  558. curl_setopt($curl, CURLOPT_BINARYTRANSFER, 1);
  559. curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0);
  560. curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);
  561. curl_setopt($curl, CURLOPT_POSTFIELDS, $post);
  562. $response = curl_exec($curl);
  563. curl_close($curl);
  564. $response = $this->clearReply($response);
  565. if (!empty($response)) {
  566. $result = json_decode($response, true);
  567. $this->logDebug('Setting user ' . $userGuid . ' ACL to ' . $acl, 'info');
  568. }
  569. return($result);
  570. }
  571. /**
  572. * Set some user ACL to allow him basic usage of his cameras
  573. *
  574. * @param string $login
  575. * @param array $channels
  576. *
  577. * @return bool
  578. */
  579. public function assignUserChannels($login, $channels = array()) {
  580. $result = false;
  581. $userGuid = $this->getUserGuid($login);
  582. if ($userGuid) {
  583. $rightsMask = '1539'; // Oo
  584. $aclString = '';
  585. if (!empty($channels)) {
  586. foreach ($channels as $io => $eachChan) {
  587. if (isset($this->channelNames[$eachChan])) {
  588. $aclString .= '/' . $this->guid . '/channels/' . $eachChan . ',' . $rightsMask . ',';
  589. } else {
  590. $this->logDebug('Channel assign failed: ' . $eachChan . ' not found on server', 'error');
  591. }
  592. }
  593. } else {
  594. $this->logDebug('User ' . $login . ' Channel assign failed - empty channels array', 'warning');
  595. }
  596. $aclString = zb_CutEnd($aclString);
  597. $this->logDebug('Setting user ' . $login . ' ACL: ' . $aclString, 'info');
  598. $aclChangeResult = $this->setUserACL($userGuid, $aclString); //push that to user
  599. $this->logDebug('User ' . $login . ' ACL setting result: ' . print_r($aclChangeResult, true), 'info');
  600. } else {
  601. $this->logDebug('User not found in server objects tree: ' . $login, 'error');
  602. }
  603. return($result);
  604. }
  605. /**
  606. * Returns registered non system users as login=>guid
  607. *
  608. * @return array
  609. */
  610. public function getUserNames() {
  611. $userNames = array();
  612. $tmp = array();
  613. if (empty($this->trassirUsers)) {
  614. $this->getServerObjects();
  615. }
  616. if (!empty($this->trassirUsers)) {
  617. foreach ($this->trassirUsers as $user) {
  618. $tmp[] = $this->apiRequest('/settings/users/' . $user . '/name', 'apikey');
  619. }
  620. }
  621. if (!empty($tmp)) {
  622. foreach ($tmp as $userDetails) {
  623. if (isset($userDetails['value']) && (!in_array($userDetails['value'], $this->serviceAccountNames))) {
  624. $userGuid = str_replace('users/', '', $userDetails['directory']);
  625. $userGuid = str_replace('/', '', $userGuid);
  626. $userNames[$userDetails['value']] = $userGuid;
  627. }
  628. }
  629. }
  630. return ($userNames);
  631. }
  632. /**
  633. * Returns existing user GUID by its login
  634. *
  635. * @param string $userLogin
  636. *
  637. * @return string/bool
  638. */
  639. public function getUserGuid($userLogin) {
  640. $result = false;
  641. if (empty($this->trassirUsers)) {
  642. $this->getServerObjects();
  643. }
  644. if (isset($this->serverObjects['UserNames'])) {
  645. if (isset($this->serverObjects['UserNames'][$userLogin])) {
  646. $result = $this->serverObjects['UserNames'][$userLogin];
  647. }
  648. }
  649. return($result);
  650. }
  651. /**
  652. * Returns full array of some user settings by its guid
  653. *
  654. * @param string $guid
  655. *
  656. * @return array
  657. */
  658. public function getUserSettings($guid) {
  659. $result = array();
  660. $userSettingsTmp = $this->apiRequest('/settings/users/' . $guid . '/', 'sid');
  661. if (!empty($userSettingsTmp)) {
  662. $result = $userSettingsTmp;
  663. if (isset($userSettingsTmp['values'])) {
  664. foreach ($userSettingsTmp['values'] as $io => $each) {
  665. $optionData = $this->apiRequest('/settings/users/' . $guid . '/' . $each, 'sid');
  666. $result['fulldata'][$each] = $optionData;
  667. }
  668. }
  669. }
  670. return($result);
  671. }
  672. /**
  673. * Sets some user setting on Trassir Server by its guid
  674. *
  675. * @param string $guid
  676. * @param string $setting
  677. * @param string $value
  678. *
  679. * @return array
  680. */
  681. protected function setUserSettings($guid, $setting, $value) {
  682. $result = $this->apiRequest('/settings/users/' . $guid . '/' . $setting . '=' . $value, 'sid');
  683. $this->logDebug('Setting GUID '.$guid.' user setting: '.$setting.'='.$value, 'lld');
  684. return($result);
  685. }
  686. /**
  687. * Saves channel screenshot to local file system
  688. *
  689. * @param string $channel One of channel guids
  690. * @param string $folder folder to save shots
  691. * @param DateTime|null $timestamp take last available shot if timestamp is null
  692. *
  693. * @return string url to image
  694. */
  695. public function saveScreenshot($channel, $folder = 'exports', $timestamp = null) {
  696. $path = '';
  697. if ($timestamp) {
  698. $time = $timestamp->format('Ymd-His');
  699. } else {
  700. $time = '0';
  701. }
  702. $img = $this->sdkProtocol . '://' . $this->ip . ':' . $this->port . '/screenshot/' . $channel . '?timestamp=' . $time . '&sid=' . $this->sid;
  703. $path = $folder . '/shot_' . $channel . '_' . zb_rand_string(8) . $time . '.jpg';
  704. $curl = curl_init($img);
  705. curl_setopt($curl, CURLOPT_HEADER, 0);
  706. curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
  707. curl_setopt($curl, CURLOPT_BINARYTRANSFER, 1);
  708. curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0);
  709. curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);
  710. $content = curl_exec($curl);
  711. $response = json_decode($content, true);
  712. if ($response['success'] === 0) {
  713. //return ($response['error_code']);
  714. } else {
  715. curl_close($curl);
  716. if (file_exists($path)) {
  717. unlink($path);
  718. }
  719. $fp = fopen($path, 'x');
  720. if ($fp !== false) {
  721. fwrite($fp, $content);
  722. fclose($fp);
  723. }
  724. }
  725. return ($path);
  726. }
  727. /**
  728. * Returns URL to some channel video stream
  729. *
  730. * @param string $channel
  731. * @param string $stream should be main or sub
  732. * @param string $container should be mjpeg|flv|jpeg|hls
  733. * @param int $quality jpg container type quality between 0-100 (percents)
  734. * @param int $framerate 0 - realtime / 60000 - 1 frame per minute
  735. * @param string $customUrl - optional custom preview URL
  736. *
  737. * @return bool|string return url to live video stream or false on failure
  738. */
  739. public function getLiveVideoStream($channel, $stream = 'main', $container = 'mjpeg', $quality = 100, $framerate = 0, $customUrl = '') {
  740. $result = false;
  741. if ($container == 'mjpeg' OR $container == 'jpeg') {
  742. $requestUrl = '/get_video?channel=' . $channel . '&container=' . $container . '&stream=' . $stream . '&quality=' . $quality . '%&framerate=' . $framerate;
  743. } else {
  744. $requestUrl = '/get_video?channel=' . $channel . '&container=' . $container . '&stream=' . $stream . '&framerate=' . $framerate;
  745. }
  746. $token = $this->apiRequest($requestUrl, 'sidamp');
  747. if ($token['success'] == 1) {
  748. $videoToken = $token['token'];
  749. if (!empty($customUrl)) {
  750. //using custom preview URL
  751. if ($container != 'hls') {
  752. $result = $customUrl . '/' . $videoToken;
  753. } else {
  754. $result = $customUrl . '/hls/' . $videoToken . '/master.m3u8';
  755. }
  756. } else {
  757. //default case
  758. if ($container != 'hls') {
  759. $result = $this->httpVideoProtocol . '://' . trim($this->ip) . ':' . $this->httpVideoPort . '/' . $videoToken;
  760. } else {
  761. $result = $this->sdkProtocol . '://' . trim($this->ip) . ':' . $this->port . '/hls/' . $videoToken . '/master.m3u8';
  762. }
  763. }
  764. }
  765. return ($result);
  766. }
  767. /**
  768. * Returns channel recording type. Possible values: 1 - permanent, 2 - manual, 3 - on detector
  769. *
  770. * @param string $channel
  771. *
  772. * @return array
  773. */
  774. public function getChannelRecordMode($channel) {
  775. $result = array();
  776. $result = $this->apiRequest('/settings/channels/' . $channel . '/record_mode_local', 'apikey');
  777. if (!empty($result)) {
  778. $result = $result['value'];
  779. }
  780. return($result);
  781. }
  782. /**
  783. * Sets channel record mode. Possible values: 1 - permanent, 2 - manual, 3 - on detector
  784. *
  785. * @param string $channel
  786. * @param int $mode
  787. *
  788. * @return array
  789. */
  790. public function setChannelRecordMode($channel, $mode) {
  791. $result = $this->apiRequest('/settings/channels/' . $channel . '/record_mode_local=' . $mode, 'apikey');
  792. return($result);
  793. }
  794. /**
  795. * Returns array of all available IP cameras GUIDs
  796. *
  797. * @return array
  798. */
  799. protected function getCameras() {
  800. $result = array();
  801. $tmp = $this->apiRequest('/settings/ip_cameras/', 'sid');
  802. if (isset($tmp['subdirs'])) {
  803. if (!empty($tmp['subdirs'])) {
  804. foreach ($tmp['subdirs'] as $io => $each) {
  805. if ($each != 'ip_camera_add') {
  806. $result[$each] = $each;
  807. }
  808. }
  809. }
  810. }
  811. return($result);
  812. }
  813. /**
  814. * Returns camera IP by its GUID
  815. *
  816. * @param string $guid
  817. *
  818. * @return string
  819. */
  820. public function getCameraIp($guid) {
  821. $result = $this->apiRequest('/settings/ip_cameras/' . $guid . '/connection_ip', 'sid');
  822. $result = $result['value'];
  823. return($result);
  824. }
  825. /**
  826. * Returns array of available supported camera protocols (vendors)
  827. *
  828. * @return array
  829. */
  830. public function getCameraProtocols() {
  831. $result = $this->apiRequest('/settings/ip_cameras/ip_camera_add/', 'sid');
  832. $result = $result['subdirs'];
  833. return($result);
  834. }
  835. /**
  836. * Returns array of supported cameras for selected protocol
  837. *
  838. * @param string $protocol
  839. *
  840. * @return array
  841. */
  842. public function getCameraModels($protocol) {
  843. $result = array();
  844. $requestRaw = $this->apiRequest('/settings/ip_cameras/ip_camera_add/' . $protocol . '/available_models', 'sid');
  845. $requestRaw = @$requestRaw['value'];
  846. if (!empty($requestRaw)) {
  847. $requestRaw = explode(',', $requestRaw);
  848. if (!empty($requestRaw)) {
  849. foreach ($requestRaw as $io => $each) {
  850. $cleanName = str_replace('%20', ' ', $each);
  851. $result[$each] = $cleanName;
  852. }
  853. }
  854. }
  855. return($result);
  856. }
  857. /**
  858. * Creates new camera device on remote Trassir Server NVR
  859. *
  860. * @param string $protocol
  861. * @param string $model
  862. * @param string $ip
  863. * @param string $port
  864. * @param string $username
  865. * @param string $password
  866. *
  867. * @return array
  868. */
  869. public function createCamera($protocol, $model, $ip, $port, $username, $password) {
  870. //Setting camera IP
  871. $this->apiRequest('/settings/ip_cameras/ip_camera_add/' . $protocol . '/create_address=' . $ip, 'sid');
  872. //Setting camera port
  873. $this->apiRequest('/settings/ip_cameras/ip_camera_add/' . $protocol . '/create_port=' . $port, 'sid');
  874. //Setting camera login
  875. $this->apiRequest('/settings/ip_cameras/ip_camera_add/' . $protocol . '/create_username=' . $username, 'sid');
  876. //Setting camera password
  877. $this->apiRequest('/settings/ip_cameras/ip_camera_add/' . $protocol . '/create_password=' . $password, 'sid');
  878. //Setting camera model
  879. $this->apiRequest('/settings/ip_cameras/ip_camera_add/' . $protocol . '/create_model=' . $model, 'sid');
  880. //Camera creation
  881. $cameraCreateResult = $this->apiRequest('/settings/ip_cameras/ip_camera_add/' . $protocol . '/create_now=1', 'sid');
  882. return($cameraCreateResult);
  883. }
  884. /**
  885. * Returns array of all registered cameras as IP=>guid
  886. *
  887. * @return array
  888. */
  889. public function getAllCameraIps() {
  890. $result = array();
  891. $allCameras = $this->getCameras();
  892. if (!empty($allCameras)) {
  893. foreach ($allCameras as $io => $eachGuid) {
  894. $cameraIp = $this->getCameraIp($eachGuid);
  895. $result[$cameraIp] = $eachGuid;
  896. }
  897. }
  898. return($result);
  899. }
  900. /**
  901. * Disables/enables model mismatch warning on some cameras.
  902. *
  903. * @param string $cameraIp
  904. * @param int $state
  905. *
  906. * @return void
  907. */
  908. public function setModelMismatch($cameraIp, $state) {
  909. $allCams = $this->getAllCameraIps();
  910. if (isset($allCams[$cameraIp])) {
  911. $cameraGuid = $allCams[$cameraIp];
  912. if (!empty($cameraGuid)) {
  913. $this->apiRequest('/settings/ip_cameras/' . $cameraGuid . '/model_missmatch_off=' . $state, 'sid');
  914. $this->apiRequest('/settings/ip_cameras/' . $cameraGuid . '/grabber_enabled=0', 'sid');
  915. $this->apiRequest('/settings/ip_cameras/' . $cameraGuid . '/grabber_enabled=1', 'sid');
  916. }
  917. }
  918. }
  919. /**
  920. * Returns current some camera model mismatch warning state
  921. *
  922. * @param string $cameraIp
  923. *
  924. * @return int
  925. */
  926. public function getModelMismatch($cameraIp) {
  927. $result = '';
  928. $allCams = $this->getAllCameraIps();
  929. if (isset($allCams[$cameraIp])) {
  930. $cameraGuid = $allCams[$cameraIp];
  931. if (!empty($cameraGuid)) {
  932. $stateRaw = $this->apiRequest('/settings/ip_cameras/' . $cameraGuid . '/model_missmatch_off', 'sid');
  933. if (is_array($stateRaw)) {
  934. $result .= $stateRaw['value'];
  935. }
  936. }
  937. }
  938. return($result);
  939. }
  940. }