BikeControl.php 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940
  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. * User: Mead
  5. * Date: 2019/9/5
  6. * Time: 9:36 PM
  7. */
  8. namespace App\Handlers\Weikemu;
  9. use GatewayClient\Gateway;
  10. use Illuminate\Support\Facades\Log;
  11. use Illuminate\Support\Facades\Redis;
  12. class BikeControl
  13. {
  14. private static $start = '42 44';
  15. private static $registerAddress = 'node1:2238';
  16. // 还车成功,请规范停车
  17. const VIDEO_RETURN_BIKE = '01';
  18. // 开锁成功
  19. const VIDEO_OPEN_LOCK = '02';
  20. // 请文明骑行规范停车
  21. const VIDEO_CIVILIZATION = '03';
  22. // 车辆已断电请回到服务区
  23. const VIDEO_POWER_FAILURE = '04';
  24. // 车辆已下线
  25. const VIDEO_OFFLINE = '05';
  26. // 非法移动
  27. const VIDEO_ILLEGAL_MOVE = '06';
  28. // 临停成功将持续计费
  29. const VIDEO_FIND_BIKE = '07';
  30. // 向着诗和远方我们继续出发吧
  31. const VIDEO_KEEP_GOING = '08';
  32. // 小喵在这里
  33. const VIDEO_BIKE_HERE = '09';
  34. // 靠近服务区边缘,服务区外将断电 10
  35. const VIDEO_BATTERY_EDGE = '0A';
  36. // 换电完成您辛苦了 11
  37. const VIDEO_POWER_CHANGE = '0B';
  38. // 您已出服务区请尽快骑回 12
  39. const VIDEO_GO_BEYOND = '0C';
  40. // 夜间出行注意安全 13
  41. const VIDEO_NIGHT_SAFETY = '0D';
  42. // 当前为禁停区禁止停车 14
  43. const VIDEO_NO_STOPPING = '0E';
  44. // 空 15
  45. // 小喵生病了试试别的车吧 16
  46. const VIDEO_USE_OTHER = '10';
  47. //电量过低 17
  48. const VIDEO_LOW_POWER = '11';
  49. // 主人即将回来试试别的车吧 18
  50. const VIDEO_OCCUPIED = '12';
  51. //小猫被预约了试试别的车吧 19
  52. const VIDEO_RESERVED = '13';
  53. // (带告警音)请停止偷窃行为 20
  54. const VIDEO_WARNING = '14';
  55. // 您已进入禁停区 21
  56. const VIDEO_NO_STOP_ZONE = '15';
  57. // 车辆已报警请勿移动 22
  58. const VIDEO_ALARMED = '16';
  59. //请停止偷窃行为 23
  60. const VIDEO_NO_STEALING = '17';
  61. // 设备已绑定 24
  62. const VIDEO_BOUND = '18';
  63. // 小喵摔倒了
  64. const VIDEO_FALL = '19';
  65. const CACHE_KEY = 'cache:select';
  66. /**
  67. * 播放语音
  68. * @param $box_no
  69. * @return bool
  70. * User: Mead
  71. */
  72. public static function playVoice($box_no, $voice_no, $msg_id = false)
  73. {
  74. $cmd = "2A";
  75. $body = [
  76. self::getMsgId(),
  77. '01',
  78. $voice_no,
  79. 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF',
  80. 'FF FF FF FF',
  81. 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF',
  82. 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF',
  83. ];
  84. $send_msg = self::makeSendMsg($cmd, $body);
  85. return self::send($box_no, $send_msg, $msg_id);
  86. }
  87. /**
  88. * queryCmd 3.2.1 查询指令
  89. *
  90. * @param $box_no
  91. * @return bool
  92. * @author Fx
  93. *
  94. */
  95. public static function queryCmd($box_no, $str2 = '00111101')
  96. {
  97. $cmd = "2B";
  98. $body = [
  99. self::getMsgId(),
  100. str_pad(base_convert($str2, 2, 16), 2, 0, STR_PAD_LEFT)
  101. ];
  102. $send_msg = self::makeSendMsg($cmd, $body);
  103. return self::send($box_no, $send_msg, false);
  104. }
  105. /**
  106. * electricSwitchControl 电门控制
  107. *
  108. * @param $box_no
  109. * @param $control 01 电门开启; 00 电门关闭(关闭防盗开关);02 电门关闭(开启防盗开关);
  110. * @return bool
  111. * @author Fx
  112. *
  113. */
  114. public static function electricSwitchControl($box_no, $control = "01")
  115. {
  116. $cmd = "2D";
  117. $msg_id = self::getMsgId();
  118. $body = [
  119. $msg_id,
  120. $control,// 01 电门开启; 00 电门关闭(关闭防盗开关);02 电门关闭(开启防盗开关);
  121. ];
  122. $send_msg = self::makeSendMsg($cmd, $body);
  123. return self::send($box_no, $send_msg, $msg_id);
  124. }
  125. /**
  126. * realLocation 3.2.2 实时位置上报参数设置
  127. *
  128. * @param $box_no
  129. * @param string $control 01:实时追踪开启,00:实时追踪关闭
  130. * @param int $interval 上报间隔 秒 量化值30
  131. * @param int $continued 持续时长(1-43200) 分钟
  132. * @return bool
  133. * @author Fx
  134. *
  135. */
  136. public static function realLocation($box_no, $control = "01", $interval = 1, $continued = 60)
  137. {
  138. $cmd = "23";
  139. $body = [
  140. self::getMsgId(),
  141. $control,// 1:实时追踪开启,0:实时追踪关闭
  142. str_pad(base_convert($interval, 10, 16), 4, 0, STR_PAD_LEFT),//上报间隔
  143. str_pad(base_convert($continued, 10, 16), 4, 0, STR_PAD_LEFT),//持续时长(1-43200)
  144. ];
  145. $send_msg = self::makeSendMsg($cmd, $body);
  146. return self::send($box_no, $send_msg, false);
  147. }
  148. /**
  149. * multipleConfigsSetting 3.2.3 综合配置参数设置
  150. *
  151. * @param $box_no
  152. * @param $arr
  153. * @return bool
  154. * @author Fx
  155. *
  156. */
  157. public static function multipleConfigsSetting($box_no, $arr)
  158. {
  159. $cmd = "2C";
  160. // ['ip' => $ip,'port' => $port,'bluetooth_name' => $bluetooth_name,'bluetooth_token' => $bluetooth_token,
  161. // 'is_auto_lock' => $is_auto_lock, 'auto_lock_time' => $auto_lock_time,
  162. // 'is_displacement' => $is_displacement, 'displacement_radius' => $displacement_radius,
  163. // 'is_shock' => $is_shock,
  164. // 'is_temperature' => $is_temperature,'temperature' => $temperature,
  165. // 'is_speeding' => $is_speeding,'speeding'=>$speeding,
  166. // 'motion_position_sampling_interval'=>$motion_position_sampling_interval,
  167. // 'motion_position_reporting_interval'=>$motion_position_reporting_interval,
  168. // 'static_position_reporting_interval'=>$static_position_reporting_interval];
  169. $ip = $arr['ip'];
  170. $port = $arr['port'];
  171. $bluetooth_name = $arr['bluetooth_name']; // 蓝牙名称
  172. $bluetooth_token = $arr['bluetooth_token']; //蓝牙token
  173. $is_auto_lock = $arr['is_auto_lock']; // 是否开启自动落锁1:自动落锁开启;0:关闭自动落锁
  174. $auto_lock_time = str_pad(base_convert($arr['auto_lock_time'], 10, 2), 7, 0, STR_PAD_LEFT); // 自动落锁时长,量化单位1分钟
  175. $is_displacement = $arr['is_displacement']; // 位移告警开启设置1:位移告警开启;0: 位移告警关闭
  176. $displacement_radius = str_pad(base_convert($arr['displacement_radius'], 10, 2), 7, 0, STR_PAD_LEFT); // 位移告警半径门限,取值范围0~126,量化单位10米
  177. $is_shock = $arr['is_shock'];//震动告警开启设置1:震动告警开启,0:震动告警关闭
  178. $is_temperature = $arr['is_temperature'];//温度告警开启设置。1:温度告警开启;0:温度告警关闭
  179. $temperature = str_pad(base_convert($arr['temperature'], 10, 2), 7, 0, STR_PAD_LEFT); // 温度告警门限,取值范围0~126,
  180. $is_speeding = $arr['is_speeding']; // 超速告警开启设置。1:超速告警开启;0:超速告警关闭
  181. $speeding = str_pad(base_convert($arr['speeding'] * 2, 10, 2), 7, 0, STR_PAD_LEFT); // 超速告警门限 量化单位2km/h,范围 0~126
  182. $motion_position_sampling_interval = $arr['motion_position_sampling_interval']; // 运动状态,位置采样间隔设置(默认1秒)
  183. $motion_position_reporting_interval = $arr['motion_position_reporting_interval']; // 运动状态,位置上报间隔设置
  184. $static_position_reporting_interval = $arr['static_position_reporting_interval']; // 静止状态,位置上报间隔设置
  185. $msg_id = self::getMsgId();
  186. $body = [
  187. $msg_id,
  188. str_pad(base_convert($motion_position_sampling_interval, 10, 16), 2, 0, STR_PAD_LEFT),// 运动状态,位置采样间隔设置(默认1秒)
  189. str_pad(base_convert($motion_position_reporting_interval, 10, 16), 2, 0, STR_PAD_LEFT),// 运动状态,位置上报间隔设置
  190. str_pad(base_convert($static_position_reporting_interval, 10, 16), 4, 0, STR_PAD_LEFT),// 静止状态,位置上报间隔设置
  191. str_pad(base_convert($displacement_radius . $is_displacement, 2, 16), 2, 0, STR_PAD_LEFT),// 位移告警
  192. str_pad(base_convert('0000000' . $is_shock, 2, 16), 2, 0, STR_PAD_LEFT),// 震动告警
  193. str_pad(base_convert($temperature . $is_temperature, 2, 16), 2, 0, STR_PAD_LEFT),// 温度告警
  194. str_pad(base_convert($speeding . $is_speeding, 2, 16), 2, 0, STR_PAD_LEFT),// 超速告警
  195. str_pad(base_convert($auto_lock_time . $is_auto_lock, 2, 16), 2, 0, STR_PAD_LEFT),// 自动落锁
  196. str_pad(base_convert($port, 10, 16), 4, 0, STR_PAD_LEFT),// 自动落锁
  197. str_pad(base_convert($ip, 10, 16), 8, 0, STR_PAD_LEFT),// 自动落锁
  198. str_pad($bluetooth_name, 10, 0, STR_PAD_LEFT),
  199. str_pad(base_convert($bluetooth_token, 10, 16), 8, 0, STR_PAD_LEFT),// 自动落锁
  200. '00 00 00 00 00 00'
  201. ];
  202. $send_msg = self::makeSendMsg($cmd, $body);
  203. return self::send($box_no, $send_msg, $msg_id);
  204. }
  205. public static function setBoxSetting($box_no, $arr)
  206. {
  207. $cmd = "2C";
  208. $auto_lock_time = str_pad(base_convert($arr['auto_lock_time'], 10, 2), 7, 0, STR_PAD_LEFT); // 自动落锁时长,量化单位1分钟
  209. $ipArr = explode('.', $arr['ip']);
  210. $ip =
  211. $msg_id = self::getMsgId();
  212. $body = [
  213. $msg_id,
  214. 'FF',// 运动状态,位置采样间隔设置(默认1秒)
  215. str_pad(base_convert($arr['motion_position_reporting_interval'], 10, 16), 2, 0, STR_PAD_LEFT),// 运动状态,位置上报间隔设置
  216. str_pad(base_convert($arr['static_position_reporting_interval'], 10, 16), 4, 0, STR_PAD_LEFT),// 静止状态,位置上报间隔设置
  217. 'FF',// 位移告警
  218. 'FF',// 震动告警
  219. 'FF',// 温度告警
  220. 'FF',// 超速告警
  221. str_pad(base_convert($auto_lock_time . '1', 2, 16), 2, 0, STR_PAD_LEFT),// 自动落锁
  222. 'FF FF',
  223. //str_pad(base_convert($arr['port'], 10, 16), 4, 0, STR_PAD_LEFT),// port
  224. 'FF FF FF FF',
  225. // str_pad(base_convert($arr['ip'], 10, 16), 8, 0, STR_PAD_LEFT),// ip
  226. 'FF FF FF FF FF FF FF FF FF FF',// 20位
  227. 'FF FF FF FF ',//
  228. 'FF FF FF FF FF FF'
  229. ];
  230. $send_msg = self::makeSendMsg($cmd, $body);
  231. // Log::info($send_msg);
  232. return self::send($box_no, $send_msg, $msg_id);
  233. }
  234. /**
  235. * reboot 重启中控
  236. *
  237. * @param $box_no
  238. * @param $reboot string 11:重启升级;01:重启不升级
  239. * @param $ip string 重启升级地址(域名或IP地址)
  240. * @param $port int 重启升级端口号
  241. * @param $path string 重启升级路径
  242. * @param $upFile string 重启升级文件名称
  243. * @return bool
  244. * @author Fx
  245. *
  246. */
  247. public static function reboot($box_no, $reboot = "01", $ip, $port, $path, $upFile)
  248. {
  249. $cmd = "25";
  250. $reboot = '000000' . $reboot; // 11:重启升级;01:重启不升级
  251. $msg_id = self::getMsgId();
  252. $body = [
  253. $msg_id,
  254. self::str2Hex($reboot, 2, 8),
  255. self::char2Hex($ip, 20),
  256. self::str2Hex($port, 10, 8),
  257. self::char2Hex($path, 20),
  258. self::char2Hex($upFile, 20),
  259. ];
  260. $send_msg = self::makeSendMsg($cmd, $body);
  261. return self::send($box_no, $send_msg, $msg_id);
  262. }
  263. /**
  264. * nowBikeBatteryMSG 从定位包中获取电量
  265. *
  266. * @param $box_no
  267. * @return bool
  268. * @author Fx
  269. *
  270. */
  271. public static function nowBikeBatteryMSG($box_no)
  272. {
  273. return self::nowBikeLocation($box_no);
  274. }
  275. public static function rebootBox($box_no)
  276. {
  277. $cmd = "25";
  278. $msg_id = self::getMsgId();
  279. $body = [
  280. $msg_id,
  281. '01',// 0X02:重启升级;0X01:重启不升级
  282. 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF',// ip 20 bytes
  283. 'FF FF FF FF FF FF FF FF FF FF ', // PORT 10 BYTES
  284. 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF', // 重启升级路径
  285. 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF', // 重启升级文件名称
  286. ];
  287. $send_msg = self::makeSendMsg($cmd, $body);
  288. return self::send($box_no, $send_msg, $msg_id);
  289. }
  290. public static function maxecuspeedToMaxspeedpercent($maxecuspeed = 7)
  291. {
  292. $MAXSPEEDPERCENT = 100;
  293. switch ($maxecuspeed) {
  294. case 1:
  295. $MAXSPEEDPERCENT = 70;
  296. break;
  297. case 2:
  298. $MAXSPEEDPERCENT = 75;
  299. break;
  300. case 3:
  301. $MAXSPEEDPERCENT = 80;
  302. break;
  303. case 4:
  304. $MAXSPEEDPERCENT = 85;
  305. break;
  306. case 5:
  307. $MAXSPEEDPERCENT = 90;
  308. break;
  309. case 6:
  310. $MAXSPEEDPERCENT = 95;
  311. break;
  312. case 7:
  313. $MAXSPEEDPERCENT = 100;
  314. break;
  315. }
  316. return $MAXSPEEDPERCENT;
  317. }
  318. /**
  319. * settingVoice 语音设置
  320. *
  321. * @param $box_no
  322. * @param $voice_no
  323. * @param $ip
  324. * @param $port
  325. * @param $path
  326. * @param $upFile
  327. * @return bool
  328. * @author Fx
  329. *
  330. */
  331. public static function settingVoice($box_no, $voice_no, $ip, $port, $path, $upFile)
  332. {
  333. $cmd = "2A";
  334. $msg_id = self::getMsgId();
  335. $body = [
  336. $msg_id,
  337. '00',
  338. self::str2Hex($voice_no, 10, 2),
  339. self::char2Hex($ip, 20),
  340. self::str2Hex($port, 10, 8),
  341. self::char2Hex($path, 20),
  342. self::char2Hex($upFile, 20),
  343. ];
  344. $send_msg = self::makeSendMsg($cmd, $body);
  345. return self::send($box_no, $send_msg, $msg_id);
  346. }
  347. /**
  348. * guardSwitch 3.2.7 防盗开关设置
  349. *
  350. * @param $box_no
  351. * @param $control 00:关闭 01:开启
  352. * @return bool
  353. * @author Fx
  354. *
  355. */
  356. public static function guardSwitch($box_no, $control)
  357. {
  358. $cmd = "2E";
  359. $msg_id = self::getMsgId();
  360. $body = [
  361. $msg_id,
  362. $control
  363. ];
  364. $send_msg = self::makeSendMsg($cmd, $body);
  365. return self::send($box_no, $send_msg, $msg_id);
  366. }
  367. /**
  368. * batterySwitch 3.2.8 电池仓开关设置
  369. *
  370. * @param $box_no
  371. * @return bool
  372. * @author Fx
  373. *
  374. */
  375. public static function openBatteryLock($box_no)
  376. {
  377. $cmd = "2F";
  378. $msg_id = self::getMsgId();
  379. $body = [
  380. $msg_id,
  381. '01',
  382. ];
  383. $send_msg = self::makeSendMsg($cmd, $body);
  384. return self::send($box_no, $send_msg, $msg_id);
  385. }
  386. /**
  387. * limitSpeed 限速
  388. *
  389. * @param $box_no
  390. * @param $limit int 限速[%]
  391. * @return bool
  392. * @author Fx
  393. *
  394. */
  395. public static function limitSpeed($box_no, $limit)
  396. {
  397. $cmd = "30";
  398. $body = [
  399. self::getMsgId(),
  400. self::str2Hex($limit, 10, 2),// 限速[%]
  401. ];
  402. $send_msg = self::makeSendMsg($cmd, $body);
  403. return self::send($box_no, $send_msg, false);
  404. }
  405. /**
  406. * undervoltageProtection 3.2.10 控制器欠压保护设置
  407. *
  408. * @param $box_no
  409. * @param $limit int 控制器欠压保护值,量单位1mv
  410. * @return bool
  411. * @author Fx
  412. *
  413. */
  414. public static function undervoltageProtection($box_no, $limit)
  415. {
  416. $cmd = "31";
  417. $body = [
  418. self::getMsgId(),
  419. self::str2Hex($limit, 10, 4),// 限速[%]
  420. ];
  421. $send_msg = self::makeSendMsg($cmd, $body);
  422. return self::send($box_no, $send_msg, false);
  423. }
  424. /**
  425. * currentLimitingProtection 3.2.11 控制器限流保护设置
  426. *
  427. * @param $box_no
  428. * @param $limit int 控制器限流保护值,量化单位1mA
  429. * @return bool
  430. * @author Fx
  431. *
  432. */
  433. public static function currentLimitingProtection($box_no, $limit)
  434. {
  435. $cmd = "32";
  436. $body = [
  437. self::getMsgId(),
  438. self::str2Hex($limit, 10, 4),//
  439. ];
  440. $send_msg = self::makeSendMsg($cmd, $body);
  441. return self::send($box_no, $send_msg, false);
  442. }
  443. /**
  444. * slowReboot 3.2.12 控制器缓启动设置
  445. *
  446. * @param $box_no
  447. * @param $control string 01,缓启动;00,快启动
  448. * @return bool
  449. * @author Fx
  450. *
  451. */
  452. public static function slowReboot($box_no, $control)
  453. {
  454. $cmd = "33";
  455. $body = [
  456. self::getMsgId(),
  457. $control,
  458. ];
  459. $send_msg = self::makeSendMsg($cmd, $body);
  460. return self::send($box_no, $send_msg, false);
  461. }
  462. /**
  463. * lampSwitch 3.2.13 控制器大灯设置
  464. *
  465. * @param $box_no
  466. * @param $control string 01,大灯开;00,大灯关
  467. * @return bool
  468. * @author Fx
  469. *
  470. */
  471. public static function lampSwitch($box_no, $control)
  472. {
  473. $cmd = "34";
  474. $body = [
  475. self::getMsgId(),
  476. $control,
  477. ];
  478. $send_msg = self::makeSendMsg($cmd, $body);
  479. return self::send($box_no, $send_msg, false);
  480. }
  481. /**
  482. * orderStatus
  483. *
  484. * @param $box_no
  485. * @param $control string 01:接单开启;00:接单关闭
  486. * @return bool
  487. * @author Fx
  488. *
  489. */
  490. public static function orderStatus($box_no, $control)
  491. {
  492. $cmd = "35";
  493. $body = [
  494. self::getMsgId(),
  495. $control,
  496. ];
  497. $send_msg = self::makeSendMsg($cmd, $body);
  498. return self::send($box_no, $send_msg, false);
  499. }
  500. /**
  501. * nowBikeLocation 立即定位
  502. *
  503. * @param $box_no
  504. * @return bool
  505. * @author Fx
  506. *
  507. */
  508. public static function nowBikeLocation($box_no)
  509. {
  510. return self::queryCmd($box_no, '00000001');
  511. }
  512. /**
  513. * openLock 开锁
  514. *
  515. * @param $box_no
  516. * @return bool
  517. * @author Fx
  518. *
  519. */
  520. public static function openLock($box_no)
  521. {
  522. // $re = self::electricSwitchControl($box_no, '01');
  523. // if ($re) {
  524. // self::orderStatus($box_no, '01');
  525. // self::playVoice($box_no, self::VIDEO_OPEN_LOCK);
  526. // return true;
  527. // }
  528. // return false;
  529. self::orderStatus($box_no, '01');
  530. self::playVoice($box_no, self::VIDEO_OPEN_LOCK);
  531. self::electricSwitchControl($box_no, '01');
  532. return true;
  533. }
  534. /**
  535. * closeLock 关锁 (设防)
  536. *
  537. * @param $box_no
  538. * @return bool
  539. * @author Fx
  540. *
  541. */
  542. public static function closeLock($box_no)
  543. {
  544. // $re = self::electricSwitchControl($box_no, '02');
  545. // if ($re) {
  546. // self::orderStatus($box_no, '00');
  547. // self::playVoice($box_no, self::VIDEO_RETURN_BIKE);
  548. // return true;
  549. // }
  550. // return false;
  551. self::orderStatus($box_no, '00');
  552. self::playVoice($box_no, self::VIDEO_RETURN_BIKE);
  553. self::electricSwitchControl($box_no, '02');
  554. return true;
  555. }
  556. /**
  557. * closeLock 临时关锁 (设防)
  558. *
  559. * @param $box_no
  560. * @return bool
  561. * @author Fx
  562. *
  563. */
  564. public static function temporaryCloseLock($box_no)
  565. {
  566. self::playVoice($box_no, self::VIDEO_FIND_BIKE);
  567. return self::electricSwitchControl($box_no, '02');
  568. }
  569. /**
  570. * temporaryOpnLock 临时开锁
  571. *
  572. * @param $box_no
  573. * @return bool
  574. * @author Fx
  575. *
  576. */
  577. public static function temporaryOpnLock($box_no)
  578. {
  579. self::playVoice($box_no, self::VIDEO_KEEP_GOING);
  580. return self::electricSwitchControl($box_no, '01');
  581. }
  582. /**
  583. * closeLockNoGuard 关锁 (不设防) 失能
  584. *
  585. * @param $box_no
  586. * @return bool
  587. * @author Fx
  588. *
  589. */
  590. public static function outAreaLoseElectric($box_no)
  591. {
  592. self::playVoice($box_no, self::VIDEO_GO_BEYOND);
  593. return self::electricSwitchControl($box_no, '00');
  594. }
  595. /**
  596. * outAreaGetElectric 开锁 获能
  597. *
  598. * @param $box_no
  599. * @return bool
  600. * @author Fx
  601. *
  602. */
  603. public static function outAreaGetElectric($box_no)
  604. {
  605. self::playVoice($box_no, self::VIDEO_KEEP_GOING);
  606. return self::electricSwitchControl($box_no, '01');
  607. }
  608. /**
  609. * 寻铃
  610. * @param $box_no
  611. * @return bool
  612. * Author: Mead
  613. */
  614. public static function bellBike($box_no)
  615. {
  616. return self::playVoice($box_no, self::VIDEO_BIKE_HERE, true);
  617. }
  618. public static function queryConfig($box_no, $str2 = '00000100')
  619. {
  620. $cmd = "2B";
  621. $msg_id = self::getMsgId();
  622. $body = [
  623. $msg_id,
  624. str_pad(base_convert($str2, 2, 16), 2, 0, STR_PAD_LEFT)
  625. ];
  626. $send_msg = self::makeSendMsg($cmd, $body, $msg_id);
  627. return self::send($box_no, $send_msg, $msg_id);
  628. }
  629. /**
  630. * 解析车辆返回数据
  631. * @param $data
  632. * @return bool|mixed
  633. */
  634. public static function decodeData($data, $decode = true)
  635. {
  636. $array = explode('||', $data);
  637. if (count($array) !== 2) return false;
  638. list($type, $value) = $array;
  639. if (!$decode) return $value;
  640. switch ($type) {
  641. case 'string':
  642. return $value;
  643. break;
  644. case 'bool':
  645. return (boolean)$data;
  646. break;
  647. case 'array':
  648. return json_decode($value);
  649. }
  650. return false;
  651. }
  652. /**
  653. * 获取序号(msg_id)
  654. * @return string
  655. * Author: Mead
  656. */
  657. private static function getMsgId()
  658. {
  659. $msg_id = str_pad(dechex(rand(0, 65535)), 4, "0", STR_PAD_LEFT);
  660. return $msg_id;
  661. }
  662. /**
  663. * str2Hex 其他进制转16进制
  664. *
  665. * @param $str string 需要转的数据
  666. * @param $frombase int 需要转的进制
  667. * @param $pad_length int 长度
  668. * @return string
  669. * @author Fx
  670. *
  671. */
  672. private static function str2Hex($str, $frombase, $pad_length)
  673. {
  674. return str_pad(base_convert($str, $frombase, 16), $pad_length, 0, STR_PAD_LEFT);
  675. }
  676. /**
  677. * char2Hex char 转16进制
  678. *
  679. * @param $char
  680. * @param $pad_length
  681. * @return string
  682. * @author Fx
  683. *
  684. */
  685. private static function char2Hex($char, $pad_length)
  686. {
  687. return str_pad(bin2hex($char), $pad_length, 0, STR_PAD_LEFT);
  688. }
  689. public static function getBikeResponse($box_no, $msg_id, $decode = true)
  690. {
  691. $redis = Redis::connection();
  692. $response = false;
  693. for ($i = 1; $i <= 30; $i++) {
  694. usleep(500000);
  695. $data = $redis->get(self::CACHE_KEY . ':' . $box_no . ':' . $msg_id);
  696. if ($data) {
  697. $response = self::decodeData($data, $decode);
  698. break;
  699. }
  700. }
  701. return $response;
  702. }
  703. /**
  704. * 发送数据
  705. * @param $box_no
  706. * @param $msg
  707. * @return bool
  708. * User: Mead
  709. */
  710. private static function send($box_no, $msg, $msg_id = false, $decode = true)
  711. {
  712. Gateway::$registerAddress = config('bike.bike_control_register_address');
  713. if (Gateway::isUidOnline($box_no)) {
  714. Gateway::sendToUid($box_no, '+NNMI,' . hex2bin(str_replace(' ', '', $msg . '0D0A')));
  715. if ($msg_id !== false) {
  716. $redis = Redis::connection();
  717. $response = false;
  718. $msg_id = strtolower(substr($msg, 6, 4));
  719. for ($i = 1; $i <= 40; $i++) {
  720. usleep(500000);
  721. $data = $redis->get(self::CACHE_KEY . ':' . $box_no . ':' . $msg_id);
  722. if ($data) {
  723. Log::error('检查key:' . $msg_id);
  724. Log::error($data);
  725. $response = self::decodeData($data, $decode);
  726. break;
  727. }
  728. if ($i == 20) {
  729. //重试一次
  730. Gateway::sendToUid($box_no, '+NNMI,' . hex2bin(str_replace(' ', '', $msg . '0D0A')));
  731. }
  732. }
  733. return $response;
  734. }
  735. return true;
  736. }
  737. return false;
  738. }
  739. /**
  740. * 组装命令
  741. * @param $cmd
  742. * @param $msgID
  743. * @return string
  744. * User: Mead
  745. */
  746. private static function makeSendMsg($cmd, $body, $msg_id = false, $length = false)
  747. {
  748. if (is_array($body)) {
  749. $body = self::arr2arr($body);
  750. }
  751. if (is_string($body)) {
  752. $body = str_split($body, 2);
  753. }
  754. if ($length !== false) {
  755. $length = str_pad($length, 4, '0', STR_PAD_LEFT);
  756. } else {
  757. $length = str_pad(dechex(count($body)), 4, '0', STR_PAD_LEFT);
  758. }
  759. if ($msg_id === false) {
  760. $msg_id = self::getMsgId();
  761. }
  762. $header = [
  763. $cmd,
  764. $msg_id,
  765. '00',
  766. $length
  767. ];
  768. $response = self::formatArr($header, $body);
  769. $response[] = self::verification($response);
  770. return self::format(self::$start . implode('', $response));
  771. }
  772. /**
  773. * 校检
  774. * @param $data
  775. * @param $verification
  776. * @return bool
  777. * Author: Mead
  778. */
  779. protected static function verification($data)
  780. {
  781. $a = $b = 0;
  782. for ($i = 0; $i < count($data); $i++) {
  783. $a = $a + hexdec($data[$i]);
  784. $b = $a + $b;
  785. }
  786. return str_pad(substr(dechex($a), -2), 2, 0, STR_PAD_LEFT) . str_pad(substr(dechex($b), -2), 2, 0, STR_PAD_LEFT);
  787. }
  788. /**
  789. * 格式数组
  790. * @param $arr
  791. * @return array
  792. * User: Mead
  793. */
  794. private static function arr2arr($arr)
  795. {
  796. $arr = implode('', $arr);
  797. return str_split(str_replace(' ', '', $arr), 2);
  798. }
  799. /**
  800. * 合并数组
  801. * @return array
  802. * User: Mead
  803. */
  804. private static function formatArr()
  805. {
  806. $args = func_get_args();
  807. $arr = '';
  808. foreach ($args as $arg) {
  809. $arr .= implode('', $arg);
  810. }
  811. return str_split($arr, 2);
  812. }
  813. /**
  814. * 格式字符
  815. * @param $str
  816. * @return string
  817. * User: Mead
  818. */
  819. private static function format($str)
  820. {
  821. return strtoupper(implode('', str_split(str_replace(' ', '', $str), 2)));
  822. }
  823. /**
  824. * 10 进制转 16
  825. */
  826. private static function decToHex($hex)
  827. {
  828. return str_pad(base_convert($hex, 10, 16), 2, 0, STR_PAD_LEFT);
  829. }
  830. }