123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302 |
- <?php
- /**
- * This file is part of workerman.
- *
- * Licensed under The MIT License
- * For full copyright and license information, please see the MIT-LICENSE.txt
- * Redistributions of files must retain the above copyright notice.
- *
- * @author walkor<walkor@workerman.net>
- * @copyright walkor<walkor@workerman.net>
- *
- * @see http://www.workerman.net/
- *
- * @license http://www.opensource.org/licenses/mit-license.php MIT License
- */
- /**
- * 用于检测业务代码死循环或者长时间阻塞等问题
- * 如果发现业务卡死,可以将下面declare打开(去掉//注释),并执行php start.php reload
- * 然后观察一段时间workerman.log看是否有process_timeout异常.
- */
- //declare(ticks=1);
- use GatewayWorker\Lib\Gateway;
- /**
- * 主逻辑
- * 主要是处理 onConnect onMessage onClose 三个方法
- * onConnect 和 onClose 如果不需要可以不用实现并删除.
- */
- class Events
- {
- use \App\Handlers\ExceptionTrait, \App\Models\WarningLogTraitModel, \App\Models\BikeTraitModel, \App\Handlers\Crc16Handler;
- public static $db = null;
- public static $redis = null;
- public static $mongo = null;
- private static $db_config = [
- 'host' => '192.168.10.10',
- 'port' => 3306,
- 'user' => 'homestead',
- 'password' => 'secret',
- 'db_name' => 'weilaibike'
- ];
- private static $redis_config = [
- 'host' => '192.168.10.10',
- 'port' => 6379,
- 'database' => 0
- ];
- private static $mongodb_config = [
- 'url' => 'mongodb://114.116.38.6',
- 'database' => 'weilaibike'
- ];
- // private static $db_config = [
- // 'host' => 'node2',
- // 'port' => 3306,
- // 'user' => 'weilaibike',
- // 'password' => 'LGcaxd5WJjepJccx',
- // 'db_name' => 'weilaibike'
- // ];
- //
- // private static $redis_config = [
- // 'host' => 'node3',
- // 'port' => 6379
- // ];
- // private static $mongodb_config = 'mongodb://node3/weilaibike';
- public static function onWorkerStart($businessWorker)
- {
- self::$db_config = Config['db'];
- self::$redis_config = Config['redis'];
- self::$mongodb_config = Config['mongodb'];
- self::$db = new \Workerman\MySQL\Connection(self::$db_config['host'], self::$db_config['port'], self::$db_config['user'], self::$db_config['password'], self::$db_config['db_name']);
- self::$redis = new Redis();
- self::$redis->pconnect(self::$redis_config['host'], self::$redis_config['port']);
- self::$redis->select(self::$redis_config['database']);
- self::$mongo = (new MongoDB\Client(self::$mongodb_config['url']))->selectDatabase(self::$mongodb_config['database']);
- }
- /**
- * 当客户端连接时触发
- * 如果业务不需此回调可以删除onConnect.
- *
- * @param int $client_id 连接id
- */
- public static function onConnect($client_id)
- {
- }
- /**
- * 当客户端发来消息时触发.
- *
- * @param int $client_id 连接id
- * @param mixed $message 具体消息
- */
- public static function onMessage($client_id, $message)
- {
- $message = bin2hex($message);
- $data = str_split(str_replace(' ', '', trim($message)), 2);
- if (($data[0] . $data[1]) !== 'aaaa') return '';
- self::log($message, 'EVENT_message', self::$LOG_DEV);
- // 传送头
- $header = array_slice($data, 0, 10);
- $dataLength = hexdec($header[2] . $header[3]);
- // 检验包是否完整
- if ($dataLength !== count($data)) return 'error:data length';
- // 过滤加密
- if ($header[4] == '05') {
- self::log($message, '**jiami**', self::$LOG_COMMON);
- Gateway::closeCurrentClient();
- return '';
- };
- // 流水码
- $num_code = $header[6];
- // 装载数据
- $body = array_slice($data, 10, -2);
- // 校检尾
- $checkEnd = implode('', array_slice($data, -2, 2));
- if ($checkEnd !== self::crc16(array_slice($data, 2, -2))) {
- self::log("CRC_ERROR", "CRC16", self::$LOG_MAJOR);
- }
- $cmd = strtoupper($data[5]);
- $cmd_in_box_no = [
- \App\Maps\CmdMap::CMD_LOGIN,
- \App\Maps\CmdMap::CMD_LOCATION,
- \App\Maps\CmdMap::CMD_BATTERY_STATUS,
- \App\Maps\CmdMap::CMD_WARNING,
- \App\Maps\CmdMap::CMD_HEARTBEAT,
- \App\Maps\CmdMap::CMD_STATUS_SYNC,
- \App\Maps\CmdMap::CMD_MSG_UP,
- \App\Maps\CmdMap::CMD_ADMIN_MSG_FORWARD,
- \App\Maps\CmdMap::CMD_BOX_UPGRADE,
- \App\Maps\CmdMap::CMD_BOX_ACTIVE_REPORTING,
- \App\Maps\CmdMap::CMD_BOX_STATUS_CHANGE_UP
- ];
- if (in_array($cmd, $cmd_in_box_no)) {
- // 响应包含box_no
- $box_no = substr(implode('', array_slice($body, 0, 5)), 0, 9);
- $_SESSION['box_no'] = $box_no;
- Gateway::bindUid($client_id, $box_no);
- if (!isset($_SESSION['bike_no'])) {
- $_SESSION['bike_no'] = self::byBoxNoGetBikeNoStatic($box_no);
- }
- //离线检查
- if (self::$redis->exists('bike:offline:' . $box_no)) {
- self::log($box_no, 'EVENT_ONLINE', self::$LOG_MAJOR);
- $cols['is_link'] = \App\Maps\BikeMap::LINK_ONLINE;
- self::$db->update('bikes')->where('box_no = ' . $box_no)->cols($cols)->query();
- self::$redis->del('bike:offline:' . $box_no);
- }
- }
- $response_body = '';
- $response_cmd = false;
- $param = [
- 'db' => self::$db,
- 'mongo' => self::$mongo,
- 'redis' => self::$redis
- ];
- switch ($cmd) {
- case \App\Maps\CmdMap::CMD_LOGIN:
- echo 'CMD_LOGIN' . PHP_EOL;
- // 登录数据包
- $response_body = (new \App\Servers\LoginServer($param))->main($body);
- $response_cmd = \App\Maps\CmdMap::CMD_RESPONSE_LOGIN;
- break;
- case \App\Maps\CmdMap::CMD_LOCATION:
- echo 'location' . PHP_EOL;
- // 位置数据包
- $response_body = (new \App\Servers\LocationServer($param))->main($body);
- $response_cmd = \App\Maps\CmdMap::CMD_RESPONSE_LOCATION;
- break;
- case \App\Maps\CmdMap::CMD_HEARTBEAT:
- echo 'CMD_HEARTBEAT' . PHP_EOL;
- // 心跳数据包
- $response_body = (new \App\Servers\HeartBeatServer($param))->main($body);
- $response_cmd = \App\Maps\CmdMap::CMD_RESPONSE_HEARTBEAT;
- break;
- case \App\Maps\CmdMap::CMD_BATTERY_STATUS:
- echo 'CMD_BATTERY_STATUS' . PHP_EOL;
- //电池数据包
- $response_body = (new \App\Servers\BatteryServer($param))->main($body);
- break;
- case \App\Maps\CmdMap::CMD_WARNING:
- echo 'CMD_WARNING' . PHP_EOL;
- //告警数据包
- $response_body = (new \App\Servers\WarningServer($param))->main($body);
- $response_cmd = \App\Maps\CmdMap::CMD_RESPONSE_WARNING;
- break;
- case \App\Maps\CmdMap::CMD_REMOTE_CONTROLLER_RESPONSE:
- echo 'CMD_REMOTE_CONTROLLER_RESPONSE' . PHP_EOL;
- // 服务器下发控制命令时,应答终端
- $response_body = (new \App\Servers\RemoteCmdServer($param))->main($body);
- $response_cmd = \App\Maps\CmdMap::CMD_RESPONSE_REMOTE_CMD;
- break;
- case \App\Maps\CmdMap::CMD_STATUS_SYNC:
- echo 'CMD_STATUS_SYNC' . PHP_EOL;
- // 终端状态同步
- $response_body = (new \App\Servers\BoxSyncServer($param))->main($body);
- $response_cmd = \App\Maps\CmdMap::CMD_RESPONSE_STATUS_SYNC;
- break;
- case \App\Maps\CmdMap::CMD_MSG_UP:
- echo 'CMD_MSG_UP' . PHP_EOL;
- // 短信上报
- $response_body = (new \App\Servers\MsgUpServer($param))->main($body);
- $response_cmd = \App\Maps\CmdMap::CMD_RESPONSE_MSG_UP;
- break;
- case \App\Maps\CmdMap::CMD_ADMIN_MSG_FORWARD:
- echo 'CMD_MSG_FORWARD' . PHP_EOL;
- // 后台短信转发响应
- (new \App\Servers\MsgForwardServer($param))->main($body);
- break;
- case \App\Maps\CmdMap::CMD_BOX_UPGRADE:
- echo 'CMD_BOX_UPGRADE' . PHP_EOL;
- //终端请求固件升级
- $response_body = (new \App\Servers\BoxUpgradeServer($param))->main($body);
- $response_cmd = \App\Maps\CmdMap::CMD_RESPONSE_BOX_UPGRADE;
- break;
- case \App\Maps\CmdMap::CMD_BOX_ACTIVE_REPORTING:
- echo 'CMD_BOX_ACTIVE_REPORTING' . PHP_EOL;
- // 终端主动上报
- $response_body = (new \App\Servers\BoxActiveReportingServer($param))->main($body);
- $response_cmd = \App\Maps\CmdMap::CMD_RESPONSE_BOX_ACTIVE_REPORTING;
- break;
- case \App\Maps\CmdMap::CMD_BOX_REPORTING_NEW_BIKE:
- echo 'CMD_BOX_REPORTING_NEW_BIKE' . PHP_EOL;
- //终端最新车辆信息上报事件
- $response_body = (new \App\Servers\NewBikeReportingServer($param))->main($body);
- $response_cmd = \App\Maps\CmdMap::CMD_RESPONSE_BOX_UP_NEW_BIKE_DATA;
- break;
- case \App\Maps\CmdMap::CMD_BOX_STATUS_CHANGE_UP:
- echo 'CMD_BOX_STATUS_CHANGE_UP' . PHP_EOL;
- // 终端状态类型变更上报
- $response_body = (new \App\Servers\BoxStatusChangeServer($param))->main($body);
- $response_cmd = \App\Maps\CmdMap::CMD_RESPONSE_BOX_STATUS_CHANGE_UP;
- break;
- case \App\Maps\CmdMap::CMD_REMOTE_SELECT_CMD_BOX_UP_DATA:
- echo 'CMD_REMOTE_SELECT_CMD_BOX_UP_DATA' . PHP_EOL;
- // 远程查询命令,终端上传
- (new \App\Servers\BoxSelectCmdServer($param))->main($body);
- break;
- case \App\Maps\CmdMap::CMD_REMOTE_SETTING_CMD_BOX_UP_DATA:
- echo 'CMD_REMOTE_SETTING_CMD_BOX_UP_DATA' . PHP_EOL;
- // 远程设置参数,终端上报
- (new \App\Servers\BoxSettingServer($param))->main($body);
- break;
- case \App\Maps\CmdMap::CMD_REMOTE_VOICE_DATA:
- echo 'CMD_REMOTE_VOICE_DATA' . PHP_EOL;
- //远程语音数据包,终端上传状态
- (new \App\Servers\BoxPlayVoiceServer($param))->main($body);
- break;
- }
- // 发送数据
- if (is_array($response_body)) {
- $response = (new \App\Servers\ResponseServer())->send($response_body, $response_cmd, $num_code);
- self::log($response, 'response', self::$LOG_DEV);
- Gateway::sendToCurrentClient(hex2bin(str_replace(' ', '', $response)));
- }
- }
- /**
- * 当用户断开连接时触发.
- *
- * @param int $client_id 连接id
- */
- public static function onClose($client_id)
- {
- $box_no = $_SESSION['box_no'];
- $bike_no = $_SESSION['bike_no'];
- // 离线检查
- if ($box_no && $bike_no && !Gateway::isUidOnline($box_no)) {
- self::log($box_no, 'EVENT_LINK_OFFLINE_ONCLOSE', self::$LOG_COMMON);
- self::$db->update('bikes')->where('box_no = ' . $box_no)->cols([
- 'is_link' => \App\Maps\BikeMap::LINK_OFFLINE
- ])->query();
- // 发出警告
- self::warningLogBikeOffLineStatic($bike_no, $box_no, 'onClose');
- self::$redis->set('bike:offline:' . $box_no, '1', 3600);
- }
- }
- }
|