WeiKeMuServer.php 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. <?php
  2. namespace App\Servers\Weikemu;
  3. use App\Handlers\ExceptionTrait;
  4. use App\Handlers\ToolsHandler;
  5. use App\Servers\Weikemu\Transforms\BaseStationLocationTransform;
  6. use App\Servers\Weikemu\Transforms\ConfigTransform;
  7. use App\Servers\Weikemu\Transforms\ControlTransform;
  8. use App\Servers\Weikemu\Transforms\HeartTransform;
  9. use App\Servers\Weikemu\Transforms\LocationTransform;
  10. use App\Servers\Weikemu\Transforms\LoginTransform;
  11. use App\Servers\Weikemu\Transforms\ResponseTransform;
  12. use App\Servers\Weikemu\Transforms\SatelliteLocationTransform;
  13. use App\Servers\Weikemu\Transforms\StatusTransform;
  14. use App\Servers\Weikemu\Transforms\UrlConfigTransform;
  15. use App\Servers\Weikemu\Transforms\VoiceTransform;
  16. use App\Servers\Weikemu\Transforms\WarningTransform;
  17. use GatewayWorker\Lib\Gateway;
  18. class WeiKeMuServer
  19. {
  20. use ExceptionTrait, ToolsHandler;
  21. protected static $db;
  22. protected static $redis;
  23. protected static $mongo;
  24. /**
  25. * 根据box_no获取车的no
  26. * @param $box_no
  27. * @return mixed
  28. * User: Mead
  29. */
  30. private static $redis_bike_no_tags = 'box_no_and_bike_no';
  31. public static function main($client_id, $message, $data, $param)
  32. {
  33. //序号
  34. $number = $data[3] . $data[4];
  35. $param['msg_id'] = $number;
  36. //校检值
  37. $verification = implode('', array_slice($data, -2, 2));
  38. //消息长度
  39. $length = hexdec($data[6] . $data[7]);
  40. //消息内容
  41. $body = array_slice($data, 8, -2);
  42. if ($length !== count($body)) {
  43. self::log('length is error', "error", self::$LOG_MAJOR);
  44. return false;
  45. }
  46. if (!self::is_verification(array_slice($data, 2, -2), $verification)) {
  47. //校检失败
  48. self::log('verification is error', "error", self::$LOG_MAJOR);
  49. return false;
  50. }
  51. $cmd = $data[2];
  52. if ($cmd === '5e') {
  53. $imei = substr(self::stitching($body, 4, 8), 0, -1);
  54. } elseif ($cmd === '08') {
  55. $imei = substr(self::stitching($body, 19, 8), 0, -1);
  56. } else {
  57. $imei = substr(self::stitching($body, 18, 8), 0, -1);
  58. }
  59. self::initDatabases($param);
  60. $box_no = $imei;
  61. self::log($client_id . '==>' . $box_no, "log", self::$LOG_DEV);
  62. $_SESSION['box_no'] = $imei;
  63. if (!Gateway::getUidByClientId($client_id)) {
  64. Gateway::bindUid($client_id, $imei);
  65. }
  66. if (!isset($_SESSION['bike_no'])) {
  67. $_SESSION['bike_no'] = self::byBoxNoGetBikeNoStatic($box_no);
  68. }
  69. if (!Gateway::isUidOnline($imei)) {
  70. //离线检查
  71. if (self::$redis->exists('bike:offline:' . $box_no)) {
  72. self::log($box_no, 'EVENT_ONLINE', self::$LOG_MAJOR);
  73. $cols['is_link'] = \App\Maps\BikeMap::LINK_ONLINE;
  74. self::$db->update('bikes')->where('box_no = ' . $box_no)->cols($cols)->query();
  75. self::$redis->del('bike:offline:' . $box_no);
  76. }
  77. }
  78. if ($box_no == '868626049272449') {
  79. self::log($box_no, 'DEV', self::$LOG_MAJOR);
  80. }
  81. $response_body = '';
  82. switch ($cmd) {
  83. case '5a':
  84. //状态
  85. self::log('CMD==>状态', "log", self::$LOG_DEV);
  86. $response_body = (new StatusTransform($param))->main($body);
  87. break;
  88. case '5b':
  89. //登录
  90. // self::log('CMD==>登录', "log", self::$LOG_DEV);
  91. $response_body = (new LoginTransform($param))->main($body);
  92. break;
  93. case '5c':
  94. self::log('CMD==>控制', "log", self::$LOG_DEV);
  95. $response_body = (new ControlTransform($param))->main($body);
  96. break;
  97. case '5d':
  98. self::log('CMD==>声音', "log", self::$LOG_DEV);
  99. $response_body = (new VoiceTransform($param))->main($body);
  100. break;
  101. case '5e':
  102. self::log('CMD==>心跳', "log", self::$LOG_DEV);
  103. $response_body = (new HeartTransform($param))->main($body);
  104. break;
  105. case '51':
  106. //告警消息
  107. self::log('CMD==>告警消息', "log", self::$LOG_DEV);
  108. $response_body = (new WarningTransform($param))->main($body);
  109. break;
  110. case '52':
  111. //卫星位置消息
  112. self::log('CMD==>卫星位置消息', "log", self::$LOG_DEV);
  113. $response_body = (new SatelliteLocationTransform($param))->main($body);
  114. break;
  115. case '53':
  116. //基站位置消息
  117. self::log('CMD==>基站位置消息', "log", self::$LOG_DEV);
  118. $response_body = (new BaseStationLocationTransform($param))->main($body);
  119. break;
  120. case '54': // 实时追踪
  121. case '55': // 位置查询
  122. //基站位置消息
  123. self::log('CMD==>基站位置消息(实时)', "log", self::$LOG_DEV);
  124. $response_body = (new LocationTransform($param))->main($body);
  125. break;
  126. case '56':
  127. //配置消息
  128. self::log('CMD==>配置消息', "log", self::$LOG_DEV);
  129. $response_body = (new ConfigTransform($param))->main($body);
  130. break;
  131. case '5f':
  132. self::log('CMD==>域名配置', "log", self::$LOG_DEV);
  133. $response_body = (new UrlConfigTransform($param))->main($body);
  134. break;
  135. case '08':
  136. self::log('CMD==>响应', "log", self::$LOG_DEV);
  137. $response_body = (new ResponseTransform($param))->main($body);
  138. break;
  139. }
  140. if ($response_body === false) {
  141. self::log('==>', 'RESPONSE_LOG', self::$LOG_DEV);
  142. return false;
  143. }
  144. $response_body[0] = $cmd;
  145. if (is_array($response_body)) {
  146. $response = self::response($response_body, $number);
  147. self::log($response, 'RESPONSE_LOG', self::$LOG_DEV);
  148. Gateway::sendToCurrentClient('+NNMI,' . hex2bin(str_replace(' ', '', $response)));
  149. }
  150. self::log('<===========================================>', 'RESPONSE_LOG', self::$LOG_DEV);
  151. }
  152. /**
  153. * 验证数据
  154. * @param $data
  155. * @param $verification
  156. * @return bool
  157. * Author: Mead
  158. */
  159. private static function is_verification($data, $verification)
  160. {
  161. $n_verification = self::verification($data);
  162. return (bool)((string)$n_verification === (string)$verification);
  163. }
  164. /**
  165. * 校检
  166. * @param $data
  167. * @param $verification
  168. * @return bool
  169. * Author: Mead
  170. */
  171. protected static function verification($data)
  172. {
  173. $a = $b = 0;
  174. for ($i = 0; $i < count($data); $i++) {
  175. $a = $a + hexdec($data[$i]);
  176. $b = $a + $b;
  177. }
  178. return str_pad(substr(dechex($a), -2), 2, 0, STR_PAD_LEFT) . str_pad(substr(dechex($b), -2), 2, 0, STR_PAD_LEFT);
  179. }
  180. public static function initDatabases($param)
  181. {
  182. self::$db = $param['db'];
  183. self::$redis = $param['redis'];
  184. self::$mongo = $param['mongo'];
  185. }
  186. public static function byBoxNoGetBikeNoStatic($box_no)
  187. {
  188. return self::$redis->hget(self::$redis_bike_no_tags, $box_no);
  189. }
  190. /**
  191. * 处理响应包
  192. * @param $body
  193. * @param $number
  194. * @return string
  195. * Author: Mead
  196. */
  197. private static function response($body, $number)
  198. {
  199. $header = [
  200. '28',
  201. "{$number}",
  202. '00',
  203. '0003',
  204. ];
  205. $data = self::arr2str($header, $body);
  206. $data .= self::verification(explode(' ', $data));
  207. return self::format('4244' . $data . '0D0A');
  208. }
  209. private static function arr2str()
  210. {
  211. $args = func_get_args();
  212. $arr = '';
  213. foreach ($args as $arg) {
  214. if (is_array($arg)) {
  215. $arr .= implode('', $arg);
  216. } else {
  217. $arr .= str_replace(' ', '', $arg);
  218. }
  219. }
  220. return implode(' ', str_split($arr, 2));
  221. }
  222. private static function format($str)
  223. {
  224. return strtoupper(implode(' ', str_split(str_replace(' ', '', $str), 2)));
  225. }
  226. public static function outLine($client_id)
  227. {
  228. }
  229. }