package com.ruoyi.task; import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONObject; import com.mashape.unirest.http.HttpResponse; import com.mashape.unirest.http.Unirest; import com.mashape.unirest.http.exceptions.UnirestException; import com.ruoyi.aibrain.domain.AiCamera; import com.ruoyi.aibrain.service.IAiCameraService; import com.ruoyi.camera.domain.CameraShipingsb; import com.ruoyi.camera.service.ICameraShipingsbService; import com.ruoyi.common.config.RuoYiConfig; import com.ruoyi.common.constant.CacheConstants; import com.ruoyi.common.core.domain.model.LoginUser; import com.ruoyi.common.core.redis.RedisCache; import com.ruoyi.common.utils.http.HttpUtils; import com.ruoyi.common.utils.spring.SpringUtils; import com.ruoyi.interchange.domain.TbDataSendRecords; import com.ruoyi.interchange.service.ITbDataSendRecordsService; import com.ruoyi.system.domain.SysUserOnline; import okhttp3.*; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import java.io.File; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.*; import java.util.concurrent.TimeUnit; public class CameraAssembleUtil { private static IAiCameraService aiCameraService; private static ICameraShipingsbService cameraShipingsbService; private static ITbDataSendRecordsService tbDataSendRecordsService; private static RedisCache redisCache; private static String SJURL="https://192.168.100.89:4200/spjr000/api/open/v1"; //省级请求地址 private static String MKBM= RuoYiConfig.getMkbm(); //煤矿编码 private static String MKMC= RuoYiConfig.getMkmc(); //煤矿名称 private static String SCCJ="徐州珂尔玛科技有限公司"; //生产厂家名称 private static String XTXH="KEM2023SPJKXT"; //系统型号 private static String XTMC="AI智能视频监控系统"; //系统名称 //接口说明:https://192.168.100.89:4200/spjr000/swagger/index.html //上传接口:https://192.168.100.89:4200/spjr000/api/open/v1/ai/channel/general/push private static SimpleDateFormat YMDformat = new SimpleDateFormat("yyyy-MM-dd"); private static SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss"); private static SimpleDateFormat formatYMD = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); static { aiCameraService = SpringUtils.getBean(IAiCameraService.class); cameraShipingsbService = SpringUtils.getBean(ICameraShipingsbService.class); tbDataSendRecordsService = SpringUtils.getBean(ITbDataSendRecordsService.class); redisCache = SpringUtils.getBean(RedisCache.class); } //AI分析识别数据传输 //HTTPS://ip:port/api/open/v1/ai/channel/general/push/ //煤矿企业编码 company String(12) //摄像头编码 biz String(5) //分析类型编码 channel String(2) //数据上报时间 pdt String(10) UTC 时间戳 //运输设备视频 (掘进工作面带式输送机机头、采煤工作面刮板机及带式输送机机头) file 上限10兆 //视频文件命名格式如下:煤矿企业编码+摄像头编码+分析类型编码+生产、运输设备运行状态编码+当前时间+.MP4,编码规范具体参考表 5-18 基础编码表。例如在 2021 年1月4日12点15分46秒识别到一煤矿企业掘进工作面带式输送机机头由停止变为运行,并且有煤,企业立即上传证据视频,视频文件名称为:1404210078660700200003000120210104121546.MP4 //扩展参数 data list String(255) //1.运输设备运行状态识别信息 //2.工作面出口障碍物识别信息 //3.单体柱状态识别信息 //4.堆煤识别信息 //5.危险区域警戒线(电子围栏)内人员进入识别信息 //6.马头门罐笼摇台状态识别信息 //7.摄像头遮挡、挪动角度识别信息 public static void cameraAiError() throws ParseException { SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss"); //查询出所以未传输的报警 Collection keys = redisCache.keys("video_*"); for (String key : keys) { JSONObject errObj = redisCache.getCacheObject(key); AiCamera aiCamera = redisCache.getCacheObject("AI::AiCameraObj"+errObj.getString("cameraCode")); if(aiCamera!=null){ String shiBieLXMC=getShiBieLXMC(errObj.getString("analyse")); if(shiBieLXMC.equals("未找到的类别")){ errObj.put("error","未找到的类别"); redisCache.setCacheObject("SC::error::"+key,errObj,10,TimeUnit.DAYS); }else{ Date warningTime=sdf.parse(errObj.getString("warningTime")); //需结合AI分析进行完善 CameraShipingsb cameraShipingsb=new CameraShipingsb(); cameraShipingsb.setSheXiangTID(aiCamera.getId());//摄像头ID cameraShipingsb.setSheXiangTBM(errObj.getString("cameraCode"));//摄像头编码 cameraShipingsb.setShiBieLXBM(errObj.getString("analyseResult"));//识别类型编码 cameraShipingsb.setShiBieLXMC(shiBieLXMC);//识别类型名称 cameraShipingsb.setFenXiLXBM(errObj.getString("analyse"));//分析类型编码 cameraShipingsb.setFileUrl(errObj.getString("recordFileName"));//识别视频存储地址 cameraShipingsb.setShuJuSJ(warningTime);//数据时间 cameraShipingsbService.insertCameraShipingsb(cameraShipingsb); JSONObject objCS=new JSONObject(); objCS.put("type","AI分析"); objCS.put("sendSum",0); JSONObject obj=new JSONObject(); obj.put("company",MKBM);//煤矿企业编码 obj.put("biz",aiCamera.getCameraNum());//摄像头编码 obj.put("channel",cameraShipingsb.getFenXiLXBM() + cameraShipingsb.getShiBieLXBM());//分析类型编码 long currentTime=warningTime.getTime()/1000; obj.put("pdt",currentTime);//数据上报时间 obj.put("file",cameraShipingsb.getFileUrl());//运输设备视频 obj.put("data","[]");//扩展参数 objCS.put("data",obj); redisCache.rightPush("CameraAssemble",objCS); redisCache.setCacheObject("SC::success::"+key,errObj,10,TimeUnit.DAYS); } }else{ errObj.put("error","未找到该摄像头"); redisCache.setCacheObject("SC::error::"+key,errObj,10,TimeUnit.DAYS); } redisCache.deleteObject(keys); } } /**识别结果,按上级要求定制,都归属于以下识别类型(在IPCConfig.xml文件中配置) * 运输设备运行状态 003 * 人员入井 004 * 货运车辆 005 * 人员睡岗 007 * 人员空岗 008 * 危险区域人员闯入 013 * 摄像头遮挡 020 * 摄像头挪动角度 021 * 罐笼摇台未到位 057 * 单体柱倾倒识别 059 * 障碍物堵塞识别 060 * 堆煤识别 062 * */ public static String getShiBieLXMC(String shiBieLXBM){ switch (shiBieLXBM){ case "003": return "运输设备运行状态"; case "004": return "人员入井"; case "005": return "货运车辆"; case "007": return "人员睡岗"; case "008": return "人员空岗"; case "013": return "危险区域人员闯入"; case "020": return "摄像头遮挡"; case "021": return "摄像头挪动角度"; case "057": return "罐笼摇台未到位"; case "059": return "单体柱倾倒识别"; case "060": return "障碍物堵塞识别"; case "062": return "堆煤识别"; default: return "未找到的类别"; } } //8.带标记实时播放地址(需鉴权 实时视频地址变动时) //HTTPS://ip:port/api/open/v1/ai/video/register/ //煤矿企业编码 company String(12) //摄像头编码 biz String(5) //识别视频流名称/简称 name String(32) //视频接入协议 protocol String(12) //接入视频编码 raw_codec String(5) //实时视频地址 url String(128) public static void cameraInfo(){ AiCamera aiCamera=new AiCamera(); aiCamera.setStatus("1");//启用的摄像头 List list = aiCameraService.selectAiCameraList(aiCamera); JSONObject objCS=new JSONObject(); objCS.put("type","摄像头信息"); objCS.put("sendSum",0); for (int i = 0; i < list.size(); i++) { AiCamera aiCameraObj=list.get(i); JSONObject obj=new JSONObject(); obj.put("company",MKBM);//煤矿企业编码 obj.put("biz",aiCameraObj.getCameraNum());//摄像头编码 obj.put("name",aiCameraObj.getName());//识别视频流名称/简称 obj.put("protocol","RTMP");//视频接入协议 obj.put("raw_codec","H.264");//接入视频编码 obj.put("url",aiCameraObj.getToRtmp());//实时视频地址 objCS.put("data",obj); redisCache.rightPush("CameraAssemble",objCS); } } //9.摄像头在线、离线检测信息(每 5分钟一次) //HTTPS://ip:port/api/open/v1/probe/status/push/ //煤矿企业编码 company String(12) //摄像头编码 biz String(5) //分析类型编码 biz_type String(2) //子系统采集类型 link_type 固定为 AI String(2) //采集传输频率 freq 固定为 0 String(1) //采集类型 freq_channel 固定为空字符串 int(1) //软件运行状态 status int(1) 摄像头离线时,推送值为 0,摄像头在线状态时,值为 1 public static void cameraSatus(){ AiCamera aiCamera=new AiCamera(); aiCamera.setStatus("1");//启用的摄像头 List list = aiCameraService.selectAiCameraList(aiCamera); JSONObject objCS=new JSONObject(); objCS.put("type","状态检测"); objCS.put("sendSum",0); for (int i = 0; i < list.size(); i++) { AiCamera aiCameraObj=list.get(i); JSONObject obj=new JSONObject(); obj.put("company",MKBM);//煤矿企业编码 obj.put("biz",aiCameraObj.getCameraNum());//摄像头编码 obj.put("biz_type",aiCameraObj.getCameraModel());//摄像头分析类型编码 obj.put("link_type","AI");//子系统采集类型 固定为 AI obj.put("freq","0");//采集传输频率 固定为 0 obj.put("freq_channel","");//采集类型 固定为空字符串 obj.put("status",aiCameraObj.getRunStatus());//软件运行状态 objCS.put("data",obj); redisCache.rightPush("CameraAssemble",objCS); } } public static void DataTransmission(JSONObject obj) throws UnirestException { //通过https方式发送 //取出的数据 System.out.println("AI上传开始发送数据:"+obj.toString()); JSONObject paramJson=obj.getJSONObject("data"); TbDataSendRecords tbDataSendRecords=new TbDataSendRecords(); tbDataSendRecords.setFileName(paramJson.toJSONString());//文件名 tbDataSendRecords.setDataHeader("");//数据头 tbDataSendRecords.setDataNumber(1l);//数据数量 tbDataSendRecords.setCoalMineId(1l);//所属煤矿ID tbDataSendRecords.setSystemId(1l);//所属系统ID tbDataSendRecords.setRuleId(1l);//数据文件采集规则ID tbDataSendRecords.setDetectionTime(new Date());//文件处理时间 tbDataSendRecords.setDetectionResult("0");//是否系统生成的 0是 1否 tbDataSendRecords.setCheckResult("1");//校验结果 0通过 1未通过 if(obj.getString("type").equals("AI分析")){ DataTransmissionAiFX(paramJson,tbDataSendRecords); tbDataSendRecords.setSendFileUrl(paramJson.getString("file"));//文件发送FTP位置 }else if(obj.getString("type").equals("摄像头信息")){ DataTransmissionCameraInfo(paramJson,tbDataSendRecords); }else if(obj.getString("type").equals("状态检测")){ DataTransmissionCameraStaus(paramJson,tbDataSendRecords); } tbDataSendRecordsService.insertTbDataSendRecords(tbDataSendRecords); } //AI分析识别数据传输 //HTTPS://ip:port/api/open/v1/ai/channel/general/push/ //煤矿企业编码 company String(12) //摄像头编码 biz String(5) //分析类型编码 channel String(2) //数据上报时间 pdt String(10) UTC 时间戳 //运输设备视频 (掘进工作面带式输送机机头、采煤工作面刮板机及带式输送机机头) file 上限10兆 //视频文件命名格式如下:煤矿企业编码+摄像头编码+分析类型编码+生产、运输设备运行状态编码+当前时间+.MP4,编码规范具体参考表 5-18 基础编码表。例如在 2021 年1月4日12点15分46秒识别到一煤矿企业掘进工作面带式输送机机头由停止变为运行,并且有煤,企业立即上传证据视频,视频文件名称为:1404210078660700200003000120210104121546.MP4 //扩展参数 data list String(255) //1.运输设备运行状态识别信息 //2.工作面出口障碍物识别信息 //3.单体柱状态识别信息 //4.堆煤识别信息 //5.危险区域警戒线(电子围栏)内人员进入识别信息 //6.马头门罐笼摇台状态识别信息 //7.摄像头遮挡、挪动角度识别信息 public static void DataTransmissionAiFX(JSONObject paramJson,TbDataSendRecords tbDataSendRecords) { System.out.println("xxxxxxxxxxxxxxxx"); //String参数 Map params = new HashMap(); params.put("company",paramJson.getString("company"));//煤矿企业编码 params.put("biz",paramJson.getString("biz"));//摄像头编码 params.put("channel",paramJson.getString("channel"));//分析类型编码 params.put("pdt",paramJson.getString("pdt"));//数据上报时间 params.put("data",paramJson.getString("data"));//扩展参数 String boundary = "------WebKitFormBoundary7MA4YWxkTrZu0gW--"; // 设置boundary字符串,用于标识参数和附件的边界 final TrustManager[] trustAllCerts = new TrustManager[]{ new X509TrustManager() { @Override public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) { } @Override public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) { } @Override public java.security.cert.X509Certificate[] getAcceptedIssuers() { return new java.security.cert.X509Certificate[]{}; } } }; //请求地址 String url = SJURL+"/ai/channel/general/push/"; try{ final SSLContext sslContext = SSLContext.getInstance("SSL"); sslContext.init(null, trustAllCerts, new java.security.SecureRandom()); final javax.net.ssl.SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory(); OkHttpClient client = new OkHttpClient.Builder() .connectTimeout(30, TimeUnit.SECONDS) .readTimeout(30, TimeUnit.SECONDS) .sslSocketFactory(sslSocketFactory, (X509TrustManager) trustAllCerts[0]) .hostnameVerifier((hostname, session) -> true) // 信任所有主机名 .build(); String fileUrl=paramJson.getString("file"); File file = new File(fileUrl); //fileUrl.split("\\"); String[] fileName=fileUrl.split("\\\\"); RequestBody body = new MultipartBody.Builder() .setType(MultipartBody.FORM) .addFormDataPart("company", params.get("company")) .addFormDataPart("biz", params.get("biz")) .addFormDataPart("channel", params.get("channel")) .addFormDataPart("pdt", params.get("pdt")) .addFormDataPart("data", params.get("data")) .addFormDataPart("file", fileName[fileName.length-1], RequestBody.create(MediaType.parse("application/octet-stream"), file)) .build(); Request request = new Request.Builder() .url(url) .header("Content-Type", "multipart/form-data; boundary=" + boundary) .post(body) .build(); Response response = client.newCall(request).execute(); if (response.isSuccessful()) { System.out.println("数据推送成功"); tbDataSendRecords.setSendResult("0");//发送结果 0成功 1失败 System.out.println("File uploaded successfully."+response.toString()); } else { System.out.println("数据推送失败"); tbDataSendRecords.setSendResult("1");//发送结果 0成功 1失败 System.out.println("Failed to upload file. Response code: " + response.code()); } }catch (Exception e){ System.out.println("数据推送失败"+e.getMessage()); tbDataSendRecords.setSendResult("1");//发送结果 0成功 1失败 } } //8.带标记实时播放地址(需鉴权 实时视频地址变动时) //HTTPS://ip:port/api/open/v1/ai/video/register/ //煤矿企业编码 company String(12) //摄像头编码 biz String(5) //识别视频流名称/简称 name String(32) //视频接入协议 protocol String(12) //接入视频编码 raw_codec String(5) //实时视频地址 url String(128) public static void DataTransmissionCameraInfo(JSONObject paramJson,TbDataSendRecords tbDataSendRecords){ //Map params= JSONObject.parseObject(paramJson.toString(),Map.class);; //String respJson = HttpClientUtilHttps.doPost(SJURL+"/ai/video/register/",params, "UTF-8"); String respJson = HttpUtils.sendJsonToHttpsPost(SJURL+"/ai/video/register/",paramJson.toString()); JSONObject data = JSONObject.parseObject(respJson); if (data == null) { System.out.println("数据推送失败"); tbDataSendRecords.setSendResult("1");//发送结果 0成功 1失败 }else{ System.out.println("数据推送成功"+data.toString()); tbDataSendRecords.setSendResult("0");//发送结果 0成功 1失败 } } //9.摄像头在线、离线检测信息(每 30秒一次) //HTTPS://ip:port/api/open/v1/probe/status/push/ //煤矿企业编码 company String(12) //摄像头编码 biz_type String(5) //分析类型编码 channel String(2) //子系统采集类型 link_type 固定为 AI String(2) //采集传输频率 freq 固定为 0 String(1) //采集类型 freq_channel 固定为空字符串 int(1) //软件运行状态 status int(1) 摄像头离线时,推送值为 0,摄像头在线状态时,值为 1 public static void DataTransmissionCameraStaus(JSONObject paramJson,TbDataSendRecords tbDataSendRecords){ //Map params= JSONObject.parseObject(paramJson.toString(),Map.class);; //String respJson = HttpClientUtilHttps.doPost(SJURL+"/ai/status/push/",params, "UTF-8"); String respJson = HttpUtils.sendJsonToHttpsPost(SJURL+"/ai/status/push/",paramJson.toString()); JSONObject data = JSONObject.parseObject(respJson); if (data == null) { System.out.println("数据推送失败"); tbDataSendRecords.setSendResult("1");//发送结果 0成功 1失败 }else{ System.out.println("数据推送成功"+data.toString()); tbDataSendRecords.setSendResult("0");//发送结果 0成功 1失败 } } }