DevicesService.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | Laravel框架 [ Laravel ]
  4. // +----------------------------------------------------------------------
  5. // | 版权所有 2017~2021 Laravel研发中心
  6. // +----------------------------------------------------------------------
  7. // | 官方网站: http://www.laravel.cn
  8. // +----------------------------------------------------------------------
  9. // | Author: wesmiler <12345678@qq.com>
  10. // +----------------------------------------------------------------------
  11. namespace App\Services;
  12. use App\Jobs\CatchLedScreen;
  13. use App\Models\DevicesModel;
  14. use App\Models\GongdengOrderModel;
  15. use Illuminate\Support\Facades\DB;
  16. /**
  17. * 供灯设备管理-服务类
  18. * @author wesmiler
  19. * @since 2020/11/11
  20. * Class DevicesService
  21. * @package App\Services
  22. */
  23. class DevicesService extends BaseService
  24. {
  25. protected static $instance=null;
  26. /**
  27. * 构造函数
  28. * @author wesmiler
  29. * @since 2020/11/11
  30. * DevicesService constructor.
  31. */
  32. public function __construct()
  33. {
  34. $this->model = new DevicesModel();
  35. }
  36. /**
  37. * 静态入口
  38. * @return DevicesService|null
  39. */
  40. public static function make(){
  41. if(!self::$instance){
  42. self::$instance = new DevicesService();
  43. }
  44. return self::$instance;
  45. }
  46. /**
  47. * 获取友链列表
  48. * @return array
  49. * @since 2020/11/11
  50. * @author wesmiler
  51. */
  52. public function getList()
  53. {
  54. $params = request()->all();
  55. return parent::getList();
  56. }
  57. /**
  58. * 添加或编辑
  59. * @return array
  60. * @since 2020/11/11
  61. * @author wesmiler
  62. */
  63. public function edit()
  64. {
  65. $data = request()->all();
  66. $code = isset($data['code'])? $data['code'] : '';
  67. $id = isset($data['id'])? $data['id'] : 0;
  68. if($code && $checkId = $this->model->where('code', $code)->value('id')){
  69. if(($checkId && !$id) || ($id && $checkId != $id) ){
  70. return message("设备编号[{$code}]已存在",false);
  71. }
  72. }
  73. $startNum = isset($data['start_num'])? $data['start_num'] : 0;
  74. $endNum = isset($data['end_num'])? $data['end_num'] : 0;
  75. if($endNum<=$startNum){
  76. return message("截止可选灯号必须大于开始可选灯号",false);
  77. }
  78. $data['update_time'] = time();
  79. return parent::edit($data); // TODO: Change the autogenerated stub
  80. }
  81. /**
  82. * 获取设备端口
  83. * @return array
  84. */
  85. public function getDevice(){
  86. $datas = $this->model::where(['status'=> 1])->orderBy(DB::raw('RAND()'))->first();
  87. $datas = $datas? $datas->toArray() : [];
  88. return $datas;
  89. }
  90. /**
  91. * 获取可用设备号
  92. * @return array|false|mixed
  93. */
  94. public function getDeviceNums($deviceInfo){
  95. $deviceCode = isset($deviceInfo['code'])? $deviceInfo['code'] : '';
  96. if(empty($deviceCode)){
  97. return false;
  98. }
  99. if(!$deviceInfo || $deviceInfo['start_num'] >= $deviceInfo['end_num']){
  100. return false;
  101. }
  102. $cacheKey = "caches:devices:nums_{$deviceCode}";
  103. $datas = RedisService::get($cacheKey);
  104. if($datas){
  105. $datas = array_values($datas);
  106. shuffle($datas);
  107. return $datas;
  108. }
  109. $deviceNums = range($deviceInfo['start_num'], $deviceInfo['end_num']);
  110. $datas = GongdengOrderModel::where(['status'=> 2, 'lamp_status'=> 2])->pluck('device_num');
  111. $datas = $datas? $datas->toArray() : [];
  112. if($deviceNums){
  113. $datas = $datas? array_diff($deviceNums, $datas) : $deviceNums;
  114. if($datas){
  115. $datas = array_values($datas);
  116. shuffle($datas);
  117. RedisService::set($cacheKey, $datas, rand(3,5));
  118. }
  119. }
  120. return $datas;
  121. }
  122. /**
  123. * 亮灯处理
  124. * @param $orderSn 订单号
  125. * @return bool
  126. */
  127. public function catchLamp($orderSn, $info=[]){
  128. if(empty($orderSn)){
  129. return false;
  130. }
  131. // 验证是否已处理
  132. // 获取可用设备
  133. $errorKey = "caches:lamps:{$orderSn}";
  134. $deviceInfo = $this->getDevice();
  135. $deviceCode = isset($deviceInfo['code'])? $deviceInfo['code'] : '';
  136. $startNum = isset($deviceInfo['start_num'])? $deviceInfo['start_num'] : 0;
  137. $endNum = isset($deviceInfo['end_num'])? $deviceInfo['end_num'] : 0;
  138. $port = isset($deviceInfo['port'])? $deviceInfo['port'] : 0;
  139. if(empty($deviceInfo) || empty($deviceCode) || ($startNum >= $endNum) || !$port){
  140. RedisService::set("{$errorKey}:error_check", ['info'=> $deviceInfo], 3600);
  141. return false;
  142. }
  143. // 获取可用设备号
  144. $deviceNums = DevicesService::make()->getDeviceNums($deviceInfo);
  145. $deviceLampNo = $deviceNums? $deviceNums[0] : 0;
  146. if(empty($deviceLampNo)){
  147. RedisService::set("{$errorKey}:error_device", ['info'=> $deviceInfo,'nums'=> $deviceNums], 3600);
  148. return false;
  149. }
  150. // 亮灯处理
  151. unset($deviceNums[0]);
  152. RedisService::set("caches:devices:nums_{$deviceCode}", $deviceNums, rand(10,30));
  153. $colors = ['黄色','红色','绿色','白色'];
  154. shuffle($colors);
  155. $data = [
  156. 'CommandType'=> 'OpenLed', // 执行命令方式:OpenLed-开灯,CloseLed-关灯,QuitStatus-查询状态
  157. 'MD'=> $deviceCode, // 机器号设备号
  158. 'MDPORT'=> $port, // 设备端口:暂与设备号一致
  159. 'LEDID'=> $deviceLampNo, // 亮灯灯号1-498对应1号设备,498后为设备2
  160. 'Color'=> $colors[0], // 颜色
  161. 'OrderNo'=> $orderSn, // 订单号
  162. 'text'=> isset($info['qf_content'])? $info['qf_content'] : '',
  163. ];
  164. $dataStr = [];
  165. foreach($data as $k => $v){
  166. $dataStr[] = $k.'='.$v;
  167. }
  168. // 屏幕控制队列数据
  169. /*
  170. $params = [
  171. 'order_sn'=> $orderSn,
  172. 'device_code'=> $deviceCode,
  173. 'port'=> $port,
  174. 'text'=> isset($info['qf_content'])? $info['qf_content'] : '',
  175. ];
  176. CatchLedScreen::dispatch($params)->delay(rand(2, 5));
  177. */
  178. // 调用亮灯接口处理
  179. $dataStr = implode('&', $dataStr);
  180. $headers = ["Content-Type:application/x-www-form-urlencoded; charset=UTF-8"];
  181. $apiUrl = ConfigService::make()->getConfigByCode('gd_api_url').'/LEDControl.ashx';
  182. RedisService::set($errorKey.':request', ['url'=> $apiUrl,'data'=> $data], 3600);
  183. $result = httpHeaderRequest($apiUrl, $dataStr,'post',$headers,'text');
  184. RedisService::set($errorKey.':result', $result, 3600);
  185. // 更新灯状态
  186. $updateData = ['lamp_status'=> 2,'device_num'=> $deviceLampNo,'params'=> json_encode($data, 256)];
  187. if($result && trim($result) == 'True'){
  188. RedisService::set($errorKey.':update', $updateData, 3600);
  189. GongdengOrderModel::where(['order_sn'=>$orderSn])->update($updateData);
  190. return true;
  191. }else{
  192. $updateData['lamp_status'] = 1;
  193. RedisService::set($errorKey.':update', $updateData, 3600);
  194. GongdengOrderModel::where(['order_sn'=>$orderSn])->update($updateData);
  195. return false;
  196. }
  197. }
  198. /**
  199. * 调度处理LED屏幕队列
  200. * @param $params
  201. */
  202. public function catchLedScreen($params){
  203. $orderSn = isset($params['order_sn'])? $params['order_sn'] : '';
  204. $port = isset($params['port'])? $params['port'] : '';
  205. $deviceCode = isset($params['device_code'])? $params['device_code'] : '';
  206. if(empty($orderSn) || empty($deviceCode) || empty($port)){
  207. RedisService::set("catch:queue:screen:error_".date('YmdHis'), $params, 3600);
  208. return false;
  209. }
  210. $cacheKey = "queue:catch:screen:{$orderSn}";
  211. RedisService::set($cacheKey.':params', $params, 600);
  212. $data = [
  213. 'CommandType'=> 'OpenLed', // 执行命令方式:OpenLed-开灯,CloseLed-关灯,QuitStatus-查询状态
  214. 'MD'=> $deviceCode, // 机器号设备号
  215. 'MDPORT'=> $port, // 设备端口:暂与设备号一致
  216. 'OrderNo'=> $orderSn, // 订单号
  217. 'text'=> isset($params['text']) && $params['text']? $params['text'] : '供灯祈福',
  218. ];
  219. $dataStr = [];
  220. foreach($data as $k => $v){
  221. $dataStr[] = $k.'='.$v;
  222. }
  223. // 调用亮灯接口处理
  224. $dataStr = implode('&', $dataStr);
  225. $headers = ["Content-Type:application/x-www-form-urlencoded; charset=UTF-8"];
  226. $apiUrl = ConfigService::make()->getConfigByCode('gd_api_url').'/LEDControl.ashx';
  227. RedisService::set($cacheKey.':request', ['url'=> $apiUrl,'data'=> $data], 3600);
  228. $result = httpHeaderRequest($apiUrl, $dataStr,'post',$headers,'text');
  229. RedisService::set($cacheKey.':result', $result, 3600);
  230. // 更新灯状态
  231. $updateData = ['screen_status'=> 1];
  232. if($result && trim($result) == 'True'){
  233. GongdengOrderModel::where(['order_sn'=>$orderSn])->update($updateData);
  234. return true;
  235. }else{
  236. $updateData['screen_status'] = 2;
  237. GongdengOrderModel::where(['order_sn'=>$orderSn])->update($updateData);
  238. return false;
  239. }
  240. }
  241. /**
  242. * 获取拍照图片
  243. * @return array
  244. */
  245. public function getPicList(){
  246. $orderSn = request()->get('order_sn');
  247. if(empty($orderSn)){
  248. return message('订单号参数错误', false);
  249. }
  250. $orderInfo = GongdengOrderModel::where(['order_sn'=> $orderSn,'mark'=> 1,'status'=> 2])
  251. ->first();
  252. if(!$orderInfo){
  253. return message('订单不存在或未支付', false);
  254. }
  255. $deviceCodes = ConfigService::make()->getConfigByCode('snapshot_device_nos');
  256. $deviceCodes = $deviceCodes? explode(',', $deviceCodes) : [];
  257. if(empty($deviceCodes)) {
  258. return message('没有可用拍照设备,请先配置', false);
  259. }
  260. $picList = [];
  261. $apiUrl = ConfigService::make()->getConfigByCode('gd_api_url');
  262. $path = $apiUrl."/img/{$orderSn}_%s.jpg";
  263. foreach($deviceCodes as $code){
  264. $picList[] = sprintf($path, $code);
  265. }
  266. return message('获取拍照图片', true, $picList);
  267. }
  268. }