// +---------------------------------------------------------------------- namespace App\Services; use App\Jobs\CatchLedScreen; use App\Models\DevicesModel; use App\Models\GongdengOrderModel; use Illuminate\Support\Facades\DB; /** * 供灯设备管理-服务类 * @author wesmiler * @since 2020/11/11 * Class DevicesService * @package App\Services */ class DevicesService extends BaseService { protected static $instance=null; /** * 构造函数 * @author wesmiler * @since 2020/11/11 * DevicesService constructor. */ public function __construct() { $this->model = new DevicesModel(); } /** * 静态入口 * @return DevicesService|null */ public static function make(){ if(!self::$instance){ self::$instance = new DevicesService(); } return self::$instance; } /** * 获取友链列表 * @return array * @since 2020/11/11 * @author wesmiler */ public function getList() { $params = request()->all(); return parent::getList(); } /** * 添加或编辑 * @return array * @since 2020/11/11 * @author wesmiler */ public function edit() { $data = request()->all(); $code = isset($data['code'])? $data['code'] : ''; $id = isset($data['id'])? $data['id'] : 0; if($code && $checkId = $this->model->where('code', $code)->value('id')){ if(($checkId && !$id) || ($id && $checkId != $id) ){ return message("设备编号[{$code}]已存在",false); } } $startNum = isset($data['start_num'])? $data['start_num'] : 0; $endNum = isset($data['end_num'])? $data['end_num'] : 0; if($endNum<=$startNum){ return message("截止可选灯号必须大于开始可选灯号",false); } $data['update_time'] = time(); return parent::edit($data); // TODO: Change the autogenerated stub } /** * 获取设备端口 * @return array */ public function getDevice(){ $datas = $this->model::where(['status'=> 1])->orderBy(DB::raw('RAND()'))->first(); $datas = $datas? $datas->toArray() : []; return $datas; } /** * 获取可用设备号 * @return array|false|mixed */ public function getDeviceNums($deviceInfo){ $deviceCode = isset($deviceInfo['code'])? $deviceInfo['code'] : ''; if(empty($deviceCode)){ return false; } if(!$deviceInfo || $deviceInfo['start_num'] >= $deviceInfo['end_num']){ return false; } $cacheKey = "caches:devices:nums_{$deviceCode}"; $datas = RedisService::get($cacheKey); if($datas){ $datas = array_values($datas); shuffle($datas); return $datas; } $deviceNums = range($deviceInfo['start_num'], $deviceInfo['end_num']); $datas = GongdengOrderModel::where(['status'=> 2, 'lamp_status'=> 2])->pluck('device_num'); $datas = $datas? $datas->toArray() : []; if($deviceNums){ $datas = $datas? array_diff($deviceNums, $datas) : $deviceNums; if($datas){ $datas = array_values($datas); shuffle($datas); RedisService::set($cacheKey, $datas, rand(3,5)); } } return $datas; } /** * 亮灯处理 * @param $orderSn 订单号 * @return bool */ public function catchLamp($orderSn, $info=[]){ if(empty($orderSn)){ return false; } // 验证是否已处理 // 获取可用设备 $errorKey = "caches:lamps:{$orderSn}"; $deviceInfo = $this->getDevice(); $deviceCode = isset($deviceInfo['code'])? $deviceInfo['code'] : ''; $startNum = isset($deviceInfo['start_num'])? $deviceInfo['start_num'] : 0; $endNum = isset($deviceInfo['end_num'])? $deviceInfo['end_num'] : 0; $port = isset($deviceInfo['port'])? $deviceInfo['port'] : 0; if(empty($deviceInfo) || empty($deviceCode) || ($startNum >= $endNum) || !$port){ RedisService::set("{$errorKey}:error_check", ['info'=> $deviceInfo], 3600); return false; } // 获取可用设备号 $deviceNums = DevicesService::make()->getDeviceNums($deviceInfo); $deviceLampNo = $deviceNums? $deviceNums[0] : 0; if(empty($deviceLampNo)){ RedisService::set("{$errorKey}:error_device", ['info'=> $deviceInfo,'nums'=> $deviceNums], 3600); return false; } // 亮灯处理 unset($deviceNums[0]); RedisService::set("caches:devices:nums_{$deviceCode}", $deviceNums, rand(10,30)); $colors = ['黄色','红色','绿色','白色']; shuffle($colors); $data = [ 'CommandType'=> 'OpenLed', // 执行命令方式:OpenLed-开灯,CloseLed-关灯,QuitStatus-查询状态 'MD'=> $deviceCode, // 机器号设备号 'MDPORT'=> $port, // 设备端口:暂与设备号一致 'LEDID'=> $deviceLampNo, // 亮灯灯号1-498对应1号设备,498后为设备2 'Color'=> $colors[0], // 颜色 'OrderNo'=> $orderSn, // 订单号 'text'=> isset($info['qf_content'])? $info['qf_content'] : '', ]; $dataStr = []; foreach($data as $k => $v){ $dataStr[] = $k.'='.$v; } // 屏幕控制队列数据 /* $params = [ 'order_sn'=> $orderSn, 'device_code'=> $deviceCode, 'port'=> $port, 'text'=> isset($info['qf_content'])? $info['qf_content'] : '', ]; CatchLedScreen::dispatch($params)->delay(rand(2, 5)); */ // 调用亮灯接口处理 $dataStr = implode('&', $dataStr); $headers = ["Content-Type:application/x-www-form-urlencoded; charset=UTF-8"]; $apiUrl = ConfigService::make()->getConfigByCode('gd_api_url').'/LEDControl.ashx'; RedisService::set($errorKey.':request', ['url'=> $apiUrl,'data'=> $data], 3600); $result = httpHeaderRequest($apiUrl, $dataStr,'post',$headers,'text'); RedisService::set($errorKey.':result', $result, 3600); // 更新灯状态 $updateData = ['lamp_status'=> 2,'device_num'=> $deviceLampNo,'params'=> json_encode($data, 256)]; if($result && trim($result) == 'True'){ RedisService::set($errorKey.':update', $updateData, 3600); GongdengOrderModel::where(['order_sn'=>$orderSn])->update($updateData); return true; }else{ $updateData['lamp_status'] = 1; RedisService::set($errorKey.':update', $updateData, 3600); GongdengOrderModel::where(['order_sn'=>$orderSn])->update($updateData); return false; } } /** * 调度处理LED屏幕队列 * @param $params */ public function catchLedScreen($params){ $orderSn = isset($params['order_sn'])? $params['order_sn'] : ''; $port = isset($params['port'])? $params['port'] : ''; $deviceCode = isset($params['device_code'])? $params['device_code'] : ''; if(empty($orderSn) || empty($deviceCode) || empty($port)){ RedisService::set("catch:queue:screen:error_".date('YmdHis'), $params, 3600); return false; } $cacheKey = "queue:catch:screen:{$orderSn}"; RedisService::set($cacheKey.':params', $params, 600); $data = [ 'CommandType'=> 'OpenLed', // 执行命令方式:OpenLed-开灯,CloseLed-关灯,QuitStatus-查询状态 'MD'=> $deviceCode, // 机器号设备号 'MDPORT'=> $port, // 设备端口:暂与设备号一致 'OrderNo'=> $orderSn, // 订单号 'text'=> isset($params['text']) && $params['text']? $params['text'] : '供灯祈福', ]; $dataStr = []; foreach($data as $k => $v){ $dataStr[] = $k.'='.$v; } // 调用亮灯接口处理 $dataStr = implode('&', $dataStr); $headers = ["Content-Type:application/x-www-form-urlencoded; charset=UTF-8"]; $apiUrl = ConfigService::make()->getConfigByCode('gd_api_url').'/LEDControl.ashx'; RedisService::set($cacheKey.':request', ['url'=> $apiUrl,'data'=> $data], 3600); $result = httpHeaderRequest($apiUrl, $dataStr,'post',$headers,'text'); RedisService::set($cacheKey.':result', $result, 3600); // 更新灯状态 $updateData = ['screen_status'=> 1]; if($result && trim($result) == 'True'){ GongdengOrderModel::where(['order_sn'=>$orderSn])->update($updateData); return true; }else{ $updateData['screen_status'] = 2; GongdengOrderModel::where(['order_sn'=>$orderSn])->update($updateData); return false; } } /** * 获取拍照图片 * @return array */ public function getPicList(){ $orderSn = request()->get('order_sn'); if(empty($orderSn)){ return message('订单号参数错误', false); } $orderInfo = GongdengOrderModel::where(['order_sn'=> $orderSn,'mark'=> 1,'status'=> 2]) ->first(); if(!$orderInfo){ return message('订单不存在或未支付', false); } $deviceCodes = ConfigService::make()->getConfigByCode('snapshot_device_nos'); $deviceCodes = $deviceCodes? explode(',', $deviceCodes) : []; if(empty($deviceCodes)) { return message('没有可用拍照设备,请先配置', false); } $picList = []; $apiUrl = ConfigService::make()->getConfigByCode('gd_api_url'); $path = $apiUrl."/img/{$orderSn}_%s.jpg"; foreach($deviceCodes as $code){ $picList[] = sprintf($path, $code); } return message('获取拍照图片', true, $picList); } }