소스 검색

新增大华云睿监控对接

liuyaowen 1 년 전
부모
커밋
bd75fe1766

+ 9 - 0
src/main/java/com/yunfeiyun/agmp/iots/core/http/DaHuaYunRuiHttpConfig.java

@@ -0,0 +1,9 @@
+package com.yunfeiyun.agmp.iots.core.http;
+
+import lombok.Data;
+
+@Data
+public class DaHuaYunRuiHttpConfig extends HttpConfig{
+    private String client_id;
+    private String client_secret;
+}

+ 151 - 0
src/main/java/com/yunfeiyun/agmp/iots/core/http/YunRuiMonitorClient.java

@@ -0,0 +1,151 @@
+package com.yunfeiyun.agmp.iots.core.http;
+
+import com.alibaba.fastjson2.JSONObject;
+import com.alibaba.fastjson2.JSONWriter;
+import com.yunfeiyun.agmp.common.constant.ErrorCode;
+import com.yunfeiyun.agmp.common.enums.RedisCacheKey;
+import com.yunfeiyun.agmp.common.exception.BizException;
+import com.yunfeiyun.agmp.common.framework.manager.RedisCacheManager;
+import com.yunfeiyun.agmp.common.utils.spring.SpringUtils;
+import com.yunfeiyun.agmp.iot.common.constant.devicetype.ServiceNameConst;
+import com.yunfeiyun.agmp.iots.common.annotate.HttpCore;
+import com.yunfeiyun.agmp.iots.common.modal.IotDeviceconnResVo;
+import com.yunfeiyun.agmp.iots.device.common.dh.DaHuaYunRuiApi;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.http.conn.ssl.NoopHostnameVerifier;
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
+import org.apache.http.conn.ssl.TrustStrategy;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.ssl.SSLContexts;
+import org.springframework.http.*;
+import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
+import org.springframework.util.StringUtils;
+import org.springframework.web.client.RestTemplate;
+import javax.net.ssl.SSLContext;
+import java.security.KeyManagementException;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author zhangn
+ */
+@Slf4j
+@HttpCore(serviceName = ServiceNameConst.SERVICE_YUN_RUI_MINITOR)
+public class YunRuiMonitorClient extends HttpClient {
+
+
+    private RestTemplate restTemplate;
+
+    private String clientId ;
+    private String clientSecret;
+    private String baseUrl;
+
+    private RedisCacheManager redisCacheManager;
+
+    @Override
+    public void init(IotDeviceconnResVo iotDeviceconnResVo, JSONObject configJson) {
+        try {
+            super.init(iotDeviceconnResVo,configJson);
+            initRestTemplate();
+            clientId = configJson.getString("client_id");
+            clientSecret = configJson.getString("client_secret");
+            baseUrl = configJson.getString("baseurl");
+            redisCacheManager = SpringUtils.getBean(RedisCacheManager.class);
+        } catch (Exception e) {
+            log.error("萤石云httpClient初始化失败",e);
+        }
+    }
+
+    private void initRestTemplate() throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
+        TrustStrategy acceptingTrustStrategy = (chain, authType) -> true;
+        SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(null, acceptingTrustStrategy).build();
+        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
+        HttpClientBuilder clientBuilder = HttpClients.custom();
+        CloseableHttpClient httpClient = clientBuilder.setSSLSocketFactory(sslsf).build();
+        HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
+        requestFactory.setConnectTimeout(1000 * 10 );
+        requestFactory.setReadTimeout(1000 * 10 );
+        requestFactory.setConnectionRequestTimeout(1000 * 10 );
+        requestFactory.setHttpClient(httpClient);
+        restTemplate = new RestTemplate(requestFactory);
+    }
+    public String getAccessToken() {
+        String accessToken = redisCacheManager.getCacheObject(RedisCacheKey.IOT_DAHUA_RUIYUN_CLOUD_HTTP_TOKEN, clientId);
+        if (StringUtils.isEmpty(accessToken)) {
+            accessToken = refreshAccessToken();
+        }
+        return accessToken;
+    }
+
+    /**
+     * 认证接口,
+     */
+    public String refreshAccessToken() {
+
+        JSONObject param = new JSONObject();
+        param.put("grant_type", "client_credentials");
+        param.put("scope", "server");
+        param.put("client_id", clientId);
+        param.put("client_secret", clientSecret);
+        MultiValueMap<String, String> headers = new HttpHeaders();
+        headers.add("Content-Type", "application/json");
+        HttpEntity<?> httpEntity = new HttpEntity<>(param, headers);
+        ResponseEntity<String> responseEntity = restTemplate.exchange(baseUrl + DaHuaYunRuiApi.GET_ACCESS_TOKEN, HttpMethod.POST, httpEntity, String.class);
+        if (responseEntity.getStatusCode().equals(HttpStatus.OK)) {
+            JSONObject result = JSONObject.parseObject(responseEntity.getBody());
+            if (null != result ) {
+                String accessToken = result.getString("token_type") + " " + result.getString("access_token");
+                long expires = Long.parseLong(result.getString("expires_in")) - 100;
+                redisCacheManager.setCacheObject(RedisCacheKey.IOT_DAHUA_RUIYUN_CLOUD_HTTP_TOKEN, clientId, accessToken, expires, TimeUnit.SECONDS);
+                return accessToken;
+            }
+        }
+        return null;
+    }
+
+    public Object postExchange(String url, JSONObject body, Class<?> responseType) {
+        MultiValueMap<String, String> headers = new HttpHeaders();
+        headers.add("Content-Type", "application/json");
+        headers.add("Authorization", getAccessToken());
+        HttpEntity<?> httpEntity = new HttpEntity<>(body, headers);
+        try {
+            ResponseEntity<String> responseEntity = restTemplate.exchange(baseUrl + url, HttpMethod.POST, httpEntity, String.class, new ArrayList<>());
+            if (responseEntity.getStatusCode().equals(HttpStatus.OK)) {
+                // 说明网络请求正常
+                return JSONObject.parseObject(responseEntity.getBody(), responseType);
+            }
+        } catch (Exception e) {
+            log.error("{}", e);
+            throw new BizException(ErrorCode.API_DISABLED);
+        }
+        throw new BizException(ErrorCode.API_DISABLED);
+    }
+
+    public Object getExchange(String url, JSONObject body, Class<?> responseType) {
+        MultiValueMap<String, String> paramsMap = new LinkedMultiValueMap<>();
+        paramsMap.setAll(JSONObject.parseObject(body.toJSONString(JSONWriter.Feature.IgnoreNoneSerializable), HashMap.class));
+        MultiValueMap<String, String> headers = new HttpHeaders();
+        headers.add("Content-Type", "application/x-www-form-urlencoded");
+        headers.add("Authorization", getAccessToken());
+        HttpEntity<?> httpEntity = new HttpEntity<>(null, headers);
+        try {
+            ResponseEntity<String> responseEntity = restTemplate.exchange(baseUrl + url, HttpMethod.GET, httpEntity, String.class, paramsMap.toSingleValueMap());
+            if (responseEntity.getStatusCode().equals(HttpStatus.OK)) {
+                // 说明网络请求正常
+                return JSONObject.parseObject(responseEntity.getBody(), responseType);
+            }
+        } catch (Exception e) {
+            log.error("{}", e);
+            throw new BizException(ErrorCode.API_DISABLED);
+        }
+        throw new BizException(ErrorCode.API_DISABLED);
+    }
+
+}

+ 6 - 6
src/main/java/com/yunfeiyun/agmp/iots/core/manager/ConnectionManager.java

@@ -1,22 +1,18 @@
 package com.yunfeiyun.agmp.iots.core.manager;
 
-import com.alibaba.fastjson2.JSON;
 import com.alibaba.fastjson2.JSONArray;
 import com.alibaba.fastjson2.JSONObject;
 import com.yunfeiyun.agmp.common.utils.StringUtils;
 import com.yunfeiyun.agmp.iot.common.constant.devicetype.IotDeviceDictEnum;
-import com.yunfeiyun.agmp.iot.common.constant.devicetype.IotDeviceTypeLv1Enum;
 import com.yunfeiyun.agmp.iot.common.domain.IotDevice;
 import com.yunfeiyun.agmp.iot.common.domain.IotDeviceconn;
 import com.yunfeiyun.agmp.iot.common.domain.TosDevicetype;
 import com.yunfeiyun.agmp.iot.common.model.mq.IotDeviceEditMqModel;
 import com.yunfeiyun.agmp.iot.common.service.DeviceconnCacheService;
-import com.yunfeiyun.agmp.iot.common.service.TypeCacheService;
 import com.yunfeiyun.agmp.iots.common.modal.IotDeviceconnResVo;
 import com.yunfeiyun.agmp.iots.core.mqtt.DeviceTopicService;
 import com.yunfeiyun.agmp.iots.core.mqtt.modal.MqttTopicValue;
 import com.yunfeiyun.agmp.iots.service.BusinessCoreService;
-import com.yunfeiyun.agmp.iots.task.IotStatusService;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.http.util.TextUtils;
 import org.eclipse.paho.client.mqttv3.MqttException;
@@ -24,7 +20,6 @@ import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
-import javax.annotation.PostConstruct;
 import javax.annotation.Resource;
 import java.util.ArrayList;
 import java.util.List;
@@ -46,6 +41,8 @@ public class ConnectionManager {
     @Resource
     private DeviceconnCacheService deviceconnCacheService;
 
+    private boolean INIT_SUCCESS = false;
+
     /**
      * 加载数据库设备配置
      *
@@ -71,9 +68,12 @@ public class ConnectionManager {
                 buildConnCoreByConfig(iotDeviceconnResVo, jsonConfig.getJSONObject(j));
             }
         }
-
+        this.INIT_SUCCESS = true;
     }
 
+    public boolean initCompleted(){
+        return this.INIT_SUCCESS;
+    }
 
 
     /**

+ 14 - 7
src/main/java/com/yunfeiyun/agmp/iots/core/manager/HttpManager.java

@@ -31,15 +31,16 @@ public class HttpManager {
     private TypeCacheService typeCacheService;
     @Resource
     private DeviceconnCacheService deviceconnCacheService;
+
     private HashMap<String, HttpClient> privateHttpClientByConnBid = new HashMap<>();
     private HashMap<String, HttpClient> commonHttpClientByTypeBid = new HashMap<>();
-
     private HashMap<String,Class<? extends HttpClient>> httpClinetClassMap = new HashMap<>();
 
+
     @PostConstruct
     public void init(){
         //获取该路径下所有类
-        Reflections reflections = new Reflections("com.yunfeiyun.agmp.iots");
+        Reflections reflections = new Reflections("com.yunfeiyun.agmp.iots.core.http");
         //获取继承了HttpClient的所有类
         Set<Class<? extends HttpClient>> classSet = reflections.getSubTypesOf(HttpClient.class);
         for (Class<? extends HttpClient> clazz : classSet){
@@ -60,10 +61,9 @@ public class HttpManager {
             // 私有连接处理
             initPrivateClient(iotDeviceconnResVo,configJson);
         }
-
-
     }
     private void initCommonClient(IotDeviceconnResVo iotDeviceconnResVo ,JSONObject configJson){
+        deviceconnCacheService.setHttpCommonConnectionByDevtypeCode(iotDeviceconnResVo.getDevconnBid(),iotDeviceconnResVo.getDevtypeCode());
         if(null != commonHttpClientByTypeBid.get(iotDeviceconnResVo.getDevtypeBid())){
             return;
         }
@@ -115,10 +115,17 @@ public class HttpManager {
     }
 
     public void deleteHttpConnection(String devconnBid) {
-        privateHttpClientByConnBid.remove(devconnBid);
+        IotDeviceconn iotDeviceconn = deviceconnCacheService.getIotDeviceConnByDevconnBid(devconnBid);
+        if(IotDeviceconnTypeEnum.COMMON.getCode().equals(iotDeviceconn.getDevconnType())){
+            // 如果http通用连接内没有绑定的连接
+            if(!deviceconnCacheService.httpConnectionBidHasLink(iotDeviceconn.getDevtypeBid())){
+                // 删除通用连接
+                commonHttpClientByTypeBid.remove(iotDeviceconn.getDevtypeBid());
+            }
+        }else {
+             privateHttpClientByConnBid.remove(devconnBid);
+        }
     }
 
-    public void updateCommonConnection(TosDevicetype tosDevicetype, JSONArray jsonConfig) {
 
-    }
 }

+ 34 - 0
src/main/java/com/yunfeiyun/agmp/iots/device/common/dh/DaHuaYunRuiApi.java

@@ -0,0 +1,34 @@
+package com.yunfeiyun.agmp.iots.device.common.dh;
+
+/**
+ * 大华Icc平台接口地址,域名是动态的,此处只设置接口地址
+ */
+public class DaHuaYunRuiApi {
+
+    /**
+     * 认证获取token
+     */
+    public static final String GET_ACCESS_TOKEN = "/gateway/auth/api/oauth/token";
+    /**
+     * 获取设备详情
+     */
+    public static final String DEVICE_PTZ_INFO = "/gateway/device/api/devicePTZInfo";
+    /**
+     * 获取视频流地址
+     */
+    public static final String REAL_TIME = "/gateway/videobussiness/api/device/liveInfo";
+    /**
+     * 云台方向控制
+     */
+    public static final String PTZ_OPERATE_DIRECT = "/gateway/device/api/controlLocationPTZ";
+    /**
+     * 远程抓拍
+     */
+    public static final String DMS = "/gateway/device/api/getChannelSnap";
+    /**
+     * 录像回放
+     */
+    public static final String BACK_VIEWS = "/gateway/device/api/getVideoLocalRecords";
+    /**查询设备是否在线*/
+    public static final String GET_DEVICE_INFO = "/gateway/device/api/deviceInfo";
+}

+ 6 - 0
src/main/java/com/yunfeiyun/agmp/iots/device/service/IYunRuiDevice.java

@@ -0,0 +1,6 @@
+package com.yunfeiyun.agmp.iots.device.service;
+
+import com.yunfeiyun.agmp.iots.device.common.HttpDevice;
+
+public interface IYunRuiDevice extends HttpDevice {
+}

+ 3 - 3
src/main/java/com/yunfeiyun/agmp/iots/device/serviceImp/IHikVisionEzvizDeviceImpl.java

@@ -118,7 +118,7 @@ public class IHikVisionEzvizDeviceImpl extends HttpDeviceAbstractImpl implements
                 iotMonitorCapture.setPicBid(iotMonitorCapture.getUUId());
                 iotMonitorCapture.setPicCreatedDate(DateUtils.dateTimeNow());
                 iotMonitorCapture.setPicUrl(resManager.saveMonitorHttpsImg(picUrl, ResConstants.BizType.EZVIZ_CAPTURE,devCode + "/" + new Date().getTime() + "-" + UUID.fastUUID(),"jpg"));
-                iotMonitorCapture.setCid(iotDevice.getTid());
+                iotMonitorCapture.setTid(iotDevice.getTid());
                 mongoService.saveOne(iotMonitorCapture);
             }
         }
@@ -178,8 +178,7 @@ public class IHikVisionEzvizDeviceImpl extends HttpDeviceAbstractImpl implements
             log.info("海康设备定时检测设备在线状态开始");
             List<CompletableFuture<JSONObject>> completableFutureList = new LinkedList<>();
             // 此处若后续数据较多时,可按租户分批处理
-            List<String> devTypeBidList = Arrays.asList(IotDeviceDictConst.TYPE_EZVIZ_JKSB,IotDeviceDictConst.TYPE_DAHUA_DEVICE,IotDeviceDictConst.TYPE_HIK_OPEN_DEVICE);
-
+            List<String> devTypeBidList = Collections.singletonList(IotDeviceDictConst.TYPE_EZVIZ_JKSB);
             List<IotDevice> iotDeviceList = iotDeviceService.selectIotDeviceByDevtypeBidList(devTypeBidList);
             Map<String,List<IotDevice>> map = iotDeviceList.stream().collect(Collectors.groupingBy(item->item.getDevCode().split("-")[0]));
             for(Map.Entry<String,List<IotDevice>> entry:map.entrySet()){
@@ -207,4 +206,5 @@ public class IHikVisionEzvizDeviceImpl extends HttpDeviceAbstractImpl implements
     public EzvizHttpClient ezvizHttpClient(IotDevice iotDevice){
         return (EzvizHttpClient) httpManager.getHttpClientByDevice(iotDevice);
     }
+
 }

+ 1 - 1
src/main/java/com/yunfeiyun/agmp/iots/device/serviceImp/IotBigDataMonitorDeviceImpl.java

@@ -40,7 +40,7 @@ public class IotBigDataMonitorDeviceImpl extends DeviceAbstractImpl implements D
             iotMonitorCapture.setPicBid(iotMonitorCapture.getUUId());
             iotMonitorCapture.setPicCreatedDate(DateUtils.dateTimeNow());
             iotMonitorCapture.setPicUrl(resManager.saveMonitorHttpsImg(picUrl, ResConstants.BizType.EZVIZ_CAPTURE,iotMonitorCapture.getPicBid(),"jpg"));
-            iotMonitorCapture.setCid(iotDevice.getTid());
+            iotMonitorCapture.setTid(iotDevice.getTid());
             mongoService.saveOne(iotMonitorCapture);
         }
         return null;

+ 420 - 0
src/main/java/com/yunfeiyun/agmp/iots/device/serviceImp/YunRuiMonitorService.java

@@ -0,0 +1,420 @@
+package com.yunfeiyun.agmp.iots.device.serviceImp;
+
+import com.alibaba.fastjson2.JSONArray;
+import com.alibaba.fastjson2.JSONObject;
+import com.yunfeiyun.agmp.common.constant.ErrorCode;
+import com.yunfeiyun.agmp.common.constant.ResConstants;
+import com.yunfeiyun.agmp.common.enums.RedisCacheKey;
+import com.yunfeiyun.agmp.common.exception.BizException;
+import com.yunfeiyun.agmp.common.framework.manager.RedisCacheManager;
+import com.yunfeiyun.agmp.common.framework.manager.ResManager;
+import com.yunfeiyun.agmp.common.log.LogCore;
+import com.yunfeiyun.agmp.common.utils.DateUtils;
+import com.yunfeiyun.agmp.common.utils.StringUtils;
+import com.yunfeiyun.agmp.common.utils.uuid.UUID;
+import com.yunfeiyun.agmp.iot.common.constant.IotEnumOnlineStatus;
+import com.yunfeiyun.agmp.iot.common.constant.devicetype.IotDeviceDictConst;
+import com.yunfeiyun.agmp.iot.common.constant.devicetype.ServiceNameConst;
+import com.yunfeiyun.agmp.iot.common.domain.IotDevice;
+import com.yunfeiyun.agmp.iot.common.domain.IotMonitorCapture;
+import com.yunfeiyun.agmp.iot.common.domain.reqvo.IotMonitorPtzConstant;
+import com.yunfeiyun.agmp.iot.common.model.cmd.CmdGroupModel;
+import com.yunfeiyun.agmp.iot.common.model.cmd.CmdModel;
+import com.yunfeiyun.agmp.iot.common.service.MongoService;
+import com.yunfeiyun.agmp.iots.core.http.YunRuiMonitorClient;
+import com.yunfeiyun.agmp.iots.core.manager.HttpManager;
+import com.yunfeiyun.agmp.iots.device.common.HttpDeviceAbstractImpl;
+import com.yunfeiyun.agmp.iots.device.common.dh.DaHuaYunRuiApi;
+import com.yunfeiyun.agmp.iots.device.service.IYunRuiDevice;
+import com.yunfeiyun.agmp.iots.service.IIotCmdlogService;
+import com.yunfeiyun.agmp.iots.service.IIotDeviceService;
+import com.yunfeiyun.agmp.iots.service.IIotDeviceconfigService;
+import com.yunfeiyun.agmp.iots.service.IIotFirmdevService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.HttpStatus;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.lang.reflect.Method;
+import java.math.BigDecimal;
+import java.util.*;
+import java.util.concurrent.CompletableFuture;
+import java.util.stream.Collectors;
+
+/**
+ * @author zhangn
+ */
+@Service(ServiceNameConst.SERVICE_YUN_RUI_MINITOR)
+@Slf4j
+public class YunRuiMonitorService extends HttpDeviceAbstractImpl implements IYunRuiDevice {
+
+    @Resource
+    private IIotCmdlogService iotCmdlogService;
+    @Resource
+    private ResManager resManager;
+    @Resource
+    private IIotDeviceService iotDeviceService;
+    @Resource
+    private IIotDeviceconfigService iotDeviceconfigService;
+    @Resource
+    private IIotFirmdevService iotFirmdevService;
+    @Resource
+    private MongoService<IotMonitorCapture> mongoService;
+    @Resource
+    private RedisCacheManager redisCacheManager;
+    @Resource
+    private HttpManager httpManager;
+
+    private final String HTTP_STATUS_OK = "0";
+
+    @Override
+    public Object sendCmd(CmdModel cmdModel) throws Exception {
+        log.info("【云睿监控】发送指令完毕!");
+        // 获取执行的指令
+        CmdModel.Cmd cmdDistribution = cmdModel.getCmdDistribution();
+        // 获取执行的方法 ,方法可以通过反射获取执行,也可以临时case 匹配
+        String methodName = cmdDistribution.getFunc();
+        Method method = this.getClass().getDeclaredMethod(methodName, JSONObject.class,IotDevice.class);
+        Object result = method.invoke(this, cmdDistribution.getJsons(), cmdModel.getIotDevice());
+        JSONObject resultObject = JSONObject.from(result);
+        cmdModel.setClogDesc(cmdDistribution.getJsons().toJSONString());
+        cmdModel.setClogSendresultContent(result.toString());
+        if (String.valueOf(HttpStatus.OK.value()).equals(resultObject.get("code"))) {
+            cmdModel.setClogSendresult("指令发送成功");
+            iotCmdlogService.insertSuccessCmdlog(cmdModel);
+        } else {
+            cmdModel.setClogSendresult("指令发送失败");
+            iotCmdlogService.insertErrorCmdlog(cmdModel);
+        }
+        return result;
+    }
+
+
+    /**
+     * 拍照
+     *
+     * @param jsonObject {@code {
+     *                   "channelId":"1",
+     *                   "deviceId":"001100",
+     *                   "streamType": 0
+     *                   }}
+     */
+    public JSONObject capture(JSONObject jsonObject,IotDevice iotDevice) {
+        log.info("【{}】【云睿监控】【拍照】参数:{}", LogCore.getSeq(), jsonObject);
+        jsonObject.remove("devBid");
+        JSONObject result = (JSONObject) yunRuiMonitorClient(iotDevice).postExchange(DaHuaYunRuiApi.DMS, jsonObject, JSONObject.class);
+        if (Integer.valueOf("0").equals(result.get("code"))) {
+            JSONObject data = JSONObject.parseObject(result.getString("data"));
+            String url = data.getString("url");
+            IotMonitorCapture iotMonitorCapture = new IotMonitorCapture();
+            iotMonitorCapture.setDevBid(iotDevice.getDevBid());
+            iotMonitorCapture.setPicBid(iotMonitorCapture.getUUId());
+            iotMonitorCapture.setPicCreatedDate(DateUtils.dateTimeNow());
+            iotMonitorCapture.setPicModifieddate(DateUtils.dateTimeNow());
+            iotMonitorCapture.setDevCode(iotDevice.getDevCode());
+            //此处的图片可能还没有返回过来,需要重试获取
+            String saveUrl = resManager.saveMonitorHttpsImg(url, ResConstants.BizType.DAHUA_YUNRUI_MONITOR_CAPTURE, iotDevice.getDevCode() + "/" + System.currentTimeMillis() + "-" + UUID.fastUUID(), "jpg");
+            if (!StringUtils.isEmpty(saveUrl)) {
+                iotMonitorCapture.setPicUrl(saveUrl);
+                iotMonitorCapture.setSaveStatus("1");
+            } else {
+                //任务放到缓存
+                iotMonitorCapture.setTempUrl(url);
+                iotMonitorCapture.setTid(iotDevice.getTid());
+                iotMonitorCapture.setSaveStatus("0");
+                iotMonitorCapture.setRetrySize(1);
+                synRetrySavePic(iotMonitorCapture);
+            }
+            mongoService.saveOne(iotMonitorCapture);
+            log.info("【{}】【云睿监控】【拍照】【响应结果】{}", LogCore.getSeq(), result);
+        }
+        result.put("code", String.valueOf(HttpStatus.OK.value()));
+        return result;
+    }
+
+    /**
+     * 基于队列里面的数据重新拉取图片转存
+     *
+     * @param iotMonitorCapture
+     */
+    public void retrySaveOssPicFromGet(IotMonitorCapture iotMonitorCapture) {
+        //重试次数+1
+        iotMonitorCapture.setRetrySize(iotMonitorCapture.getRetrySize() + 1);
+        String saveUrl = resManager.saveMonitorHttpsImg(iotMonitorCapture.getTempUrl(), ResConstants.BizType.DAHUA_YUNRUI_MONITOR_CAPTURE, iotMonitorCapture.getDevCode() + "/" + System.currentTimeMillis() + "-" + UUID.fastUUID(), "jpg");
+        if (!StringUtils.isEmpty(saveUrl)) {
+            Map param = new HashMap<>();
+            param.put("id", iotMonitorCapture.getPicBid());
+            param.put("saveStatus", "1");
+            param.put("picModifieddate", DateUtils.dateTimeNow());
+            param.put("picUrl", saveUrl);
+            param.put("retrySize", iotMonitorCapture.getRetrySize());
+            //更新数据
+            mongoService.update(IotMonitorCapture.class, param);
+            log.info("【图片转存】【重试】【成功】id:{} ,picUrl:{} ", iotMonitorCapture.getPicBid(), saveUrl);
+        } else {
+            log.info("【图片转存】【重试】【失败】【准备入队列】id:{} ,picUrl:{} ", iotMonitorCapture.getPicBid(), saveUrl);
+            iotMonitorCapture.setPicModifieddate(DateUtils.dateTimeNow());
+            //任务放到缓存
+            synRetrySavePic(iotMonitorCapture);
+            log.info("【图片转存】【重试】【失败】【完成重新入队列】id:{} ,picUrl:{} ", iotMonitorCapture.getPicBid(), saveUrl);
+        }
+    }
+
+
+    public void removeRetrySaveTask(IotMonitorCapture iotMonitorCapture) {
+        mongoService.removeAllByParam("picBid", iotMonitorCapture.getPicBid(), "IotMonitorCapture");
+        redisCacheManager.removeListItemByOne(RedisCacheKey.IOT_DAHUA_RUIYUN_CLOUD_PIC_RETRY_SAVE_TASK, "", iotMonitorCapture);
+    }
+
+    /**
+     * 异步重试转存图片
+     *
+     * @param iotMonitorCapture
+     */
+    private void synRetrySavePic(IotMonitorCapture iotMonitorCapture) {
+        //放到缓存的队列
+        redisCacheManager.rightPushListItem(RedisCacheKey.IOT_DAHUA_RUIYUN_CLOUD_PIC_RETRY_SAVE_TASK, "", iotMonitorCapture);
+    }
+
+    /**
+     * 从队列获取一个
+     *
+     * @return
+     */
+    public IotMonitorCapture getRetryPic() {
+        return redisCacheManager.getListItemLeftPopByOne(RedisCacheKey.IOT_DAHUA_RUIYUN_CLOUD_PIC_RETRY_SAVE_TASK, "");
+    }
+
+    /**
+     * 从队列获取一个
+     *
+     * @return
+     */
+    public Long getRetryTaskSize() {
+        return redisCacheManager.getListSize(RedisCacheKey.IOT_DAHUA_RUIYUN_CLOUD_PIC_RETRY_SAVE_TASK, "");
+    }
+
+    /**
+     * 设备录像查询
+     *
+     * @param jsonObject {@code {
+     *                   "deviceId": "xxxxx",
+     *                   "channelId": "0",
+     *                   "beginTime": "yyyy-MM-dd hh:mm:ss",
+     *                   "endTime": "yyyy-MM-dd hh:mm:ss ",
+     *                   "recordType": "localRecord"
+     *                   }}
+     * @return jsonObject {@code {
+     * "code": "0",
+     * "data": {
+     * "url":'xxxx',
+     * },
+     * "errMsg": "",
+     * "success": true
+     * }}
+     */
+    public JSONObject backView(JSONObject jsonObject,IotDevice iotDevice) {
+        log.info("【{}】【云睿监控】【设备录像查询】参数:{}", LogCore.getSeq(), jsonObject);
+        JSONObject response = (JSONObject) yunRuiMonitorClient(iotDevice).postExchange(DaHuaYunRuiApi.BACK_VIEWS, jsonObject, JSONObject.class);
+        log.info("【{}】【云睿监控】【设备录像查询】【响应结果】{}", LogCore.getSeq(), response);
+        response.put("code", String.valueOf(HttpStatus.OK.value()));
+        return response;
+    }
+
+
+    /**
+     * 获取流地址
+     *
+     * @param jsonObject {@code
+     *                   {
+     *                   "deviceId":"xxxxx",
+     *                   "channelId":"0"
+     *                   }}
+     * @return {@code
+     * {
+     * "deviceId":"xxxxx",
+     * "channelId":"0"
+     * }}
+     */
+    public JSONObject refreshVideoUrl(JSONObject jsonObject,IotDevice iotDevice) {
+        log.info("【{}】【云睿监控】【创建设备拉流地址】参数:{}", LogCore.getSeq(), jsonObject);
+        JSONObject response = (JSONObject) yunRuiMonitorClient(iotDevice).postExchange(DaHuaYunRuiApi.REAL_TIME, jsonObject, JSONObject.class);
+        log.info("【{}】【云睿监控】【创建设备拉流地址】【响应结果】{}", LogCore.getSeq(), response);
+        String streamType = jsonObject.getString("streamType");
+        if (StringUtils.isEmpty(streamType)) {
+            streamType = "1";
+        }
+        JSONObject result = new JSONObject();
+        result.put("code", String.valueOf(HttpStatus.OK.value()));
+        result.put("url", getHlsUrlByStreamId(response, Integer.parseInt(streamType)));
+        return result;
+    }
+
+    /**
+     * @return {@code {
+     * "code":"0",
+     * "data":
+     * "v":"0",
+     * "h":"0",
+     * "z":"0"
+     * }
+     * }
+     * </br>
+     * h:水平位置,范围【-1,1】
+     * </br>
+     * v:垂直位置,范围【-1,1】
+     * </br>
+     * z:变倍参数,范围【0,1】
+     */
+    public JSONObject getPtzStatus(JSONObject jsonObject,IotDevice iotDevice) {
+        log.info("【{}】【云睿监控】【获取设备云台状态】参数:{}", LogCore.getSeq(), jsonObject);
+        JSONObject response = (JSONObject) yunRuiMonitorClient(iotDevice).postExchange(DaHuaYunRuiApi.DEVICE_PTZ_INFO, jsonObject, JSONObject.class);
+        log.info("【{}】【云睿监控】【获取设备云台状态】【响应结果】{}", LogCore.getSeq(), response);
+        if (!HTTP_STATUS_OK.equals(response.get("code"))) {
+            throw new BizException(ErrorCode.INVALID_PARAMETER.getCode(), response.getString("errMsg"));
+        }
+        return response;
+    }
+
+    /**
+     * @param jsonObject {@code {
+     *                   "deviceId":"xxxxx",
+     *                   "channelId":"0",
+     *                   "operateType": 1,
+     *                   "direct": 1,
+     *                   "step": 1,
+     *                   }}
+     */
+    public JSONObject ptz(JSONObject jsonObject,IotDevice iotDevice) {
+        log.info("【{}】【云睿监控】【云台控制】参数:{}", LogCore.getSeq(), jsonObject);
+        String operateType = jsonObject.getString("operateType");
+        Integer step = jsonObject.getInteger("step");
+        String direct = jsonObject.getString("direct");
+        JSONObject ptzStatusParam = new JSONObject();
+        ptzStatusParam.put("deviceId", jsonObject.getString("deviceId"));
+        ptzStatusParam.put("channelId", jsonObject.getString("channelId"));
+        JSONObject ptzStatusResponse = getPtzStatus(ptzStatusParam,iotDevice);
+        JSONObject ptzStatus = ptzStatusResponse.getJSONObject("data");
+        BigDecimal stepValue = new BigDecimal("0.1").multiply(new BigDecimal(step));
+        String value;
+        String key = null;
+        if (IotMonitorPtzConstant.OperationConstant.LENS.equals(operateType)) {
+            key = "z";
+            stepValue = stepValue.multiply(new BigDecimal(direct));
+        } else if (IotMonitorPtzConstant.OperationConstant.MOVE.equals(operateType)) {
+            switch (direct) {
+                case IotMonitorPtzConstant.MoveDirectConstant.UP:
+                    key = "v";
+                    stepValue = stepValue.multiply(new BigDecimal(1));
+                    break;
+                case IotMonitorPtzConstant.MoveDirectConstant.DOWN:
+                    key = "v";
+                    stepValue = stepValue.multiply(new BigDecimal(-1));
+                    break;
+                case IotMonitorPtzConstant.MoveDirectConstant.LEFT:
+                    key = "h";
+                    stepValue = stepValue.multiply(new BigDecimal(1));
+                    break;
+                case IotMonitorPtzConstant.MoveDirectConstant.RIGHT:
+                    key = "h";
+                    stepValue = stepValue.multiply(new BigDecimal(-1));
+                    break;
+            }
+        }
+        value = ptzStatus.getString(key);
+        value = new BigDecimal(value).add(stepValue).toString();
+        ptzStatus.put(key, value);
+        JSONObject response = (JSONObject) yunRuiMonitorClient(iotDevice).postExchange(DaHuaYunRuiApi.PTZ_OPERATE_DIRECT, ptzStatus, JSONObject.class);
+        log.info("【{}】【云睿监控】【云台控制】【响应结果】{}", LogCore.getSeq(), response);
+        // 变倍倍数
+        return response;
+    }
+
+    @Override
+    public void sysAllDevice() {
+        try {
+            log.info("【{}】【云睿监控】【定时检测设备在线状态】【开始】", LogCore.getSeq());
+            List<CompletableFuture<JSONObject>> completableFutureList = new LinkedList<>();
+            // 此处若后续数据较多时,可按租户分批处理
+            List<String> devTypeBidList = Collections.singletonList(IotDeviceDictConst.TYPE_DAHUA_YUNRUI_DEVICE);
+            List<IotDevice> iotDeviceList = iotDeviceService.selectIotDeviceByDevtypeBidList(devTypeBidList);
+            Map<String,List<IotDevice>> map = iotDeviceList.stream().collect(Collectors.groupingBy(item->item.getDevCode().split("-")[0]));
+            for(Map.Entry<String,List<IotDevice>> entry:map.entrySet()){
+                CompletableFuture<JSONObject> generateGraphics = CompletableFuture.supplyAsync(() -> {
+                    try {
+                        IotDevice iotDevice = new IotDevice();
+                        iotDevice.setDevCode(entry.getKey());
+                        iotDevice.setDevtypeBid(entry.getValue().get(0).getDevtypeBid());
+                        iotDevice.setDevconnBid(entry.getValue().get(0).getDevconnBid());
+                        return this.refreshStatus(iotDevice,entry.getValue());
+                    } catch (Exception e) {
+                        throw new RuntimeException(e);
+                    }
+                });
+                completableFutureList.add(generateGraphics);
+            }
+            CompletableFuture<Void> allFutures = CompletableFuture.allOf(completableFutureList.toArray(new CompletableFuture[0]));
+            allFutures.get();
+            log.info("【{}】【云睿监控】【定时检测设备在线状态】【结束】", LogCore.getSeq());
+        }catch (Exception e){
+            log.error("【{}】【云睿监控】【定时检测设备在线状态】【异常】", LogCore.getSeq(),e);
+        }
+
+    }
+
+    private JSONObject refreshStatus(IotDevice iotDevice,List<IotDevice> childDeviceList) {
+        JSONObject param = new JSONObject();
+        param.put("deviceId", iotDevice.getDevCode());
+        log.info("【{}】【云睿监控】【检测设备状态】参数:{}", LogCore.getSeq(), param);
+        JSONObject response = (JSONObject) yunRuiMonitorClient(iotDevice).postExchange(DaHuaYunRuiApi.GET_DEVICE_INFO, param, JSONObject.class);
+        log.info("【{}】【云睿监控】【获取设备云台状态】【响应结果】{}", LogCore.getSeq(), response);
+        if (!HTTP_STATUS_OK.equals(response.get("code"))) {
+            throw new BizException(ErrorCode.INVALID_PARAMETER.getCode(), response.getString("errMsg"));
+        }
+        JSONObject resultData = response.getJSONObject("data");
+        JSONArray resultDataChannels = resultData.getJSONArray("channelList");
+        Map<String,String> onlineStatusMap = new HashMap<>();
+        String deviceId = resultData.getString("deviceId");
+        if(null != resultDataChannels){
+            for(Object resultDataChannelsItem : resultDataChannels){
+                JSONObject channelsItem = JSONObject.from(resultDataChannelsItem);
+                String status = channelsItem.getString("onlineStatus");
+                String channelId = channelsItem.getString("channelId");
+                onlineStatusMap.put(deviceId+"-"+channelId,status);
+            }
+        }
+        for(IotDevice childDevice : childDeviceList){
+            String status = onlineStatusMap.get(childDevice.getDevCode());
+            if(null != status){
+                log.info("【{}】【云睿监控】【获取设备云台状态】设备编号:{},设备状态:{}", LogCore.getSeq() ,childDevice.getDevCode() , IotEnumOnlineStatus.messageOfCode(childDevice.getDevStatus()));
+                childDevice.setDevStatus(status);
+            }else {
+                log.info("【{}】【云睿监控】【获取设备云台状态】设备编号:{},未查询到设备状态信息,视为设备离线", LogCore.getSeq() ,childDevice.getDevCode());
+                childDevice.setDevStatus(IotEnumOnlineStatus.OFFLINE.getStatus());
+            }
+            iotDeviceService.updateIotDeviceBatch(childDeviceList);
+        }
+        return response;
+    }
+
+
+    public String getHlsUrlByStreamId(JSONObject jsonObject, int targetStreamId) {
+        JSONArray streams = jsonObject.getJSONObject("data").getJSONArray("streams");
+        for (int i = 0; i < streams.size(); i++) {
+            JSONObject stream = streams.getJSONObject(i);
+            if (stream.getIntValue("streamId") == targetStreamId) {
+                return stream.getString("hls");
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public boolean isDeviceProps(JSONObject cmdJson) {
+        return false;
+    }
+
+    private YunRuiMonitorClient yunRuiMonitorClient(IotDevice iotDevice){
+        return (YunRuiMonitorClient) httpManager.getHttpClientByDevice(iotDevice);
+    }
+}

+ 0 - 28
src/main/java/com/yunfeiyun/agmp/iots/device/task/HikMonitorStatusScheduler.java

@@ -1,28 +0,0 @@
-package com.yunfeiyun.agmp.iots.device.task;
-
-import com.yunfeiyun.agmp.iots.device.service.IHikVisionEzvizDevice;
-import com.yunfeiyun.agmp.iots.service.IIotDeviceService;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.scheduling.annotation.Scheduled;
-import org.springframework.stereotype.Component;
-
-import javax.annotation.Resource;
-
-/**
- * 海康萤石云监控设备检测设备在线状态
- * */
-@Slf4j
-@Component
-public class HikMonitorStatusScheduler {
-
-    @Resource
-    private IHikVisionEzvizDevice hikVisionDevice;
-    @Resource
-    private IIotDeviceService iotDeviceService;
-
-    @Scheduled(cron = "0 0 * * * ?")
-    public void selectMonitorStatusByAll() {
-        hikVisionDevice.sysAllDevice();
-    }
-
-}

+ 46 - 0
src/main/java/com/yunfeiyun/agmp/iots/device/task/MonitorStatusScheduler.java

@@ -0,0 +1,46 @@
+package com.yunfeiyun.agmp.iots.device.task;
+
+import com.yunfeiyun.agmp.iots.core.manager.ConnectionManager;
+import com.yunfeiyun.agmp.iots.device.service.IHikVisionEzvizDevice;
+import com.yunfeiyun.agmp.iots.device.service.IYunRuiDevice;
+import com.yunfeiyun.agmp.iots.service.IIotDeviceService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+
+/**
+ * 海康萤石云监控设备检测设备在线状态
+ * */
+@Slf4j
+@Component
+public class MonitorStatusScheduler {
+
+    @Resource
+    private IHikVisionEzvizDevice hikVisionDevice;
+    @Resource
+    private IIotDeviceService iotDeviceService;
+    @Resource
+    private IYunRuiDevice yunRuiDevice;
+    @Resource
+    private ConnectionManager connectionManager;
+
+    @Scheduled(cron = "0 0 * * * ?")
+    public void selectHikMonitorStatusByAll() {
+        if(!connectionManager.initCompleted()){
+            return;
+        }
+        hikVisionDevice.sysAllDevice();
+    }
+
+    @Scheduled(cron = "0/15 * * * * ?")
+    public void selectDaHuaYunRuiMonitorStatusByAll() {
+        if(!connectionManager.initCompleted()){
+            return;
+        }
+        yunRuiDevice.sysAllDevice();
+    }
+
+}