Newer
Older
huludao / src / main / java / com / newfiber / api / pc / camera / service / CameraService.java
package com.newfiber.api.pc.camera.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.newfiber.api.core.commons.CustomException;
import com.newfiber.api.pc.camera.dto.Result;
import com.newfiber.api.pc.camera.dto.Stream;
import com.newfiber.api.pc.camera.util.CONST;
import com.newfiber.api.pc.camera.util.HttpSend;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;

/**
 * @program: OpenJavaDemo
 * @description: 登录接口
 * @author: djt
 * @create: 2020-12-10 14:51
 **/
@Slf4j
@Service
public class CameraService {
    @Autowired
    private HttpSend httpSend;

    /**
     * 请i去
     *
     * @param paramsMap
     * @param methodUrl
     * @param token
     * @return java.lang.String
     * @author djt
     * @creed: Talk is cheap,show me the code
     * @date 2020/12/12 8:45
     * @description: ${description}
     */
    private String rpc(Map<String, Object> paramsMap, String methodUrl, String token) {
        String url = String.format(CONST.URL, methodUrl);
        Map<String, Object> map = httpSend.buildSystemParams();
        paramsMap.put("token", token);
        map.put("params", paramsMap);
        Optional<String> optional = httpSend.doPost(url, map);
        return optional.orElseThrow(() -> new RuntimeException("通讯失败,返回数据为空"));
    }

    /**
     * 请求
     *
     * @param paramsMap
     * @param methodUrl
     * @return java.lang.String
     * @author djt
     * @creed: Talk is cheap,show me the code
     * @date 2020/12/12 8:46
     * @description: ${description}
     */
    public String rpc(Map<String, Object> paramsMap, String methodUrl) {
     //   checkToken();
        String rpcString = rpc(paramsMap, methodUrl, CONST.token);
        JSONObject result = JSONObject.parseObject(rpcString).getJSONObject("result");
        if (StringUtils.equalsIgnoreCase(result.getString("code"), "TK1002")) {
            doLogin(0);
            return rpc(paramsMap, methodUrl, CONST.token);
        }
        return rpcString;
    }

    /**
     * 检查tooken是否存在  。。可改成redis? todo
     *
     * @param
     * @return void
     * @author djt
     * @creed: Talk is cheap,show me the code
     * @date 2020/12/12 8:44
     * @description: ${description}
     */
    private void checkToken() {
        doLogin(0);
    }

    /**
     * 登录,请求得到token
     *
     * @param retry 重试次数
     * @return void
     * @author djt
     * @creed: Talk is cheap,show me the code
     * @date 2020/12/12 8:45
     * @description: ${description}
     */
    private void doLogin(int retry) {
        if (retry >= 3) {
            throw new CustomException(500,"登录失败,超过登录最大重试次数,停止重试");
        }
        String json = rpc(Maps.newHashMap(), CONST.ACCESSTOKEN_V2, null);
        if (!loginParse(json)) {
            retry++;
            doLogin(retry);
        }
    }

    /**
     * 解析登录
     *
     * @param jsonObject
     * @return boolean
     * "expireTime":259176,
     * "accessToken":"At_00006ac6e32d123141238f60147de7ec"
     * @author djt
     * @creed: Talk is cheap,show me the code
     * @date 2020/12/11 13:45
     * @description: ${description}
     */
    private boolean loginParse(String jsonObject) {
        JSONObject result = JSONObject.parseObject(jsonObject).getJSONObject("result");
        if (StringUtils.equalsIgnoreCase(result.getString("code"), "0")) {
            CONST.token = result.getJSONObject("data").getString("accessToken");
            return true;
        }
        return false;
    }

    /**
     * 检查设备是否创建过直播,若创建过。。直接返回播放地址,若没有,则去创建播放。。在返回地址
     *
     * @param
     * @return boolean
     * @author djt
     * @creed: Talk is cheap,show me the code
     * @date 2020/12/11 14:31
     * @description: ${description}
     */
    public String checkCameraPlaying(String deviceId,String channelId) {
        Map<String, Object> map = Maps.newHashMap();
        map.put("deviceId", deviceId);
        map.put("channelId", channelId);
        map.put("streamId",1);

        String json = rpc(map, CONST.GETLIVESTREAMINFO_V2);
        //String json = rpc(map, CONST.BINDDEVICELIVE_V2);
        Optional<String> url = parseDeviceUrl(json);
        return url.orElseGet(() -> play(deviceId,channelId));
    }

    /**
     * 根据deviceid播放 创建直播
     *
     * @param deviceId
     * @return java.lang.String
     * @author djt
     * @creed: Talk is cheap,show me the code
     * @date 2020/12/12 8:43
     * @description: ${description}
     */
    private String play(String deviceId,String channelId) {
        Map<String, Object> map = Maps.newHashMap();
        map.put("streamId", 1);
        map.put("deviceId", deviceId);
        map.put("channelId", channelId);
        String json = rpc(map, CONST.BINDDEVICELIVE_V2);
        return playParse(json);
    }

    /**
     * 根据设备id,获取直播地址
     *
     * @param json
     * @return java.lang.String
     * @author djt
     * @creed: Talk is cheap,show me the code
     * @date 2020/12/11 16:57
     * @description: ${description}
     */
    private Optional<String> parseDeviceUrl(String json) {
        Result<JSONObject> result = JSONObject.parseObject(json).getObject("result", Result.class);
        //若没有则返回null
        if (StringUtils.equalsIgnoreCase("LV1002", result.getCode())) {

            return Optional.empty();
        }
        //若是其他状态码。。直接返回前端
        if (!StringUtils.equalsIgnoreCase("0", result.getCode())) {
            throw new CustomException(500,result.getMsg());
        }
        //返回直播地址
        JSONArray jsonArray = result.getData().getJSONArray("streams");
        if (ObjectUtil.isNotNull(jsonArray)&&jsonArray.size()>1) {
            Stream stream = jsonArray.getObject(0, Stream.class);
            return Optional.of(stream.getHls());
        }
        return Optional.empty();
    }

    /**
     * 解析添加直播的回复,添加错误,抛出异常。添加成功返回直播地址(入口为检查视频是否播放中)
     *
     * @param jsonObject
     * @return void
     * @author djt
     * @creed: Talk is cheap,show me the code
     * @date 2020/12/11 17:24
     * @description: ${description}
     */
    private String playParse(String jsonObject) {
        Result<JSONObject> result = JSONObject.parseObject(jsonObject).getObject("result", Result.class);
        if (StringUtils.equalsIgnoreCase(result.getCode(), "0")) {
            return result.getData().getJSONArray("streams").getJSONObject(0).getString("hls");
//            Stream stream = (Stream) result.getData().getJSONArray("streams").get(0);
//            return stream.getHls();
        }
        throw new CustomException(500,result.getMsg());
    }

    /**
     * 只需要,知道是否成功
     *
     * @param json
     * @return boolean
     * @author djt
     * @creed: Talk is cheap,show me the code
     * @date 2020/12/11 17:54
     * @description: ${description}
     */
    private boolean parseJson(String json) {
        Result<JSONObject> result = JSONObject.parseObject(json).getObject("result", Result.class);
        if (StringUtils.equalsIgnoreCase(result.getCode(), "0")) {
            return true;
        }
        throw new CustomException(500,result.getMsg());
    }

//    public static void main(String[] args) {
//        CameraService service = new CameraService();
//        service.checkCameraPlaying("6F00BA1PAZ57D9C");
//        service.ptz("6F00BA1PAZ57D9C", "1");
//        Map<String, Object> map = new HashMap<String, Object>(5);
//        map.put("limit", "128");
//        map.put("type", "bind");
//        map.put("bindId", "-1");
//        map.put("needApInfo", "true");
//        service.rpc(map, CONST.DEVICEOPENLIST_V2, token);
//        service.checkCameraPlaying("6F00BA1PAZ57D9C");
//        service.play("6F00BA1PAZ57D9C");
//        map.put("streamId", 1);
//        map.put("deviceId", "6F00BA1PAZ57D9C");
//        map.put("channelId", "0");
//        service.rpc(map,CONST.PLAY_V2,token);
//        service.doPlay(map);
//        map.put("type","All");
//        map.put("queryRange","1-10");
//        map.put("beginTime","2020-05-19 00:00:00");
//        map.put("endTime","2020-12-11 23:59:59");
//        map.put("channelId","0");
//        map.put("deviceId","6F00BA1PAZ57D9C");
//        service.rpc(map,CONST.QUERYLOCALRECORDS_V2,token);
//        map.put("deviceId", "6F00BA1PAZ57D9C");
//        map.put("channelId", "0");
//        //	0-上,1-下,2-左,3-右,4-左上,5-左下,6-右上,7-右下,8-放大,9-缩小,10-停止
//        map.put("operation", "0");
//        map.put("duration", "1000");
//        service.rpc(map, CONST.CONTROLMOVEPTZ_V2, token);
//    }

    /**
     * 云台控制,
     *
     * @param deviceId 设备id,设备唯一标识,并不是自己生成的id,而是
     * @param instruct 云台控制指令
     * @return boolean
     * @author djt
     * @creed: Talk is cheap,show me the code
     * @date 2020/12/12 8:42
     * @description: ${description}
     */
    public boolean ptz(String deviceId, String instruct,String channelId) {
        if (INSTRUCTS.contains(instruct)) {
            Map<String, Object> map = Maps.newHashMap();
            map.put("deviceId", deviceId);
            map.put("channelId", channelId);
            //	0-上,1-下,2-左,3-右,4-左上,5-左下,6-右上,7-右下,8-放大,9-缩小,10-停止
            map.put("operation", instruct);
            map.put("duration", "1000");
            String json = rpc(map, CONST.CONTROLMOVEPTZ_V2);
            return parseJson(json);
        }
        throw new CustomException(500,"其他未知指令,请输入正确指令");
    }

    /**
     * 根据设备的序列号。。查询设备的信息
     *
     * @param deviceIds 查询设备的集合
     * @return java.lang.String
     * @author djt
     * @creed: Talk is cheap,show me the code
     * @date 2020/12/12 11:07
     * @description: ${description}  最多8个设备
     */
    public String list(List<String> deviceIds) {
        if (CollUtil.isEmpty(deviceIds)) {
            throw new CustomException(500,"查询参数不能为空");
        }
        Map<String, Object> map = Maps.newHashMap();
        List<Map<String, Object>> json = Lists.newArrayList();
        deviceIds.forEach(i -> {
            json.add(ImmutableMap.of("deviceId", i));
        });
        map.put("deviceList", json);
        rpc(map, CONST.DEVICE_OPENDETAIL_LIST_V2);
        return null;
    }

    /**
     * 绑定设备
     *
     * @param deviceId 设备序列号
     * @param code  设备验证码 admin123
     * @return void
     * @author djt
     * @creed: Talk is cheap,show me the code
     * @date 2020/12/12 11:13
     * @description: ${description}
     */
    public boolean bindDevice(String deviceId, String code) {
        Map<String, Object> map = Maps.newHashMap();
        map.put("deviceId", deviceId);
        map.put("code", code);
        String json = rpc(map, CONST.BIND_DEVICE_V2);
        return parseJson(json);
    }

    /**
     * 解绑设备
     *
     * @param deviceId 设备序列号
     * @return boolean
     * @author djt
     * @creed: Talk is cheap,show me the code
     * @date 2020/12/12 11:12
     * @description: ${description}
     */
    public boolean unBindDevice(String deviceId) {
        Map<String, Object> map = Maps.newHashMap();
        map.put("deviceId", deviceId);
        String json = rpc(map, CONST.UNBINDDEVICE_V2);
        return parseJson(json);
    }

    public Result<JSONObject> selectDeviceBindByDeviceCode(String deviceCode){
        Map<String, Object> map = Maps.newHashMap();
        map.put("deviceId", deviceCode);
        String json = rpc(map, CONST.CHECKDEVICEBINDORNOT_V2);
        return JSONObject.parseObject(json).getObject("result", Result.class);
    }
    /**
     * 
     * @param deviceCode  设备序列号
     * @return boolean
     * @author djt
     * @creed: Talk is cheap,show me the code
     * @date 2020/12/15 9:43
     * @description: ${description}
     */
    public boolean selectCameraStatus(String deviceCode) {
        Map<String, Object> map = Maps.newHashMap();
        map.put("deviceId", deviceCode);
        try{
            String json = rpc(map, CONST.DEVICEONLINE_V2);
            Result<JSONObject> result = JSONObject.parseObject(json).getObject("result", Result.class);
            if (StringUtils.equalsIgnoreCase(result.getCode(), "0")) {
                String status = result.getData().getString("onLine");
                return StringUtils.equalsIgnoreCase("1", status);
            }
        }catch (Exception e){
            log.error("同步摄像头的在线状态错误,错误信息:{},摄像头信息:{}",e.getLocalizedMessage(),deviceCode);
            return false;
        }
        return false;
    }

    private static final Set<String> INSTRUCTS = Sets.newHashSet("0","1", "2", "3", "4", "5", "6", "7", "8", "9", "10");
}