WeiKeMuServer.php 8.2 KB

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