package com.ruoyi.other.controller;
|
|
import com.alibaba.fastjson2.JSONObject;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.ruoyi.common.core.domain.R;
|
import com.ruoyi.common.core.web.domain.AjaxResult;
|
import com.ruoyi.common.core.web.page.PageInfo;
|
import com.ruoyi.common.security.utils.SecurityUtils;
|
import com.ruoyi.other.api.domain.TDevice;
|
import com.ruoyi.other.api.feignClient.RoleSiteClient;
|
import com.ruoyi.other.api.feignClient.UserSiteClient;
|
import com.ruoyi.other.query.VideoMonitorControlRequest;
|
import com.ruoyi.other.query.VideoMonitorPageQuery;
|
import com.ruoyi.other.service.TDeviceService;
|
import com.ruoyi.other.util.EzvizOpenApiUtils;
|
import com.ruoyi.other.vo.VideoMonitorDeviceVO;
|
import com.ruoyi.system.api.domain.SysUser;
|
import com.ruoyi.system.api.feignClient.SysUserClient;
|
import com.ruoyi.system.api.feignClient.SysUserRoleClient;
|
import com.ruoyi.system.api.model.SysUserRoleVo;
|
import io.swagger.annotations.ApiOperation;
|
import org.springframework.beans.BeanUtils;
|
import org.springframework.util.StringUtils;
|
import org.springframework.web.bind.annotation.*;
|
|
import javax.annotation.Resource;
|
import java.util.Collections;
|
import java.util.HashSet;
|
import java.util.List;
|
import java.util.Objects;
|
import java.util.Set;
|
import java.util.stream.Collectors;
|
|
/**
|
* 视频监控控制器
|
*
|
* @author ruoyi
|
*/
|
@RestController
|
@RequestMapping("/video-monitor")
|
public class VideoMonitorController {
|
|
private static final String SUCCESS_CODE = "200";
|
|
@Resource
|
private TDeviceService deviceService;
|
|
@Resource
|
private EzvizOpenApiUtils ezvizOpenApiUtils;
|
|
@Resource
|
private SysUserClient sysUserClient;
|
|
@Resource
|
private SysUserRoleClient sysUserRoleClient;
|
|
@Resource
|
private UserSiteClient userSiteClient;
|
|
@Resource
|
private RoleSiteClient roleSiteClient;
|
|
@ResponseBody
|
@GetMapping("/pageList")
|
@ApiOperation(value = "获取视频监控列表", tags = {"管理后台-视频监控"})
|
public AjaxResult<PageInfo<VideoMonitorDeviceVO>> pageList(VideoMonitorPageQuery query) {
|
DeviceAuthScope scope = resolveAuthScope();
|
if (scope.siteIds != null && scope.siteIds.isEmpty()) {
|
// 非管理员且无任何授权站点:直接返回空列表,避免全量查询
|
return AjaxResult.success(new PageInfo<>(query.getPageCurr(), query.getPageSize()));
|
}
|
Page<TDevice> page = deviceService.lambdaQuery()
|
.like(StringUtils.hasText(query.getDeviceName()), TDevice::getDeviceName, query.getDeviceName())
|
.eq(query.getPartnerType() != null, TDevice::getPartnerType, query.getPartnerType())
|
.eq(query.getPartnerId() != null, TDevice::getPartnerId, query.getPartnerId())
|
.eq(query.getSiteId() != null && query.getSiteId() != 0, TDevice::getSiteId, query.getSiteId())
|
.eq(scope.partnerId != null, TDevice::getPartnerId, scope.partnerId)
|
.in(scope.siteIds != null, TDevice::getSiteId, scope.siteIds)
|
.orderByDesc(TDevice::getCreateTime)
|
.page(Page.of(query.getPageCurr(), query.getPageSize()));
|
|
List<VideoMonitorDeviceVO> records = page.getRecords().stream()
|
.map(device -> {
|
VideoMonitorDeviceVO vo = toMonitorVO(device);
|
fillOnlineStatus(vo);
|
fillLiveAddress(vo, device);
|
return vo;
|
})
|
.filter(item -> query.getOnlineStatus() == null || query.getOnlineStatus().equals(item.getOnlineStatus()))
|
.collect(Collectors.toList());
|
|
PageInfo<VideoMonitorDeviceVO> pageInfo = new PageInfo<>(query.getPageCurr(), query.getPageSize());
|
pageInfo.setTotal(page.getTotal());
|
pageInfo.setRecords(records);
|
return AjaxResult.success(pageInfo);
|
}
|
|
@ResponseBody
|
@GetMapping("/detail/{id}")
|
@ApiOperation(value = "获取视频监控详情", tags = {"管理后台-视频监控"})
|
public AjaxResult<VideoMonitorDeviceVO> detail(@PathVariable Integer id) {
|
TDevice device = getDevice(id);
|
if (device == null) {
|
return AjaxResult.error("设备不存在");
|
}
|
if (!canAccessDevice(device)) {
|
return AjaxResult.error("无权访问该设备");
|
}
|
|
VideoMonitorDeviceVO vo = toMonitorVO(device);
|
fillOnlineStatus(vo);
|
fillLiveAddress(vo, device);
|
return AjaxResult.success(vo);
|
}
|
|
@ResponseBody
|
@PostMapping("/ptz")
|
@ApiOperation(value = "视频监控云台控制", tags = {"管理后台-视频监控"})
|
public AjaxResult ptz(@RequestBody VideoMonitorControlRequest request) {
|
TDevice device = getDevice(request.getId());
|
if (device == null) {
|
return AjaxResult.error("设备不存在");
|
}
|
if (!canAccessDevice(device)) {
|
return AjaxResult.error("无权访问该设备");
|
}
|
|
JSONObject result = ezvizOpenApiUtils.ptzControl(
|
device.getDeviceSerial(),
|
defaultChannelNo(request.getChannelNo(), device),
|
StringUtils.hasText(request.getAction()) ? request.getAction() : "start",
|
request.getCommand(),
|
request.getSpeed()
|
);
|
return buildEzvizResult(result, "云台控制失败");
|
}
|
|
@ResponseBody
|
@PostMapping("/sceneSwitch")
|
@ApiOperation(value = "视频监控镜头开关", tags = {"管理后台-视频监控"})
|
public AjaxResult sceneSwitch(@RequestBody VideoMonitorControlRequest request) {
|
TDevice device = getDevice(request.getId());
|
if (device == null) {
|
return AjaxResult.error("设备不存在");
|
}
|
if (!canAccessDevice(device)) {
|
return AjaxResult.error("无权访问该设备");
|
}
|
|
JSONObject result = ezvizOpenApiUtils.setSceneSwitch(
|
device.getDeviceSerial(),
|
defaultChannelNo(request.getChannelNo(), device),
|
request.getEnable()
|
);
|
return buildEzvizResult(result, "摄像头开关控制失败");
|
}
|
|
@ResponseBody
|
@PostMapping("/focus")
|
@ApiOperation(value = "视频监控焦距控制", tags = {"管理后台-视频监控"})
|
public AjaxResult focus(@RequestBody VideoMonitorControlRequest request) {
|
TDevice device = getDevice(request.getId());
|
if (device == null) {
|
return AjaxResult.error("设备不存在");
|
}
|
if (!canAccessDevice(device)) {
|
return AjaxResult.error("无权访问该设备");
|
}
|
|
JSONObject result = ezvizOpenApiUtils.ptzControl(
|
device.getDeviceSerial(),
|
defaultChannelNo(request.getChannelNo(), device),
|
"start",
|
request.getCommand(),
|
request.getSpeed()
|
);
|
if (isEzvizSuccess(result)) {
|
ezvizOpenApiUtils.ptzControl(
|
device.getDeviceSerial(),
|
defaultChannelNo(request.getChannelNo(), device),
|
"stop",
|
request.getCommand(),
|
null
|
);
|
}
|
return buildEzvizResult(result, "焦距控制失败");
|
}
|
|
@ResponseBody
|
@PostMapping("/playback")
|
@ApiOperation(value = "获取视频监控回放地址", tags = {"管理后台-视频监控"})
|
public AjaxResult<VideoMonitorDeviceVO> playback(@RequestBody VideoMonitorControlRequest request) {
|
TDevice device = getDevice(request.getId());
|
if (device == null) {
|
return AjaxResult.error("设备不存在");
|
}
|
if (!canAccessDevice(device)) {
|
return AjaxResult.error("无权访问该设备");
|
}
|
|
JSONObject result;
|
if (Integer.valueOf(2).equals(request.getType())) {
|
result = ezvizOpenApiUtils.getLocalPlaybackAddress(
|
device.getDeviceSerial(),
|
device.getValidateCode(),
|
defaultChannelNo(request.getChannelNo(), device),
|
request.getStartTime(),
|
request.getStopTime()
|
);
|
} else {
|
result = ezvizOpenApiUtils.getCloudPlaybackAddress(
|
device.getDeviceSerial(),
|
device.getValidateCode(),
|
defaultChannelNo(request.getChannelNo(), device),
|
request.getStartTime(),
|
request.getStopTime()
|
);
|
}
|
|
if (!isEzvizSuccess(result)) {
|
return AjaxResult.error(ezvizErrorMessage("获取回放地址失败", result));
|
}
|
VideoMonitorDeviceVO vo = toMonitorVO(device);
|
vo.setPlaybackAddress(resolveVideoUrl(result));
|
return AjaxResult.success(vo);
|
}
|
|
/**
|
* 设备数据访问范围
|
* siteIds 为 null 表示不限站点;partnerId 非空表示仅限该合作商名下设备
|
*/
|
private static class DeviceAuthScope {
|
private final Set<Integer> siteIds;
|
private final Integer partnerId;
|
|
DeviceAuthScope(Set<Integer> siteIds, Integer partnerId) {
|
this.siteIds = siteIds;
|
this.partnerId = partnerId;
|
}
|
}
|
|
/**
|
* 解析当前登录用户可访问的设备范围(与站点管理 getSiteList 口径一致):
|
* 合作商(roleType=2)仅可见自己名下设备;roleId=1 管理员不限;其他用户按 用户站点 ∪ 角色站点 过滤
|
*/
|
private DeviceAuthScope resolveAuthScope() {
|
Long userId = SecurityUtils.getUserId();
|
SysUser user = sysUserClient.getSysUser(userId).getData();
|
if (user == null) {
|
return new DeviceAuthScope(Collections.emptySet(), null);
|
}
|
Integer roleType = user.getRoleType();
|
Integer objectId = user.getObjectId();
|
// 合作商:仅可见自己名下的设备
|
if (Objects.equals(roleType, 2)) {
|
return new DeviceAuthScope(null, objectId);
|
}
|
// 与站点管理一致:roleId != 1 视为非管理员
|
R<Integer> admin = sysUserClient.isAdmin(userId);
|
if (admin != null && admin.getData() != null && admin.getData() == 1) {
|
return new DeviceAuthScope(null, null);
|
}
|
return new DeviceAuthScope(getAssignedSiteIds(user.getUserId()), null);
|
}
|
|
private Set<Integer> getAssignedSiteIds(Long userId) {
|
Set<Integer> siteIds = new HashSet<>();
|
if (userId == null) {
|
return siteIds;
|
}
|
R<List<Integer>> userSiteResult = userSiteClient.getSiteIds(userId);
|
if (userSiteResult != null && userSiteResult.getData() != null) {
|
siteIds.addAll(userSiteResult.getData());
|
}
|
R<List<SysUserRoleVo>> roleResult = sysUserRoleClient.getRoleByUserId(userId);
|
if (roleResult != null && roleResult.getData() != null) {
|
for (SysUserRoleVo role : roleResult.getData()) {
|
if (role == null || role.getRoleId() == null) {
|
continue;
|
}
|
R<List<Integer>> roleSiteResult = roleSiteClient.getSiteIds(role.getRoleId());
|
if (roleSiteResult != null && roleSiteResult.getData() != null) {
|
siteIds.addAll(roleSiteResult.getData());
|
}
|
}
|
}
|
return siteIds;
|
}
|
|
private boolean canAccessDevice(TDevice device) {
|
if (device == null) {
|
return false;
|
}
|
DeviceAuthScope scope = resolveAuthScope();
|
if (scope.partnerId != null) {
|
return Objects.equals(device.getPartnerId(), scope.partnerId);
|
}
|
if (scope.siteIds == null) {
|
return true; // 管理员
|
}
|
return device.getSiteId() != null && scope.siteIds.contains(device.getSiteId());
|
}
|
|
private TDevice getDevice(Integer id) {
|
if (id == null) {
|
return null;
|
}
|
TDevice device = deviceService.getById(id);
|
if (device == null) {
|
return null;
|
}
|
return device;
|
}
|
|
private VideoMonitorDeviceVO toMonitorVO(TDevice device) {
|
VideoMonitorDeviceVO vo = new VideoMonitorDeviceVO();
|
BeanUtils.copyProperties(device, vo);
|
return vo;
|
}
|
|
private void fillOnlineStatus(VideoMonitorDeviceVO vo) {
|
try {
|
JSONObject result = ezvizOpenApiUtils.getDeviceInfo(vo.getDeviceSerial());
|
if (!isEzvizSuccess(result)) {
|
result = ezvizOpenApiUtils.getDeviceStatus(vo.getDeviceSerial());
|
}
|
if (!isEzvizSuccess(result)) {
|
vo.setOnlineStatus(0);
|
vo.setStatusMsg(ezvizErrorMessage("获取在线状态失败", result));
|
return;
|
}
|
JSONObject data = result.getJSONObject("data");
|
Integer status = data == null ? null : data.getInteger("status");
|
if (status == null && data != null) {
|
status = data.getInteger("onlineStatus");
|
}
|
vo.setOnlineStatus(Integer.valueOf(1).equals(status) ? 1 : 0);
|
vo.setStatusMsg(Integer.valueOf(1).equals(vo.getOnlineStatus()) ? "在线" : "不在线");
|
} catch (Exception e) {
|
vo.setOnlineStatus(0);
|
vo.setStatusMsg("获取在线状态失败:" + e.getMessage());
|
}
|
}
|
|
private void fillLiveAddress(VideoMonitorDeviceVO vo, TDevice device) {
|
int channelNo = defaultChannelNo(null, device);
|
try {
|
vo.setAccessToken(ezvizOpenApiUtils.getAccessToken());
|
vo.setChannelNo(channelNo);
|
vo.setLiveAddress(buildEzopenLiveAddress(device.getDeviceSerial(), channelNo));
|
if (Integer.valueOf(1).equals(vo.getOnlineStatus())) {
|
vo.setStatusMsg("在线");
|
}
|
} catch (Exception e) {
|
vo.setLiveAddress(null);
|
vo.setStatusMsg("获取直播凭证失败:" + e.getMessage());
|
}
|
}
|
|
private String buildEzopenLiveAddress(String deviceSerial, Integer channelNo) {
|
return String.format("ezopen://open.ys7.com/%s/%d.live", deviceSerial, channelNo);
|
}
|
|
private AjaxResult buildEzvizResult(JSONObject result, String defaultMessage) {
|
if (isEzvizSuccess(result)) {
|
return AjaxResult.success(result);
|
}
|
return AjaxResult.error(ezvizErrorMessage(defaultMessage, result), result);
|
}
|
|
private boolean isEzvizSuccess(JSONObject result) {
|
return result != null && SUCCESS_CODE.equals(result.getString("code"));
|
}
|
|
private String ezvizErrorMessage(String defaultMessage, JSONObject result) {
|
if (result == null) {
|
return defaultMessage;
|
}
|
String message = result.getString("msg");
|
if (StringUtils.hasText(message)) {
|
return message;
|
}
|
String code = result.getString("code");
|
return StringUtils.hasText(code) ? defaultMessage + ",错误码:" + code : defaultMessage;
|
}
|
|
private String resolveVideoUrl(JSONObject result) {
|
JSONObject data = result.getJSONObject("data");
|
if (data == null) {
|
return null;
|
}
|
String url = data.getString("url");
|
if (StringUtils.hasText(url)) {
|
return url;
|
}
|
return data.getString("ezopen");
|
}
|
|
private Integer defaultChannelNo(Integer channelNo, TDevice device) {
|
if (channelNo != null && channelNo > 0) {
|
return channelNo;
|
}
|
if (device != null && device.getChannelNo() != null && device.getChannelNo() > 0) {
|
return device.getChannelNo();
|
}
|
return 1;
|
}
|
}
|