package com.sandu.ximon.admin.service; import cn.hutool.http.HttpUtil; import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.sandu.common.domain.CommonPage; import com.sandu.common.execption.BusinessException; import com.sandu.common.object.BaseConditionVO; import com.sandu.common.service.impl.BaseServiceImpl; import com.sandu.common.util.SpringContextHolder; import com.sandu.ximon.admin.dto.YSY_AccessTokenDto; import com.sandu.ximon.admin.dto.YSY_MonitorDto; import com.sandu.ximon.admin.param.MonitorParam; import com.sandu.ximon.admin.redis.DeviceRedisKey; import com.sandu.ximon.admin.security.SecurityUtils; import com.sandu.ximon.admin.utils.ListPagingUtils; import com.sandu.ximon.admin.utils.RedisUtils; import com.sandu.ximon.admin.utils.StoreOperationRecordsUtils; import com.sandu.ximon.admin.vo.EquipmentInfomation; import com.sandu.ximon.admin.vo.RedisDeviceStatus; import com.sandu.ximon.dao.bo.MonitorBo; import com.sandu.ximon.dao.domain.Monitor; import com.sandu.ximon.dao.domain.PoleBinding; import com.sandu.ximon.dao.enums.OrderByEnums; import com.sandu.ximon.dao.enums.PoleBindingEnums; import com.sandu.ximon.dao.mapper.MonitorMapper; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.CountDownLatch; @Service @AllArgsConstructor @Slf4j public class MonitorService extends BaseServiceImpl { private final MonitorMapper monitorMapper; //萤石云AppKey private static final String AppKey = "51a534ebadf54c31a0848dc575dfa206"; //萤石云 AppKey Secret private static final String Secret = "8c32c67a73c87b9e461b2e3bdf58967a"; //萤石云地址 private static final String YSY_URL = "https://open.ys7.com/api/lapp"; //获取萤石云accessToken地址 private static final String ACCESSTOKEN_URL = "/token/get"; //添加萤石云摄像头 private static final String ADD_DEVICE_URL = "/device/add"; //删除萤石云摄像头 private static final String DELETE_DEVICE_URL = "/device/delete"; //获取萤石云单个设备信息 private static final String GET_DEVICE_URL = "/device/info"; //获取萤石云摄像头播放地址URL private static final String GET_VEDIO_URL = "/v2/live/address/get"; private final PoleBindingService poleBindingService; private final RedisUtils redisUtils; /** * 摄像头列表模糊查询 */ public CommonPage listMonitorByKeyword(BaseConditionVO baseConditionVO, Integer order, Integer seq, MonitorParam monitorParam) { //绑定状态:已绑定/未绑定/全部 if (monitorParam.getBindingState() == null) { //全部 monitorParam.setBindingState(2); } //排序字段 String orderByResult = "id"; //正序、倒叙 String orderBySeq = OrderByEnums.ASC.getCode(); if (order != null) { switch (order) { case 1: orderByResult = OrderByEnums.MONITOR_POLE_NAME.getCode(); break; case 2: orderByResult = OrderByEnums.MONITOR_CREATE_TIME.getCode(); break; default: } } if (seq != null) { switch (seq) { case 1: orderBySeq = " ASC"; break; case 2: orderBySeq = " DESC"; break; default: break; } } //排序方式 String orderBy = orderByResult + " " + orderBySeq; List list; if (SecurityUtils.getClientId() == null) { list = monitorMapper.listMonitorDeviceSerial1(null, monitorParam.getKeyword(), monitorParam.getBindingState(), orderBy); } else { list = monitorMapper.listMonitorDeviceSerial1(SecurityUtils.getUserId(), monitorParam.getKeyword(), monitorParam.getBindingState(), orderBy); } //没有数据时候直接返回空数组 if (list.size() == 0 || list == null) { return new CommonPage(); } List device_serialList = new ArrayList<>(list.size()); CountDownLatch latch = new CountDownLatch(list.size()); for (Monitor demo : list) { device_serialList.add(demo.getDeviceSerial()); getMonitorInfo_Async(demo, latch); } try { latch.await(); } catch (InterruptedException e) { e.printStackTrace(); } if (monitorParam.getEquipmentState() == null) { //全部 monitorParam.setEquipmentState(2); } List temp = new ArrayList<>(); if (monitorParam.getEquipmentState() == 2) { temp.addAll(list); } else { for (MonitorBo monitorBo : list) { //筛选状态数据 if (monitorBo.getEquipmentState().equals(monitorParam.getEquipmentState())) { temp.add(monitorBo); } } } if (baseConditionVO == null) { baseConditionVO = new BaseConditionVO(); baseConditionVO.setPageSize(null); baseConditionVO.setPageNo(null); } CommonPage commonPage = ListPagingUtils.pages(temp, baseConditionVO.getPageNo(), baseConditionVO.getPageSize()); return commonPage; } /** * 摄像头列表地(用于首页数据统计) * * @return */ public List listMonitorOnHome() { List list; if (SecurityUtils.getClientId() == null) { list = monitorMapper.listMonitorDeviceSerial1(null, null, 2, null); } else { list = monitorMapper.listMonitorDeviceSerial1(SecurityUtils.getUserId(), null, 2, null); } //没有数据时候直接返回空数组 if (list == null) { return new ArrayList<>(); } return list; } /** * 删除摄像头 * * @param Id * @return */ public boolean deleteMonitor(Long Id) { Monitor monitor = getById(Id); if (monitor == null) { throw new BusinessException("找不到摄像头"); } PoleBinding one = poleBindingService.getOne(Wrappers.lambdaQuery(PoleBinding.class).eq(PoleBinding::getDeviceCode, monitor.getDeviceSerial())); if (one != null) { //删除摄像头设备前需要先解绑 poleBindingService.unBindPole(null, monitor.getDeviceSerial()); } /** * 删除摄像头日志记录开始 */ String content = "{摄像头Code:" + monitor.getDeviceSerial() + ", 摄像头名称:" + monitor.getDeviceName() + " }"; List listCode = new ArrayList<>(); listCode.add(monitor.getDeviceSerial()); StoreOperationRecordsUtils.storeOperationData(listCode, null, "删除摄像头", content); /** * 删除摄像头日志记录结束 */ return removeById(Id); } /** * 获取萤石云accessToken */ public String getAccessToken() { Map paramMap = new HashMap<>(); paramMap.put("appKey", AppKey); paramMap.put("appSecret", Secret); String s = HttpUtil.post(YSY_URL + ACCESSTOKEN_URL, paramMap); if (!s.startsWith("{") || !s.endsWith("}")) { log.error("获取摄像头token失败,格式有误!"); } YSY_AccessTokenDto accessTokenDto = JSON.parseObject(s, YSY_AccessTokenDto.class); //二次获取 if(accessTokenDto == null){ log.error("获取摄像头token失败,格式有误!"); s = HttpUtil.post(YSY_URL + ACCESSTOKEN_URL, paramMap); accessTokenDto = JSON.parseObject(s, YSY_AccessTokenDto.class); } return accessTokenDto.getData().getAccessToken(); } /** * 获取萤石云摄像头信息(异步) * * @return */ public void getMonitorInfo_Async(Monitor monitor, CountDownLatch countDownLatch) { Thread t = new Thread() { @Override public void run() { String token = getAccessToken(); Map paramMap = new HashMap<>(); paramMap.put("accessToken", token); paramMap.put("deviceSerial", monitor.getDeviceSerial()); String s = HttpUtil.post(YSY_URL + GET_DEVICE_URL, paramMap); YSY_MonitorDto monitorDto = null; try { monitorDto = JSON.parseObject(s, YSY_MonitorDto.class); System.out.println(s + " ----------"); monitor.setEquipmentState(monitorDto.getData().getStatus()); countDownLatch.countDown(); } catch (Exception e) { monitor.setEquipmentState(0); countDownLatch.countDown(); } } }; t.start(); } /** * 获取萤石云摄像头信息 无需验证accessToken * * @return */ public EquipmentInfomation getMonitorInfo(String deviceSerial) { EquipmentInfomation equipmentInfo = new EquipmentInfomation(); equipmentInfo.setEquipmentType("摄像头"); if (deviceSerial == null || deviceSerial.trim().length() == 0) { return equipmentInfo; } Monitor one = getOne(Wrappers.lambdaQuery(Monitor.class).eq(Monitor::getDeviceSerial, deviceSerial)); if (one != null) { equipmentInfo.setEquipmentCreateTime(one.getAddTime()); equipmentInfo.setEquipmentMac(one.getDeviceSerial()); equipmentInfo.setEquipmentName(one.getDeviceName()); } String token = getAccessToken(); Map paramMap = new HashMap<>(); paramMap.put("accessToken", token); paramMap.put("deviceSerial", deviceSerial); String s = HttpUtil.post(YSY_URL + GET_DEVICE_URL, paramMap); try { YSY_MonitorDto monitorDto = JSON.parseObject(s, YSY_MonitorDto.class); if (monitorDto != null) { //在线状态:0-不在线,1-在线 if (monitorDto.getData().getStatus() == 1) { equipmentInfo.setEquipmentState("在线"); } else { equipmentInfo.setEquipmentState("离线"); } } } catch (Exception e) { e.printStackTrace(); } return equipmentInfo; } /** * 添加萤石云摄像头 * * @param deviceSerial 设备序列号,存在英文字母的设备序列号,字母需为大写 * // * @param validateCode 设备验证码,设备机身上的六位大写字母 */ public boolean addYSYMonitor(String deviceSerial, String validateCode) { List list = list(Wrappers.lambdaQuery(Monitor.class).eq(Monitor::getDeviceSerial, deviceSerial)); if (list.size() != 0) { throw new BusinessException("该摄像头已存在,无法重复添加!"); } Map paramMap = new HashMap<>(); paramMap.put("accessToken", getAccessToken()); paramMap.put("deviceSerial", deviceSerial); if (validateCode != null && validateCode.trim().length() != 0) { paramMap.put("validateCode", validateCode); } String s = HttpUtil.post(YSY_URL + ADD_DEVICE_URL, paramMap); if (!s.startsWith("{") && !s.endsWith("}")) { throw new BusinessException("萤石云数据异常"); } YSY_MonitorDto monitorDto = JSON.parseObject(s, YSY_MonitorDto.class); boolean result; if ("20017".equals(monitorDto.getCode())) { //当前摄像头已经被萤石云官网添加过,Code:20017 monitorDto = getYSYMonitorInfo(getAccessToken(), deviceSerial); } else if (!"200".equals(monitorDto.getCode())) { //当前摄像头成功被萤石云官网添加,Code:200 throw new BusinessException(monitorDto.getMsg()); } if (monitorDto.getData() == null) { throw new BusinessException("萤石云数据异常!"); } Monitor monitor = new Monitor(); monitor.setDeviceSerial(monitorDto.getData().getDeviceSerial()); monitor.setDevicesCode(validateCode); monitor.setDeviceName(monitorDto.getData().getDeviceName()); monitor.setEquipmentState(monitorDto.getData().getStatus()); monitor.setIsEncrypt(monitorDto.getData().getIsEncrypt()); monitor.setDeviceType(monitorDto.getData().getModel()); monitor.setNetAddress(monitorDto.getData().getNetAddress()); result = addMonitorInfoToTable(monitor); /** * 新增摄像头开始 */ String content = "{摄像头Code:" + monitor.getDeviceSerial() + ", 摄像头名称:" + monitor.getDeviceName() + " }"; List listCode = new ArrayList<>(); listCode.add(monitor.getDeviceSerial()); StoreOperationRecordsUtils.storeOperationData(listCode, null, "新增摄像头", content); /** * 新增摄像头结束 */ return result; } /** * 获取萤石云摄像头单个设备信息 * * @param accessToken 授权过程获取的access_token * @param deviceSerial 设备序列号,存在英文字母的设备序列号,字母需为大写 */ public YSY_MonitorDto getYSYMonitorInfo(String accessToken, String deviceSerial) { Map paramMap = new HashMap<>(); paramMap.put("accessToken", accessToken); paramMap.put("deviceSerial", deviceSerial); String s = HttpUtil.post(YSY_URL + GET_DEVICE_URL, paramMap); System.out.println(s); YSY_MonitorDto monitor = JSON.parseObject(s, YSY_MonitorDto.class); return monitor; } /** * 将摄像头设备相关信息存储到数据库 * * @param monitor 摄像头对象 * @return */ public boolean addMonitorInfoToTable(Monitor monitor) { Monitor one = getOne(Wrappers.lambdaQuery(Monitor.class).eq(Monitor::getDeviceSerial, monitor.getDeviceSerial())); if (one == null) { return save(monitor); } else { monitor.setId(one.getId()); return updateById(monitor); } } /** * 返回摄像头实时画面播放地址 * * @param accessToken * @param deviceSerial * @return */ public String getMonitorVideoUrl(String accessToken, String deviceSerial, int protocol, int expireTime) { if (expireTime < 30 || expireTime > 62208000) { throw new BusinessException("设置的URL播放地址过期时长数据错误"); } Map paramMap = new HashMap<>(); paramMap.put("accessToken", accessToken); paramMap.put("deviceSerial", deviceSerial); paramMap.put("protocol", protocol); paramMap.put("expireTime", expireTime); String s = HttpUtil.post(YSY_URL + GET_VEDIO_URL, paramMap); System.out.println(s); YSY_MonitorDto monitor = JSON.parseObject(s, YSY_MonitorDto.class); if ("200".equals(monitor.getCode())) { return monitor.getData().getUrl(); } else { throw new BusinessException(monitor.getMsg()); } } /** * 修改设备绑定状态 * * @param flag true为绑定 false 为解绑 */ public void updateBingdingState(boolean flag, String deviceCode) { if (flag) {//绑定 Monitor monitor = getOne(Wrappers.lambdaQuery(Monitor.class).eq(Monitor::getDeviceSerial, deviceCode)); if (monitor == null) { return; } monitor.setBindingState(1); updateById(monitor); } else {//解绑 Monitor monitor = getOne(Wrappers.lambdaQuery(Monitor.class).eq(Monitor::getDeviceSerial, deviceCode)); if (monitor == null) { return; } monitor.setBindingState(0); updateById(monitor); } } /** * 修改note * * @param deviceSerial * @param notes * @return */ public boolean updateNotes(String deviceSerial, String notes) { if (deviceSerial == null || deviceSerial.trim().length() == 0 || notes == null) { throw new BusinessException("修改备注参数有误!"); } Monitor one = getOne(Wrappers.lambdaQuery(Monitor.class).eq(Monitor::getDeviceSerial, deviceSerial)); boolean belong = SpringContextHolder.getBean(PoleBindingService.class).isBelong(one.getDeviceSerial(), PoleBindingEnums.MONITOR); if (!belong) { throw new BusinessException("该设备不属于您,不能修改设备信息"); } if (one != null) { one.setNote(notes); /** * 添加摄像头备注日志记录开始 */ String content = "编辑摄像头:" + deviceSerial + "编辑内容:" + notes; List list = new ArrayList<>(); list.add(deviceSerial); StoreOperationRecordsUtils.storeOperationData(list, null, "编辑摄像头", content); /** * 添加摄像头备注日志记录结束 */ return updateById(one); } else { throw new BusinessException("摄像头设备不存在!"); } } /** * 向Redis中存入设备状态 */ public void setCacheData() { list().forEach( device -> { RedisDeviceStatus deviceStatus = new RedisDeviceStatus(); deviceStatus.setDeviceId(device.getDeviceSerial()); if (device != null) { EquipmentInfomation monitorInfo = getMonitorInfo(device.getDeviceSerial()); if (monitorInfo != null) { if ("在线".equals(monitorInfo.getEquipmentState())) { deviceStatus.setStatus(0); } else { deviceStatus.setStatus(1); } } else { deviceStatus.setStatus(1); } } redisUtils.set(DeviceRedisKey.MONITOR + device.getDeviceSerial(), JSON.toJSONString(deviceStatus)); // redisUtils.delete(DeviceRedisKey.MONITOR + device.getDeviceSerial()); } ); } }