FindBoxCoreSystem.php 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. <?php
  2. /**
  3. * @param array $array
  4. * @param array $keysToExtract
  5. * @return array
  6. * @author Open Mind
  7. * @date 28/03/2018
  8. * @time 09:13
  9. */
  10. namespace OpenMind\FindBox;
  11. use Exception;
  12. use OpenMind\System\System;
  13. function array_filter_keys(array $array, array $keysToExtract)
  14. {
  15. return array_intersect_key($array, array_flip($keysToExtract));
  16. }
  17. class FindBoxCoreSystem
  18. {
  19. private $Host;
  20. private $Port;
  21. private $Key;
  22. private $Pass;
  23. private $coreDetails;
  24. /**
  25. * CoreLabel constructor.
  26. *
  27. * @param string $host hostname of FindBox OS system
  28. * @param int $port
  29. * @param string $APIKey
  30. * @param string $Password
  31. * @throws Exception
  32. */
  33. public function __construct(string $host, int $port, string $APIKey, string $Password)
  34. {
  35. $this->Host = $host;
  36. $this->Port = $port;
  37. $this->Key = $APIKey;
  38. $this->Pass = $Password;
  39. Global $System;
  40. /** @var System $System */
  41. $Cache = $System->getCache();
  42. if (!$Cache->exists('FindBoxCoreSystem')) {
  43. $URI = '/1.0.0/index.php/getstatus/1.0.0/';
  44. $ret = $this->CallAPI($URI, "");
  45. if ($ret['err'] != 0)
  46. throw new Exception("Can't connect to FindBox server:<br/><br/>{$ret['value']}");
  47. if ($ret['err'] == 0 && $ret['value']['code'] == 0) {
  48. $details = $ret['value']['value'];
  49. $this->coreDetails = array_filter_keys($details, ['core.box_id', 'core.version']);
  50. }
  51. $Cache->set('FindBoxCoreSystem', $this->coreDetails, 3600);
  52. } else {
  53. $this->coreDetails = $Cache->get('FindBoxCoreSystem');
  54. }
  55. }
  56. /**
  57. * CallGetAPI make HTTP GET requests
  58. * @param string $URI full path of api url, for example "/1.0.0/index.php/smartesl.blink_special/1.0.0/"
  59. * @param string $Parameters
  60. * @param bool $skipResponse for faster communications, if response not need, you can skip this step
  61. * @return array converted from JSON response of request if present
  62. */
  63. public function CallAPI(string $URI, string $Parameters, bool $skipResponse = false): array
  64. {
  65. $bodyJSON = null;
  66. $auth = "Authorization: Basic " . base64_encode("{$this->Key}:{$this->Pass}") . "\r\n";
  67. $streamfbOS = @stream_socket_client("tcp://{$this->Host}:{$this->Port}", $errno, $errstr, 1);
  68. if (!$streamfbOS) {
  69. return $this->returnCode($errno, $errstr);
  70. } else {
  71. //$requestText = "{$method} {$URI}{$Parameters} HTTP/1.0\r\nHost: {$this->Host}\r\n{$auth}Accept: */*\r\nConnection: close\r\n\r\n";
  72. $requestBodyLength = strlen($Parameters);
  73. $requestText = "POST {$URI} HTTP/1.0\r\nHost: {$this->Host}\r\n{$auth}Accept: */*\r\nContent-Type: application/json\r\nContent-Length: {$requestBodyLength}\r\n\r\n{$Parameters}\r\n";
  74. //file_put_contents("request.txt", $requestText);
  75. fwrite($streamfbOS, $requestText);
  76. if (!$skipResponse) {
  77. $r = stream_get_contents($streamfbOS);
  78. list(, $bodyJSON) = explode("\r\n\r\n", $r, 2);
  79. }
  80. fclose($streamfbOS);
  81. }
  82. $bodyJSON = ($bodyJSON == null) ? "{}" : $bodyJSON;
  83. return $this->returnCode(0, $bodyJSON);
  84. }
  85. /**
  86. * Helper for make JSON return code
  87. *
  88. * @param int $errorCode
  89. * @param string $value
  90. * @return array
  91. */
  92. private function returnCode(int $errorCode, string $value): array
  93. {
  94. $val = json_decode($value, true) ?? $value;
  95. return array(
  96. "err" => $errorCode,
  97. "value" => $val);
  98. }
  99. public function BlinkUnassigned()
  100. {
  101. $URI = "/1.0.0/index.php/smartesl.blink_unassigned/2.0.0/";
  102. $this->CallAPI($URI, "", true);
  103. }
  104. /**
  105. * Save products into findbus database
  106. * @param string $barcode
  107. * @param string $name
  108. * @param array $dataFields Custom fields
  109. * @return array
  110. */
  111. public function SaveProducts(string $barcode, string $name, array $dataFields): array
  112. {
  113. $product = json_encode([[[
  114. "barcode" => $barcode,
  115. "name1" => $name,
  116. "datafields" => $dataFields
  117. ]]]);
  118. $URI = "/1.0.0/index.php/saveproducts/1.2.0/";
  119. return $this->CallAPI($URI, $product);
  120. }
  121. /**
  122. * Add label into findbox system and Bind it with a barcode
  123. *
  124. * @param string $labelId
  125. * @param string $barcode
  126. * @return array
  127. */
  128. public function Bind(string $labelId, string $barcode): array
  129. {
  130. $URI = "/1.0.0/index.php/smartesl.bind/1.1.0/";
  131. return $this->CallAPI($URI, "[\"{$labelId}\",\"{$barcode}\"]");
  132. }
  133. /**
  134. * Remove label from findbox system
  135. *
  136. * @param string $labelId
  137. * @return array
  138. */
  139. public function UnBind(string $labelId): array
  140. {
  141. // Retrieve barcode associated to the label
  142. $labelDetails = $this->CallAPI("/1.0.0/index.php/smartesl.getstatus/3.1.0/", "[[\"{$labelId}\"]]");
  143. // If RSSI exist, label it is binded to system
  144. if (isset($labelDetails['value']['value'][$labelId]['rssi'])) {
  145. $barcode = $labelDetails['value']['value'][$labelId]['data']['barcode'];
  146. $ret = $this->CallAPI("/1.0.0/index.php/smartesl.unbind/1.0.0/", "[\"{$labelId}\"]");
  147. if ($ret['err'] != 0)
  148. return $this->returnCode(1, 'Error on unbind');
  149. $ret = $this->CallAPI("/1.0.0/index.php/deleteproducts/1.0.0/", "[\"{$barcode}\"]");
  150. if ($ret['err'] != 0)
  151. return $this->returnCode(1, 'Error on deleteproducts');
  152. // All ok
  153. return $this->returnCode(0, '');
  154. } else
  155. return $this->returnCode(1, 'No label exist on Findbox');
  156. }
  157. /**
  158. * Check the response of FindBoxOS, return an array if no error, else NULL
  159. *
  160. * @param array $fbOS_Response
  161. * @return NULL|array
  162. */
  163. public function getLabelsFromResponse(array $fbOS_Response): ?array
  164. {
  165. // Check if response have field 'value' that is an array
  166. $haveArray = isset($fbOS_Response['value']['value']) && is_array($fbOS_Response['value']['value']);
  167. if (!$haveArray)
  168. return NULL;
  169. return $fbOS_Response['value']['value'];
  170. }
  171. /**
  172. * Request all label status to FindBox core.
  173. * If request is forced may require large amount of time to retrieve status directly from labels
  174. *
  175. * @param bool $force true = ask status directly to ESL and not from FindBox Core Cache
  176. *
  177. * @return null|array return array with labelID => status_struct
  178. */
  179. public function GetAllESLStatus($force = false): ?array
  180. {
  181. // Retrieve all labels
  182. $URI = '/1.0.0/index.php/smartesl.getstatus/4.0.0/[[],false]';
  183. $ret = $this->CallAPI($URI, "");
  184. if ($ret['err'] != 0)
  185. return null;
  186. $fbOSResponse = $this->getLabelsFromResponse($ret);
  187. if (!$fbOSResponse) {
  188. $this->log->write('GetAllESLStatus: ' . $ret['value']['value'], 'd/m/Y H:i:s');
  189. return null;
  190. }
  191. $labels = $fbOSResponse;
  192. $this->setTemplatesName($labels);
  193. if (!$force)
  194. return $labels;
  195. // Request status directly to ESL
  196. $eslStatus = [];
  197. foreach($labels as $labelID => $status) {
  198. // Filter for ONLINE labels only
  199. $labelStatus = strtoupper($status['data']['esl_state']);
  200. if ($force && in_array($labelStatus, ['OFFLINE', 'BLOCKED,FC']))
  201. continue;
  202. // Request status to ESL
  203. $URI = "/1.0.0/index.php/smartesl.getstatus/4.0.0/[[\"{$labelID}\"],true]";
  204. $fbOSResponse = $this->getLabelsFromResponse($this->CallAPI($URI, ""));
  205. if ($fbOSResponse != null) {
  206. $eslStatus = array_merge($eslStatus, $fbOSResponse);
  207. }
  208. }
  209. return $eslStatus;
  210. }
  211. /**
  212. * Add 'data.template_name' to the structure returned by GetStatus
  213. *
  214. * @param array $status
  215. */
  216. private function setTemplatesName(&$status)
  217. {
  218. $tplNameList = [];
  219. $fb_template = $this->CallAPI('/1.0.0/index.php/smartesl.gettemplates/1.0.0/', '[]');
  220. $templates = $this->getLabelsFromResponse($fb_template);
  221. if ($templates != null) {
  222. foreach($templates as $item) {
  223. $tplNameList[$item['template_id']] = $item['name'];
  224. }
  225. }
  226. foreach($status as &$esl) {
  227. if (count($tplNameList) == 0) {
  228. $esl['data']['template_name'] = '';
  229. continue;
  230. }
  231. $tplName = $tplNameList[$esl['data']['template_id']];
  232. $esl['data']['template_name'] = $tplName ?? '{NO_NAME}';
  233. }
  234. }
  235. }