NoticeAction.class.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. <?php
  2. class NoticeAction extends Action {
  3. public function jgpush( ){
  4. $app_key = '58e15e345e0c21b7e638e186';
  5. $master_secret = 'a91d0b1c1fa1b327db832506';
  6. $client = new \JPush\Client($app_key, $master_secret);
  7. $push_payload = $client->push()
  8. ->setPlatform('all')
  9. ->addAllAudience()
  10. ->setNotificationAlert('车辆异动告警');
  11. try {
  12. $response = $push_payload->send();
  13. print_r($response);
  14. } catch (\JPush\Exceptions\APIConnectionException $e) {
  15. // try something here
  16. print $e;
  17. } catch (\JPush\Exceptions\APIRequestException $e) {
  18. // try something here
  19. print $e;
  20. }
  21. }
  22. public function pushFromKafka( ){
  23. $conf = new RdKafka\Conf();
  24. // Set a rebalance callback to log partition assignments (optional)(当有新的消费进程加入或者退出消费组时,kafka 会自动重新分配分区给消费者进程,这里注册了一个回调函数,当分区被重新分配时触发)
  25. $conf->setRebalanceCb(function (RdKafka\KafkaConsumer $kafka, $err, array $partitions = null) {
  26. switch ($err) {
  27. case RD_KAFKA_RESP_ERR__ASSIGN_PARTITIONS:
  28. echo "Assign: ";
  29. var_dump($partitions);
  30. $kafka->assign($partitions);
  31. break;
  32. case RD_KAFKA_RESP_ERR__REVOKE_PARTITIONS:
  33. echo "Revoke: ";
  34. var_dump($partitions);
  35. $kafka->assign(NULL);
  36. break;
  37. default:
  38. throw new \Exception($err);
  39. }
  40. });
  41. // Configure the group.id. All consumer with the same group.id will consume( 配置groud.id 具有相同 group.id 的consumer 将会处理不同分区的消息,所以同一个组内的消费者数量如果订阅了一个topic, 那么消费者进程的数量多于这个topic 分区的数量是没有意义的。)
  42. // different partitions.
  43. $conf->set('group.id', 'myConsumerGroup');
  44. // Initial list of Kafka brokers(添加 kafka集群服务器地址)
  45. if( !C('KAFKA_BROKER_LIST') ){
  46. echo 'please set broker list !!! ';
  47. }
  48. $conf->set('metadata.broker.list', C('KAFKA_BROKER_LIST'));
  49. $topicConf = new RdKafka\TopicConf();
  50. // Set where to start consuming messages when there is no initial offset in
  51. // offset store or the desired offset is out of range.
  52. // 'smallest': start from the beginning
  53. $topicConf->set('auto.offset.reset', 'smallest');
  54. // Set the configuration to use for subscribed/assigned topics
  55. $conf->setDefaultTopicConf($topicConf);
  56. $consumer = new RdKafka\KafkaConsumer($conf);
  57. // 消费者订阅
  58. $consumer->subscribe(['gps_alarm_msg_queue']);
  59. while (true) {
  60. $message = $consumer->consume(120*1000);
  61. switch ($message->err) {
  62. case RD_KAFKA_RESP_ERR_NO_ERROR:
  63. $msg_data = json_decode($message->payload,true);
  64. if($msg_data){
  65. // 使用极光推送消息
  66. if(!C('JPUSH_APP_KEY') || !C('JPUSH_MASTER_SECRET')){
  67. echo 'jpush app key or secret not exists',PHP_EOL;
  68. break;
  69. }
  70. $jpush_client = new \JPush\Client( C('JPUSH_APP_KEY'), C('JPUSH_MASTER_SECRET') );
  71. // 电子围栏告警,上锁车辆异动告警,低电量告警,被盗告警,广播消息推送
  72. $result = $this->jpushMsg( $jpush_client, $msg_data );
  73. if($result){
  74. echo $result['message'],PHP_EOL;
  75. debug_log('jpush',$result['message']);
  76. }
  77. }
  78. break;
  79. case RD_KAFKA_RESP_ERR__PARTITION_EOF:
  80. echo "No more messages; will wait for more\n";
  81. break;
  82. case RD_KAFKA_RESP_ERR__TIMED_OUT:
  83. echo "Timed out\n";
  84. break;
  85. default:
  86. throw new \Exception($message->errstr(), $message->err);
  87. break;
  88. }
  89. }
  90. }
  91. private function jpushMsg( $client, $msg_data ){
  92. /*
  93. $msg_data = '{
  94. "type":2,
  95. "title":"被盗告警",
  96. "content":"车被偷了,赶紧去找",
  97. "device_number":"FFFFFF123122"
  98. }';
  99. $msg_data = '{
  100. "type":9,
  101. "title":"群推消息",
  102. "content":"这是一个广播"
  103. }';
  104. */
  105. $single_push_type = array(
  106. \Rlfd\Alarm\PushTypeEnum::OUTAGE_ALARM, // C('OUTAGE_ALARM'),// 1-断电报警
  107. \Rlfd\Alarm\PushTypeEnum::SOS_ALARM,// C('SOS_ALARM'), // 2-SOS报警
  108. \Rlfd\Alarm\PushTypeEnum::LOWWER_BATTERY_ALARM,// C('LOWWER_BATTERY_ALARM'), // 3-低电量告警
  109. \Rlfd\Alarm\PushTypeEnum::SHAKE_ALARM,// C('SHAKE_ALARM'), // 4-震动报警
  110. \Rlfd\Alarm\PushTypeEnum::SHIFT_ALARM,// C('SHIFT_ALARM'), // 5-位移报警
  111. \Rlfd\Alarm\PushTypeEnum::LOCK_VEHICLE_ALARM,// C('LOCK_VEHICLE_ALARM'), // 99-锁车告警
  112. \Rlfd\Alarm\PushTypeEnum::STOLEN_ALARM,// C('STOLEN_ALARM'), // 7-被盗告警
  113. \Rlfd\Alarm\PushTypeEnum::FENCE_ALARM,// C('FENCE_ALARM'), // 8-电子围栏告警
  114. \Rlfd\Alarm\PushTypeEnum::CRASH_ALARM,
  115. \Rlfd\Alarm\PushTypeEnum::HIGHVOLTAGE_ALARM,
  116. \Rlfd\Alarm\PushTypeEnum::TAKEAPART_ALARM,//拆动报警
  117. \Rlfd\Alarm\PushTypeEnum::TURN_ALARM,//翻转报警
  118. );
  119. if(!is_array($msg_data)){
  120. return array( 'success' => false , 'message' => 'invalid message data format!'.$msg_data);
  121. }
  122. // 通过传过来的车牌查出 JgClientRegistrationId
  123. if( empty($client) ){
  124. $client = new \JPush\Client( C('JPUSH_APP_KEY'), C('JPUSH_MASTER_SECRET') );
  125. }
  126. if( in_array($msg_data['type'],$single_push_type) && $msg_data['device_number'] ){
  127. // 判断是否在围栏告警时间间隔内
  128. $ctlRes = $this->alarmIntervalControl($msg_data);
  129. if(!$ctlRes['success']){
  130. return $ctlRes;
  131. }
  132. // 取车辆数据
  133. $where = array('DeviceNumber|GpsDeviceNumber' => $msg_data['device_number']);
  134. $fields= 'CityId,LicensePlate,FullName,JgClientRegistrationId';
  135. if( !S( 'jpush_vinfo_'.$msg_data['device_number'] ) ){ //如果不存在,则缓存
  136. $vehicle_info = M('jms_vehicle')->field($fields)->where($where)->find();
  137. S( 'jpush_vinfo_'.$msg_data['device_number'], $vehicle_info, 60 ); //缓存1分钟
  138. }
  139. $vehicle_info = S( 'jpush_vinfo_'.$msg_data['device_number'] ); //从缓存取
  140. if(!$vehicle_info['JgClientRegistrationId']){
  141. return array('success'=> false,'message'=>'jpush registration id not exists!');
  142. }
  143. }elseif( $msg_data['type'] == \Rlfd\Alarm\PushTypeEnum::BROADCASTING ){
  144. //广播
  145. }else{
  146. return array( 'success' => false , 'message' => '未知的告警类型:'.$msg_data['type'] );
  147. }
  148. // 推送平台
  149. $platform = array('ios', 'android');
  150. // 通知栏显示内容
  151. $alert = $msg_data['content'];
  152. // 推送android
  153. $android_notification = array(
  154. 'title' => $msg_data['title'],
  155. 'builder_id' => 2, //通知栏样式
  156. );
  157. // 推送ios
  158. $ios_notification = array(
  159. 'sound' => 'default',
  160. 'badge' => '+1',
  161. 'content-available' => true
  162. );
  163. // 可选项
  164. $options = array(
  165. 'sendno' => 100,
  166. 'time_to_live' => 100,
  167. );
  168. // 组装推送
  169. $cid = $client->push()->getCid();
  170. //var_dump($cid['body']['cidlist'][0]);
  171. $push_payload = $client->push()
  172. ->setCid($cid['body']['cidlist'][0])
  173. ->setPlatform( $platform )
  174. ->iosNotification($alert, $ios_notification)
  175. ->androidNotification($alert, $android_notification)
  176. ->options($options);
  177. if( $msg_data['type'] == \Rlfd\Alarm\PushTypeEnum::BROADCASTING ){ // 9-广播
  178. $push_payload->addAllAudience();
  179. }elseif( isset($vehicle_info) && $vehicle_info ){ // 单推
  180. $msg_data['vehicle_info'] = $vehicle_info;
  181. $push_payload->addRegistrationId($vehicle_info['JgClientRegistrationId']);
  182. }else{
  183. //未知类型
  184. var_dump('出错了:'.$msg_data);
  185. return;
  186. }
  187. try {
  188. $response = $push_payload->send();
  189. // 保存日志
  190. $msg_data['response'] = array(
  191. 'code' => $response['http_code'],
  192. 'resp_msg' => 'ok',
  193. );
  194. if(!$this->saveLog($msg_data)){
  195. return array( 'success' => false , 'message' => 'add log failed 1' );
  196. }
  197. if( $response['http_code'] == 200 ){ //如果成功了
  198. if( C('FENCE_ALARM_INTERVAL') && $msg_data['type'] == \Rlfd\Alarm\PushTypeEnum::FENCE_ALARM ){
  199. //设置最后围栏告警时间缓存
  200. S('last_fence_alarm_'.$msg_data['device_number'], time(), C('FENCE_ALARM_INTERVAL')*60);
  201. }
  202. return array( 'success' => true , 'message' => 'ok' );
  203. }
  204. } catch (\JPush\Exceptions\APIConnectionException $e) {
  205. // try something here
  206. $msg_data['response'] = array(
  207. 'code' => $e->getHttpCode(),
  208. 'resp_msg' => substr($e->__toString(), strpos($e->__toString(),'[')),
  209. );
  210. if(!$this->saveLog($msg_data)){
  211. return array( 'success' => false , 'message' => 'add log failed 2' );
  212. }
  213. print $e;
  214. } catch (\JPush\Exceptions\APIRequestException $e) {
  215. // try something here
  216. $msg_data['response'] = array(
  217. 'code' => $e->getHttpCode(),
  218. 'resp_msg' => substr($e->__toString(), strpos($e->__toString(),'[')),
  219. );
  220. if(!$this->saveLog($msg_data)){
  221. return array( 'success' => false , 'message' => 'add log failed 3' );
  222. }
  223. print $e;
  224. }
  225. }
  226. private function saveLog( $msg_data ){
  227. $fdls_app_message = M('jms_baojing_message');
  228. $log_data = array(
  229. 'ID' => create_guid(),
  230. 'Type' => $msg_data['type'],
  231. 'Title' => $msg_data['title'],
  232. 'Comment' => $msg_data['content'],
  233. 'SendStatus' => $msg_data['response']['code'],
  234. 'AddTime' => date('Y-m-d H:i:s'),
  235. 'RespMsg' => $msg_data['response']['resp_msg'],
  236. );
  237. if( $msg_data['type'] != C('BROADCASTING') ){ // 非广播
  238. $log_data['CityId'] = $msg_data['vehicle_info']['CityId'];
  239. $log_data['DeviceNumber'] = $msg_data['device_number'];
  240. $log_data['FullName'] = $msg_data['vehicle_info']['FullName'];
  241. $log_data['LicensePlate'] = $msg_data['vehicle_info']['LicensePlate'];
  242. }
  243. $result = $fdls_app_message->createAdd($log_data);
  244. return $result;
  245. }
  246. private function alarmIntervalControl( $msg_data ){
  247. if(empty($msg_data)){
  248. return array( 'success' => false , 'message' => '告警数据为空' );
  249. }
  250. if($msg_data['type'] == \Rlfd\Alarm\PushTypeEnum::FENCE_ALARM ){
  251. $interval = C('FENCE_ALARM_INTERVAL_SECOND') ? C('FENCE_ALARM_INTERVAL_SECOND') : 120;
  252. $type = '围栏告警';
  253. $cache = 'last_fence_alarm_';
  254. }
  255. if($msg_data['type'] == \Rlfd\Alarm\PushTypeEnum::OUTAGE_ALARM ){
  256. $interval = C('OUTAGE_ALARM_INTERVAL_SECOND') ? C('OUTAGE_ALARM_INTERVAL_SECOND') : 300;
  257. $type = '断电告警';
  258. $cache = 'last_outage_alarm_';
  259. }
  260. if($msg_data['type'] == \Rlfd\Alarm\PushTypeEnum::FENCE_ALARM ){
  261. $interval = C('HIGHVOLTAGE_ALARM_INTERVAL_SECOND') ? C('HIGHVOLTAGE_ALARM_INTERVAL_SECOND') : 300;
  262. $type = '高电压报警';
  263. $cache = 'last_highvoltage_alarm_';
  264. }
  265. if($msg_data['type'] == \Rlfd\Alarm\PushTypeEnum::SHIFT_ALARM ){
  266. $redis = Redis('czapp_lock_status', 'hash');
  267. $lockStatus = $redis->get($msg_data['device_number']);
  268. if($lockStatus == 1){
  269. return array('success' => false, 'message' => $msg_data['device_number'].'已启用czapp锁车,无需推送gps位移告警');
  270. }
  271. $interval = C('SHIFT_ALARM_INTERVAL_SECOND') ? C('SHIFT_ALARM_INTERVAL_SECOND') : 120;
  272. $type = 'gps位移报警';
  273. $cache = 'last_shift_alarm_';
  274. }
  275. if($msg_data['type'] == \Rlfd\Alarm\PushTypeEnum::LOCK_VEHICLE_ALARM ){
  276. $interval = C('LOCK_ALARM_INTERVAL_SECOND') ? C('LOCK_ALARM_INTERVAL_SECOND') : 120;
  277. $type = '锁车报警';
  278. $cache = 'last_lock_alarm_';
  279. }
  280. if($msg_data['type'] == \Rlfd\Alarm\PushTypeEnum::TAKEAPART_ALARM ){
  281. $interval = C('TAKEAPART_ALARM_INTERVAL_SECOND') ? C('TAKEAPART_ALARM_INTERVAL_SECOND') : 120;
  282. $type = '拆动报警';
  283. $cache = 'last_takeapart_alarm_';
  284. }
  285. if($msg_data['type'] == \Rlfd\Alarm\PushTypeEnum::TAKEAPART_ALARM ){
  286. $interval = C('CRASH_ALARM_INTERVAL_SECOND') ? C('CRASH_ALARM_INTERVAL_SECOND') : 120;
  287. $type = '碰撞报警';
  288. $cache = 'last_crash_alarm_';
  289. }
  290. if($msg_data['type'] == \Rlfd\Alarm\PushTypeEnum::TURN_ALARM ){
  291. $interval = C('TURN_ALARM_INTERVAL_SECOND') ? C('TURN_ALARM_INTERVAL_SECOND') : 120;
  292. $type = '翻转报警';
  293. $cache = 'last_turn_alarm_';
  294. }
  295. // \Rlfd\Alarm\PushTypeEnum::SHIFT_ALARM,// C('SHIFT_ALARM'), // 5-位移报警
  296. // \Rlfd\Alarm\PushTypeEnum::LOCK_VEHICLE_ALARM,// C('LOCK_VEHICLE_ALARM'), // 6-锁车告警
  297. return $this->getResultInterval($interval, $msg_data, $type, $cache);
  298. }
  299. public function getResultInterval( $interval, $msg_data, $type, $cache ){
  300. $last_alarm_time = S( $cache.$msg_data['device_number'] );
  301. if( time() - $last_alarm_time < $interval ){
  302. return array( 'success' => false , 'message' => $msg_data['device_number'] . '【'. $type .'】' . ' 不可推送,推送间隔最小为:'. $interval. '秒,最后一次告警时间:'.$last_alarm_time );
  303. }else{
  304. return array( 'success' => true , 'message' => $msg_data['device_number'] . '【'. $type .'】' .' 不在限制间隔内,可以推送');
  305. }
  306. }
  307. }