diff --git a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/config/ZLMediaKitConfig.java b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/config/ZLMediaKitConfig.java new file mode 100644 index 00000000..d6289ff2 --- /dev/null +++ b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/config/ZLMediaKitConfig.java @@ -0,0 +1,24 @@ +package org.dromara.sis.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +@Data +@Configuration +@ConfigurationProperties(prefix = "zlm") +public class ZLMediaKitConfig { + + private String ip; + + private String apiSecret; + + private Short rtspPort; + + private Short rtmpPort; + + private Short httpPort; + + private String vhost; + +} diff --git a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/controller/SisElevatorFloorRefController.java b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/controller/SisElevatorFloorRefController.java new file mode 100644 index 00000000..93daebba --- /dev/null +++ b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/controller/SisElevatorFloorRefController.java @@ -0,0 +1,106 @@ +package org.dromara.sis.controller; + +import java.util.List; + +import lombok.RequiredArgsConstructor; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.constraints.*; +import cn.dev33.satoken.annotation.SaCheckPermission; +import org.springframework.web.bind.annotation.*; +import org.springframework.validation.annotation.Validated; +import org.dromara.common.idempotent.annotation.RepeatSubmit; +import org.dromara.common.log.annotation.Log; +import org.dromara.common.web.core.BaseController; +import org.dromara.common.mybatis.core.page.PageQuery; +import org.dromara.common.core.domain.R; +import org.dromara.common.core.validate.AddGroup; +import org.dromara.common.core.validate.EditGroup; +import org.dromara.common.log.enums.BusinessType; +import org.dromara.common.excel.utils.ExcelUtil; +import org.dromara.sis.domain.vo.SisElevatorFloorRefVo; +import org.dromara.sis.domain.bo.SisElevatorFloorRefBo; +import org.dromara.sis.service.ISisElevatorFloorRefService; +import org.dromara.common.mybatis.core.page.TableDataInfo; + +/** + * 电梯⇄楼层关联 + * 前端访问路由地址为:/sis/elevatorFloorRef + * + * @author lsm + * @since 2025-07-15 + */ +@Validated +@RequiredArgsConstructor +@RestController +@RequestMapping("/elevatorFloorRef") +public class SisElevatorFloorRefController extends BaseController { + + private final ISisElevatorFloorRefService sisElevatorFloorRefService; + + /** + * 查询电梯⇄楼层关联列表 + */ + @SaCheckPermission("sis:elevatorFloorRef:list") + @GetMapping("/list") + public TableDataInfo list(SisElevatorFloorRefBo bo, PageQuery pageQuery) { + return sisElevatorFloorRefService.queryPageList(bo, pageQuery); + } + + /** + * 导出电梯⇄楼层关联列表 + */ + @SaCheckPermission("sis:elevatorFloorRef:export") + @Log(title = "电梯⇄楼层关联", businessType = BusinessType.EXPORT) + @PostMapping("/export") + public void export(SisElevatorFloorRefBo bo, HttpServletResponse response) { + List list = sisElevatorFloorRefService.queryList(bo); + ExcelUtil.exportExcel(list, "电梯⇄楼层关联", SisElevatorFloorRefVo.class, response); + } + + /** + * 获取电梯⇄楼层关联详细信息 + * + * @param id 主键 + */ + @SaCheckPermission("sis:elevatorFloorRef:query") + @GetMapping("/{id}") + public R getInfo(@NotNull(message = "主键不能为空") + @PathVariable("id") Long id) { + return R.ok(sisElevatorFloorRefService.queryById(id)); + } + + /** + * 新增电梯⇄楼层关联 + */ + @SaCheckPermission("sis:elevatorFloorRef:add") + @Log(title = "电梯⇄楼层关联", businessType = BusinessType.INSERT) + @RepeatSubmit() + @PostMapping() + public R add(@Validated(AddGroup.class) @RequestBody SisElevatorFloorRefBo bo) { + return toAjax(sisElevatorFloorRefService.insertByBo(bo)); + } + + /** + * 修改电梯⇄楼层关联 + */ + @SaCheckPermission("sis:elevatorFloorRef:edit") + @Log(title = "电梯⇄楼层关联", businessType = BusinessType.UPDATE) + @RepeatSubmit() + @PutMapping() + public R edit(@Validated(EditGroup.class) @RequestBody SisElevatorFloorRefBo bo) { + return toAjax(sisElevatorFloorRefService.updateByBo(bo)); + } + + /** + * 删除电梯⇄楼层关联 + * + * @param ids 主键串 + */ + @SaCheckPermission("sis:elevatorFloorRef:remove") + @Log(title = "电梯⇄楼层关联", businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + public R remove(@NotEmpty(message = "主键不能为空") + @PathVariable("ids") Long[] ids) { + return toAjax(sisElevatorFloorRefService.deleteWithValidByIds(List.of(ids), true)); + } +} diff --git a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/controller/zkmedia/ZKLmediaController.java b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/controller/zkmedia/ZKLmediaController.java new file mode 100644 index 00000000..08bfff36 --- /dev/null +++ b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/controller/zkmedia/ZKLmediaController.java @@ -0,0 +1,125 @@ +package org.dromara.sis.controller.zkmedia; + +import cn.hutool.core.util.IdUtil; +import lombok.extern.slf4j.Slf4j; +import org.dromara.common.core.domain.R; +import org.dromara.sis.sdk.zkmedia.MediaServerUtils; +import org.dromara.sis.sdk.zkmedia.ZLMediaKitService; +import org.dromara.sis.sdk.zkmedia.model.AddStreamProxy; +import org.dromara.sis.sdk.zkmedia.model.AddStreamProxyResp; +import org.dromara.sis.sdk.zkmedia.model.StartStreamProxy; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; + +/** + * ZKLmedia 流媒体服务 + * + * @author lxj + * @since 2025-07-15 + */ +@Slf4j +@RestController +@RequestMapping("/stream") +public class ZKLmediaController { + + @Resource + private ZLMediaKitService zlMediaKitService; + + + private static final String HIK_REALTIME_RTSP_TEMPLATE = "rtsp://%s:%s@%s:%s/Streaming/Channels/%s"; + private static final String DAHUA_REALTIME_RTSP_TEMPLATE = "rtsp://%s:%s@%s:%s/cam/realmonitor?channel=%s&subtype=0"; + + private static final String HIK_HISTORY_RTSP_TEMPLATE = "rtsp://%s:%s@%s:%s/Streaming/tracks/%s?starttime=%s&endtime=%s"; + private static final String DAHUA_HISTORY_RTSP_TEMPLATE = "rtsp://%s:%s@%s:%s/cam/playback?channel=%s&subtype=0&starttime=%s&endtime=%s"; + + /** + * 创建拉流任务,返回null代表创建拉流任务失败 + * + * @param data 创建拉流设备信息(如果外网不建议使用这种方式) + * @return 返回拉流任务信息 + */ + @PostMapping("/realtime/add") + public R alarm(@RequestBody @Validated AddStreamProxy data) { + StartStreamProxy proxy = new StartStreamProxy(); + proxy.setApp("realtime"); + String s = IdUtil.fastSimpleUUID(); + proxy.setStream(s); + if ("DS1010".equals(data.getFactoryNo())) { + proxy.setUrl(String.format(HIK_REALTIME_RTSP_TEMPLATE, data.getAccount(), data.getPwd(), data.getVideoIp(), data.getVideoPort(), data.getChannelId())); + } else if ("DS1014".equals(data.getFactoryNo())) { + proxy.setUrl(String.format(DAHUA_REALTIME_RTSP_TEMPLATE, data.getAccount(), data.getPwd(), data.getVideoIp(), data.getVideoPort(), data.getChannelId())); + } else { + throw new RuntimeException("未知的设备类型!"); + } + AddStreamProxyResp addStreamProxyResp = zlMediaKitService.addStreamProxy(proxy); + if (addStreamProxyResp != null) { + return R.ok(addStreamProxyResp); + } + return R.fail(); + } + + /** + * 创建历史回放拉流任务,返回null代表创建拉流任务失败 + * + * @param data 创建拉流设备信息(如果外网不建议使用这种方式) + * @return 返回拉流任务信息 + */ + @PostMapping("/history/add") + public R history(@RequestBody @Validated AddStreamProxy data) throws InterruptedException { + StartStreamProxy proxy = new StartStreamProxy(); + proxy.setApp("history"); + String s = IdUtil.fastSimpleUUID(); + proxy.setStream(s); + if ("DS1010".equals(data.getFactoryNo())) { + String pattern = "yyyyMMdd'T'HHmmss'Z'"; + String startTime = MediaServerUtils.formatTimestamp(data.getStartTime(), "yyyyMMdd'T'HHmmss'Z'"); + String endTime = MediaServerUtils.formatTimestamp(data.getEndTime(), "yyyyMMdd'T'HHmmss'Z'"); + proxy.setUrl(String.format(HIK_HISTORY_RTSP_TEMPLATE, data.getAccount(), data.getPwd(), data.getVideoIp(), data.getVideoPort(), data.getChannelId(), startTime, endTime)); + } else if ("DS1014".equals(data.getFactoryNo())) { + String startTime = MediaServerUtils.formatTimestamp(data.getStartTime(), "yyyy_MM_dd_HH_mm_ss"); + String endTime = MediaServerUtils.formatTimestamp(data.getEndTime(), "yyyy_MM_dd_HH_mm_ss"); + proxy.setUrl(String.format(DAHUA_HISTORY_RTSP_TEMPLATE, data.getAccount(), data.getPwd(), data.getVideoIp(), data.getVideoPort(), data.getChannelId(), startTime, endTime)); + } else { + throw new RuntimeException("未知的设备类型!"); + } + AddStreamProxyResp addStreamProxyResp = zlMediaKitService.addStreamProxy(proxy); + if (addStreamProxyResp != null) { + return R.ok(addStreamProxyResp); + } + return R.fail(); + } + + /** + * 查询设备的信息 + * + * @param data 设备ip + * @return + */ + /*@PostMapping("/queryMediaInfo") + public R queryMediaInfo(@RequestBody VideoConfigTreeDTO data) { + if (StringUtils.isEmpty(data.getVideoIp())) { + throw new BizException(ErrorType.VIDEOIP_FAIL, "视频IP不能为空"); + } + logger.info("查询视频信息,参数:{}", JSONObject.toJSON(data.getVideoIp())); + TpEqpAcquisitionDTO result = tpEqpAcquisitionService.queryConfigByEqpNo(data.getVideoIp()); + logger.info("查询视频信息,返回信息:{}", JSONObject.toJSON(result)); + return BizResultVO.success(result); + } + + @PostMapping("/history/delete/{stream}") + public BizResultVO delete(@PathVariable("stream") String stream) throws InterruptedException { + StartStreamProxy proxy = new StartStreamProxy(); + proxy.setApp("history"); + proxy.setStream(stream); + String ss = zlMediaKitService.delStreamProxy(proxy); + if (ss != null) { + return BizResultVO.success(ss); + } + return BizResultVO.fail(ErrorType.ADD_STREAMPROXY_FAIL, null); + }*/ +} diff --git a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/domain/SisElevatorFloorRef.java b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/domain/SisElevatorFloorRef.java new file mode 100644 index 00000000..59f93ee5 --- /dev/null +++ b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/domain/SisElevatorFloorRef.java @@ -0,0 +1,41 @@ +package org.dromara.sis.domain; + +import org.dromara.common.tenant.core.TenantEntity; +import com.baomidou.mybatisplus.annotation.*; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serial; + +/** + * 电梯⇄楼层关联对象 sis_elevator_floor_ref + * + * @author lsm + * @since 2025-07-15 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("sis_elevator_floor_ref") +public class SisElevatorFloorRef extends TenantEntity { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 主键id + */ + @TableId(value = "id") + private Long id; + + /** + * 电梯id + */ + private Long elevatorId; + + /** + * 楼层层数 + */ + private Long layerNum; + + +} diff --git a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/domain/bo/SisElevatorFloorRefBo.java b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/domain/bo/SisElevatorFloorRefBo.java new file mode 100644 index 00000000..3da9c32f --- /dev/null +++ b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/domain/bo/SisElevatorFloorRefBo.java @@ -0,0 +1,42 @@ +package org.dromara.sis.domain.bo; + +import org.dromara.sis.domain.SisElevatorFloorRef; +import org.dromara.common.mybatis.core.domain.BaseEntity; +import org.dromara.common.core.validate.AddGroup; +import org.dromara.common.core.validate.EditGroup; +import io.github.linpeilie.annotations.AutoMapper; +import lombok.Data; +import lombok.EqualsAndHashCode; +import jakarta.validation.constraints.*; + +/** + * 电梯⇄楼层关联业务对象 sis_elevator_floor_ref + * + * @author lsm + * @since 2025-07-15 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@AutoMapper(target = SisElevatorFloorRef.class, reverseConvertGenerate = false) +public class SisElevatorFloorRefBo extends BaseEntity { + + /** + * 主键id + */ + @NotNull(message = "主键id不能为空", groups = { EditGroup.class }) + private Long id; + + /** + * 电梯id + */ + @NotNull(message = "电梯id不能为空", groups = { AddGroup.class, EditGroup.class }) + private Long elevatorId; + + /** + * 楼层层数 + */ + @NotNull(message = "楼层层数不能为空", groups = { AddGroup.class, EditGroup.class }) + private Long layerNum; + + +} diff --git a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/domain/vo/SisAccessControlVo.java b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/domain/vo/SisAccessControlVo.java index 864abcaa..d9d30feb 100644 --- a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/domain/vo/SisAccessControlVo.java +++ b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/domain/vo/SisAccessControlVo.java @@ -105,6 +105,12 @@ public class SisAccessControlVo implements Serializable { @ExcelProperty(value = "外部编码") private String outCode; + /** + * 外部门编码 + */ + @ExcelProperty(value = "外部编码") + private String outDoorCode; + private String bindDeviceId; private String bindDeviceIp; diff --git a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/domain/vo/SisAuthRecordVo.java b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/domain/vo/SisAuthRecordVo.java index 6b9d50ad..4f26c293 100644 --- a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/domain/vo/SisAuthRecordVo.java +++ b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/domain/vo/SisAuthRecordVo.java @@ -42,7 +42,7 @@ public class SisAuthRecordVo implements Serializable { * 设备id(门禁/电梯) */ @ExcelProperty(value = "设备id", converter = ExcelDictConvert.class) - @ExcelDictFormat(readConverterExp = "门=禁/电梯") + @ExcelDictFormat(readConverterExp = "门禁/电梯") private Long deviceId; /** diff --git a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/domain/vo/SisElevatorFloorRefVo.java b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/domain/vo/SisElevatorFloorRefVo.java new file mode 100644 index 00000000..31d5b63a --- /dev/null +++ b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/domain/vo/SisElevatorFloorRefVo.java @@ -0,0 +1,50 @@ +package org.dromara.sis.domain.vo; + +import org.dromara.sis.domain.SisElevatorFloorRef; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import org.dromara.common.excel.annotation.ExcelDictFormat; +import org.dromara.common.excel.convert.ExcelDictConvert; +import io.github.linpeilie.annotations.AutoMapper; +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; +import java.util.Date; + + + +/** + * 电梯⇄楼层关联视图对象 sis_elevator_floor_ref + * + * @author lsm + * @since 2025-07-15 + */ +@Data +@ExcelIgnoreUnannotated +@AutoMapper(target = SisElevatorFloorRef.class) +public class SisElevatorFloorRefVo implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 主键id + */ + @ExcelProperty(value = "主键id") + private Long id; + + /** + * 电梯id + */ + @ExcelProperty(value = "电梯id") + private Long elevatorId; + + /** + * 楼层层数 + */ + @ExcelProperty(value = "楼层层数") + private Long layerNum; + + +} diff --git a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/mapper/SisAuthRecordMapper.java b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/mapper/SisAuthRecordMapper.java index 54f18483..da91c0c0 100644 --- a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/mapper/SisAuthRecordMapper.java +++ b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/mapper/SisAuthRecordMapper.java @@ -4,6 +4,8 @@ import org.dromara.sis.domain.SisAuthRecord; import org.dromara.sis.domain.vo.SisAuthRecordVo; import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; +import java.util.List; + /** * 授权记录Mapper接口 * @@ -11,5 +13,5 @@ import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; * @since 2025-07-14 */ public interface SisAuthRecordMapper extends BaseMapperPlus { - + List checkAuth(Long personId); } diff --git a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/mapper/SisElevatorFloorRefMapper.java b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/mapper/SisElevatorFloorRefMapper.java new file mode 100644 index 00000000..3381838f --- /dev/null +++ b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/mapper/SisElevatorFloorRefMapper.java @@ -0,0 +1,15 @@ +package org.dromara.sis.mapper; + +import org.dromara.sis.domain.SisElevatorFloorRef; +import org.dromara.sis.domain.vo.SisElevatorFloorRefVo; +import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; + +/** + * 电梯⇄楼层关联Mapper接口 + * + * @author lsm + * @date 2025-07-15 + */ +public interface SisElevatorFloorRefMapper extends BaseMapperPlus { + +} diff --git a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/runner/HikDeviceApplicationRunner.java b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/runner/HikDeviceApplicationRunner.java index e0a303b6..e97504f6 100644 --- a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/runner/HikDeviceApplicationRunner.java +++ b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/runner/HikDeviceApplicationRunner.java @@ -4,25 +4,29 @@ import cn.hutool.core.collection.CollUtil; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.dromara.common.core.utils.SpringUtils; +import org.dromara.sis.domain.bo.SisDeviceManageBo; +import org.dromara.sis.domain.vo.SisDeviceManageVo; import org.dromara.sis.domain.vo.SisElevatorInfoVo; import org.dromara.sis.sdk.hik.HikApiService; import org.dromara.sis.sdk.hik.calback.HikAlarmCallBack; +import org.dromara.sis.service.ISisDeviceManageService; import org.dromara.sis.service.ISisElevatorInfoService; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; -import java.util.Arrays; +import java.util.ArrayList; import java.util.List; @Slf4j -@RequiredArgsConstructor @Component +@RequiredArgsConstructor public class HikDeviceApplicationRunner implements ApplicationRunner { - private final ISisElevatorInfoService elevatorInfoService; private final HikAlarmCallBack hikAlarmCallBack; + private final ISisDeviceManageService deviceManageService; + private final ISisElevatorInfoService elevatorInfoService; @Override public void run(ApplicationArguments args) throws Exception { @@ -38,35 +42,73 @@ public class HikDeviceApplicationRunner implements ApplicationRunner { @Async public void hikElevatorInfoLogin() { - /*List sisElevatorInfoVos = elevatorInfoService.queryAll(); + List sisElevatorInfoVos = elevatorInfoService.queryAll(); if (CollUtil.isNotEmpty(sisElevatorInfoVos)) { sisElevatorInfoVos.forEach(item -> { // 执行设备登录操作 HikApiService.getInstance().login(item.getControlIp(), item.getControlPort().shortValue(), item.getControlAccount(), item.getControlPwd()); + // 根据建筑ID获取楼层信息 +// SisFloorInfoVo floorInfo = floorInfoService.queryByBuildingId(item.getBuildingId()); + // 获取楼层数组 +// List layerArray = generateFloorArray(floorInfo.getMinLayer().intValue(), floorInfo.getMaxLayer().intValue()); + // 下发权限 +// for (int i = 0; i < layerArray.size(); i++) { +// HikApiService.getInstance().controlGateway(item.getControlIp(), (i + 1), layerArray.get(i)); +// } }); - }*/ - String ip = "192.168.24.188"; - short port = 8000; - String account = "admin"; - String pwd = "qweasd123"; - HikApiService.getInstance().login(ip, port, account, pwd); - List arrs = Arrays.asList(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2); - for (int i = 0; i < arrs.size(); i++) { - HikApiService.getInstance().controlGateway(ip, (i + 1), arrs.get(i)); + } +// String ip = "192.168.24.188"; +// short port = 8000; +// String account = "admin"; +// String pwd = "qweasd123"; +// HikApiService.getInstance().login(ip, port, account, pwd); +// List arrs = Arrays.asList(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2); +// for (int i = 0; i < arrs.size(); i++) { +// HikApiService.getInstance().controlGateway(ip, (i + 1), arrs.get(i)); +// } + } + + //输入最低层,最高层,返回楼层数组 + public List generateFloorArray(int minLayer, int maxLayer) { + // 验证输入范围 + if (minLayer > maxLayer) { + throw new IllegalArgumentException("最低层不能大于最高层"); } + // 使用List动态收集楼层 + List layerList = new ArrayList<>(); + + // 遍历所有楼层,跳过0层 + for (int layer = minLayer; layer <= maxLayer; layer++) { + if (layer != 0) { + // 初始数组赋值为3,不下发权限 + layerList.add(3); + } + } + + return layerList; } @Async public void hikNetCameraLogin() { - String ip = "192.168.24.19"; - short port = 8000; - String account = "admin"; - String pwd = "xzf13579"; - int handler = HikApiService.getInstance().login(ip, port, account, pwd); - if(handler != -1){ - HikApiService.getInstance().setAlarmChan(handler); + List deviceList = deviceManageService.queryList(new SisDeviceManageBo()); + + if (CollUtil.isEmpty(deviceList)) { + log.info("没有查询到摄像设备信息,不执行登录"); + return; } + + deviceList.forEach(item -> { + int handler = HikApiService.getInstance().login(item.getDeviceIp(), item.getDevicePort().shortValue(), item.getDeviceAccount(), item.getDevicePwd()); + if (handler != -1) { + HikApiService.getInstance().setAlarmChan(handler); + } + }); +// String ip = "192.168.24.19"; +// short port = 8000; +// String account = "admin"; +// String pwd = "xzf13579"; +// int handler = HikApiService.getInstance().login(ip, port, account, pwd); } } diff --git a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/hik/calback/HikAlarmCallBack.java b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/hik/calback/HikAlarmCallBack.java index ae400392..f4c5d8fe 100644 --- a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/hik/calback/HikAlarmCallBack.java +++ b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/hik/calback/HikAlarmCallBack.java @@ -1,16 +1,22 @@ package org.dromara.sis.sdk.hik.calback; import cn.hutool.core.codec.Base64Encoder; +import cn.hutool.core.collection.CollUtil; import com.sun.jna.Pointer; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.dromara.sis.domain.vo.*; +import org.dromara.sis.sdk.e8.AccessControlService; +import org.dromara.sis.sdk.e8.domain.accessControl.req.RemoteOpenDoorReq; import org.dromara.sis.sdk.hik.HCNetSDK; import org.dromara.sis.sdk.hik.HikApiService; import org.dromara.sis.sdk.huawei.HuaWeiBoxApi; +import org.dromara.sis.service.*; import org.springframework.stereotype.Component; import java.nio.ByteBuffer; -import java.util.Arrays; +import java.util.ArrayList; +import java.util.Collection; import java.util.List; @Slf4j @@ -19,6 +25,13 @@ import java.util.List; public class HikAlarmCallBack implements HCNetSDK.FMSGCallBack_V31 { private final HuaWeiBoxApi huaWeiBoxApi; + private final ISisAuthRecordService authRecordService; + private final ISisElevatorInfoService elevatorInfoService; + private final ISisDeviceBindRefService deviceBindRefService; + private final ISisAccessControlService accessControlService; + private final ISisElevatorFloorRefService elevatorFloorRefService; + + private final AccessControlService e8AccessControlService; private static final int COMM_UPLOAD_FACESNAP_RESULT = 0x1112; @@ -32,47 +45,133 @@ public class HikAlarmCallBack implements HCNetSDK.FMSGCallBack_V31 { Pointer pItsPlateInfo = result.getPointer(); pItsPlateInfo.write(0, pAlarmInfo.getByteArray(0, result.size()), 0, result.size()); result.read(); + // 读取人脸小图 ByteBuffer buffers = result.pBuffer1.getByteBuffer(0, result.dwFacePicLen); byte[] smallImg = new byte[result.dwFacePicLen]; buffers.rewind(); buffers.get(smallImg); - String dir = ""; + // 读取人脸大图 -// ByteBuffer buffers1 = result.pBuffer2.getByteBuffer(0, result.dwBackgroundPicLen); -// byte[] bigImg = new byte[result.dwBackgroundPicLen]; -// buffers1.rewind(); -// buffers1.get(bigImg); + /*ByteBuffer buffers1 = result.pBuffer2.getByteBuffer(0, result.dwBackgroundPicLen); + byte[] bigImg = new byte[result.dwBackgroundPicLen]; + buffers1.rewind(); + buffers1.get(bigImg);*/ + + //设备ip + String sAlarmInfo = new String(pAlarmer.sDeviceIP).trim(); + // 设备绑定关系 + List bindRefList = deviceBindRefService.queryByDeviceIp(sAlarmInfo); + if (CollUtil.isEmpty(bindRefList)) { + log.info("当前报警设备未绑定门禁/梯控,不做处理!"); + return true; + } + // todo 进行人脸比对 String smallImgBase64Str = Base64Encoder.encode(smallImg); - long s1 = System.currentTimeMillis(); Long person = huaWeiBoxApi.findPerson(smallImgBase64Str); log.info("人脸比对执行完成,耗时:{}", System.currentTimeMillis() - s1); if (person == null) { log.info("未命中人脸数据,暂不处理。"); - log.info("权限下发执行完成,耗时:{}", System.currentTimeMillis() - s); return true; } log.info("人脸比对完成,personId={}", person); + + // 授权记录 + List authVoList = authRecordService.checkAuth(person); + // 获取门禁id + Collection acIds = authVoList.stream().filter(vo -> vo.getDeviceType() == 1).map(SisAuthRecordVo::getDeviceId).toList(); + if (CollUtil.isNotEmpty(acIds)) { + acIds.forEach(id -> { + Long deviceId = bindRefList.stream().filter(vo -> vo.getBindId().equals(id)).findFirst().map(SisDeviceBindRefVo::getDeviceId).orElse(null); + SisAccessControlVo ac = accessControlService.queryById(deviceId); + if (ac != null) { + log.info("调用门禁服务远程开门"); + RemoteOpenDoorReq req = new RemoteOpenDoorReq(); + req.setType(0); + RemoteOpenDoorReq.ControlData data = new RemoteOpenDoorReq.ControlData(); + data.setDeviceId(Long.parseLong(ac.getOutCode())); + data.setDoorId(Long.parseLong(ac.getOutCode())); + req.setControlList(List.of(data)); + Boolean flag = e8AccessControlService.remoteOpenDoor(req); + log.info("远程开门结果,result={}", flag); + } + }); + } + + + // 获取电梯ids +// Collection eleIds = authVoList.stream().filter(vo -> vo.getDeviceType() == 2).map(SisAuthRecordVo::getDeviceId).toList(); +// if (CollUtil.isNotEmpty(eleIds)) { +// eleIds.forEach(id -> { +// Long deviceId = bindRefList.stream().filter(vo -> vo.getBindId().equals(id)).findFirst().map(SisDeviceBindRefVo::getDeviceId).orElse(null); +// SisElevatorInfoVo ele = elevatorInfoService.queryById(deviceId); +// if (ele != null) { +// log.info("下发电梯权限"); +// // 根据建筑ID获取楼层信息 +// SisFloorInfoVo floorInfo = floorInfoService.queryByBuildingId(ele.getBuildingId()); +// // 获取电梯⇄楼层关联信息 +// List floorRefList = elevatorFloorRefService.queryByElevatorId(deviceId); +// // 获取楼层数组 +// List layerArray = generateFloorArray(floorInfo.getMinLayer().intValue(), floorInfo.getMaxLayer().intValue()); +// +// +// layerArray.forEach(layer -> { +// SisElevatorFloorRefVo floorRef = floorRefList.stream() +// .filter(vo -> vo.getLayerNum().intValue() == layer) // 直接使用 layer +// .findFirst() +// .orElse(null); +// +// if (floorRef == null) { +// HikApiService.getInstance().controlGateway(ele.getControlIp(), layer, 3); +// } else { +// HikApiService.getInstance().controlGateway(ele.getControlIp(), layer, 2); +// } +// }); +// } +// +// }); +// } + // List arrs = Arrays.asList(2, 2, 2, 3, 3, 3 ,3, 3, 3, 3, 3, 3, 3, 3, 3, 3); - List arrs = Arrays.asList(3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2); - for (int i = 0; i < arrs.size(); i++) { - HikApiService.getInstance().controlGateway("192.168.24.188", (i + 1), arrs.get(i)); - } - log.info("权限下发执行完成,耗时:{}", System.currentTimeMillis() - s); - try { - Thread.sleep(10000L); - List ass = Arrays.asList(3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3); - for (int i = 0; i < arrs.size(); i++) { - HikApiService.getInstance().controlGateway("192.168.24.188", (i + 1), arrs.get(i)); - } - } catch (InterruptedException e) { - throw new RuntimeException(e); - } +// List arrs = Arrays.asList(3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2); +// for (int i = 0; i < arrs.size(); i++) { +// HikApiService.getInstance().controlGateway("192.168.24.188", (i + 1), arrs.get(i)); +// } +// log.info("权限下发执行完成,耗时:{}", System.currentTimeMillis() - s); +// try { +// Thread.sleep(10000L); +// List ass = Arrays.asList(3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3); +// for (int i = 0; i < arrs.size(); i++) { +// HikApiService.getInstance().controlGateway("192.168.24.188", (i + 1), arrs.get(i)); +// } +// } catch (InterruptedException e) { +// throw new RuntimeException(e); +// } + } else { log.info("未知报警类型,lCommand={}", lCommand); } return true; } + + //输入最低层,最高层,返回楼层数组 + public List generateFloorArray(int minLayer, int maxLayer) { + + // 验证输入范围 + if (minLayer > maxLayer) { + throw new IllegalArgumentException("最低层不能大于最高层"); + } + // 使用List动态收集楼层 + List layerList = new ArrayList<>(); + // 遍历所有楼层,跳过0层 + for (int layer = minLayer; layer <= maxLayer; layer++) { + if (layer != 0) { + layerList.add(layer); + } + } + + return layerList; + } } diff --git a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/zkmedia/HttpClientUtil.java b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/zkmedia/HttpClientUtil.java new file mode 100644 index 00000000..0c6da063 --- /dev/null +++ b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/zkmedia/HttpClientUtil.java @@ -0,0 +1,94 @@ +package org.dromara.sis.sdk.zkmedia; + +import cn.hutool.core.collection.CollectionUtil; +import com.alibaba.fastjson2.JSONObject; +import com.alibaba.fastjson2.TypeReference; +import lombok.extern.slf4j.Slf4j; +import org.apache.http.HttpEntity; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.util.EntityUtils; +import org.dromara.sis.sdk.zkmedia.model.R; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +@Slf4j +public class HttpClientUtil { + + public static T get(String url, Map params, TypeReference reference) { + String s = get(url, params); + return JSONObject.parseObject(s, reference); + } + + public static R get(String url, Map params, Class cls) { + String s = get(url, params); + return JSONObject.parseObject(s, new TypeReference>(cls) { + }); + } + + public static String get(String url, Map params) { + if (params != null && !params.isEmpty()) { + List ls = new ArrayList<>(params.size()); + for (Map.Entry entry : params.entrySet()) { + ls.add(entry.getKey() + "=" + entry.getValue()); + } + url = url + "?" + CollectionUtil.join(ls, "&"); + } + + CloseableHttpResponse response; + try (CloseableHttpClient httpClient = HttpClients.createDefault()) { + HttpGet httpGet = new HttpGet(url); + response = httpClient.execute(httpGet); + log.info("ZLM请求成功,url={}, code={}", url, response.getStatusLine().getStatusCode()); + HttpEntity entity = response.getEntity(); + String res = EntityUtils.toString(entity); + log.info("ZLM请求成功,result={}", res); + return res; + } catch (Exception e) { + log.info("ZLM发起请求失败,msg={}", e.getMessage()); + return null; + } + } + + public static T post(String url, Map header, Map body, TypeReference reference) { + String res = post(url, header, body); + return JSONObject.parseObject(res, reference); + } + + public static R post(String url, Map header, Map body, Class cls) { + String res = post(url, header, body); + return JSONObject.parseObject(res, new TypeReference>(cls) { + }); + } + + + public static String post(String url, Map header, Map body) { + try (CloseableHttpClient httpClient = HttpClients.createDefault()) { + HttpPost httpPost = new HttpPost(url); + httpPost.setHeader("Content-Type", "application/json"); + if (header != null && !header.isEmpty()) { + for (Map.Entry entry : header.entrySet()) { + httpPost.setHeader(entry.getKey(), String.valueOf(entry.getValue())); + } + } + if (body != null && !body.isEmpty()) { + httpPost.setEntity(new StringEntity(JSONObject.toJSONString(body))); + } + CloseableHttpResponse response = httpClient.execute(httpPost); + HttpEntity entity = response.getEntity(); + return EntityUtils.toString(entity); + } catch (Exception e) { + log.info("ZLM发起请求失败,msg={}", e.getMessage()); + return null; + } + + + } + +} diff --git a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/zkmedia/MediaServerUtils.java b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/zkmedia/MediaServerUtils.java new file mode 100644 index 00000000..7d28fcac --- /dev/null +++ b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/zkmedia/MediaServerUtils.java @@ -0,0 +1,36 @@ +package org.dromara.sis.sdk.zkmedia; + +import org.springframework.util.ObjectUtils; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +public class MediaServerUtils { + public static Map urlParamToMap(String params) { + HashMap map = new HashMap<>(); + if (ObjectUtils.isEmpty(params)) { + return map; + } + String[] paramsArray = params.split("&"); + if (paramsArray.length == 0) { + return map; + } + for (String param : paramsArray) { + String[] paramArray = param.split("="); + if (paramArray.length == 2) { + map.put(paramArray[0], paramArray[1]); + } + } + return map; + } + + + public static String formatTimestamp(String timestamp, String pattern) { + Date date = new Date(Long.parseLong(timestamp)); + SimpleDateFormat sdf = new SimpleDateFormat(pattern); + return sdf.format(date); + } + +} diff --git a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/zkmedia/ZLMediaKitService.java b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/zkmedia/ZLMediaKitService.java new file mode 100644 index 00000000..569ea4df --- /dev/null +++ b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/zkmedia/ZLMediaKitService.java @@ -0,0 +1,159 @@ +package org.dromara.sis.sdk.zkmedia; + + +import org.dromara.sis.sdk.zkmedia.model.AddStreamProxyResp; +import org.dromara.sis.sdk.zkmedia.model.R; +import org.dromara.sis.sdk.zkmedia.model.StartStreamProxy; +import org.dromara.sis.sdk.zkmedia.model.ThreadsLoadDelay; + +import java.util.List; + +public interface ZLMediaKitService { + + /** + * 获取各后台 epoll(或 select)线程负载以及延时 + */ + R> getWorkThreadsLoad(); + + /** + * 获取ZLMediaKit服务器配置信息 + */ + Object getServerConfig(); + + /** + * 设置服务器配置 + */ + Object setServerConfig(); + + /** + * 重启服务器,只有 Daemon 方式才能重启,否则是直接关闭! + */ + Object restartServer(); + + /** + * 获取流列表,可选筛选参数 + */ + Object getMediaList(); + + /** + * 关闭流(目前所有类型的流都支持关闭) + */ + Object closeStreams(); + + /** + * 获取所有 TcpSession 列表(获取所有 tcp 客户端相关信息) + */ + Object getAllSession(); + + /** + * 断开 tcp 连接,比如说可以断开 rtsp、rtmp 播放器等 + */ + Object kickSession(); + + /** + * 断开 tcp 连接,比如说可以断开 rtsp、rtmp 播放器等 + */ + Object kickSessions(); + + /** + * 动态添加 rtsp/rtmp/hls/http-ts/http-flv 拉流代理(只支持 H264/H265/aac/G711/opus 负载) + */ + AddStreamProxyResp addStreamProxy(StartStreamProxy startStreamProxy); + + /** + * (流注册成功后,也可以使用close_streams接口替代) + * 关闭拉流代理 + */ + String delStreamProxy(StartStreamProxy startStreamProxy); + + /** + * 通过 fork FFmpeg 进程的方式拉流代理,支持任意协议 + */ + Object addFFmpegSource(); + + /** + * 流注册成功后,也可以使用close_streams接口替代 + */ + Object delFFmpegSource(); + + /** + * 获取 rtp 代理时的某路 ssrc rtp 信息 + */ + Object getRtpInfo(); + + /** + * 搜索文件系统,获取流对应的录像文件列表或日期文件夹列表 + */ + Object getMp4RecordFile(); + + /** + * 开始录制 hls 或 MP4 + */ + Object startRecord(); + + /** + * 停止录制流 + */ + Object stopRecord(); + + /** + * 获取流录制状态 + */ + Object isRecording(); + + /** + * 获取截图或生成实时截图并返回 + */ + Object getSnap(); + + /** + * 创建 GB28181 RTP 接收端口,如果该端口接收数据超时,则会自动被回收(不用调用 closeRtpServer 接口) + */ + Object openRtpServer(); + + /** + * 关闭 GB28181 RTP 接收端口 + */ + Object closeRtpServer(); + + /** + * 获取 openRtpServer 接口创建的所有 RTP 服务器 + */ + Object listRtpServer(); + + /** + * 作为 GB28181 客户端,启动 ps-rtp 推流,支持 rtp/udp 方式;该接口支持 rtsp/rtmp 等协议转 ps-rtp 推流。第一次推流失败会直接返回错误,成功一次后,后续失败也将无限重试。 + */ + Object startSendRtp(); + + /** + * 停止 GB28181 ps-rtp 推流 + */ + Object stopSendRtp(); + + /** + * 获取主要对象个数统计,主要用于分析内存性能 + */ + Object getStatistic(); + + /** + * 添加 rtsp/rtmp 主动推流(把本服务器的直播流推送到其他服务器去) + */ + Object addStreamPusherProxy(); + + /** + * 关闭推流,可以使用close_streams接口关闭源直播流也可以停止推流) + */ + Object delStreamPusherProxy(); + + /** + * 获取版本信息,如分支,commit id, 编译时间 + */ + Object getVersion(); + + /** + * 获取某个流观看者列表 + */ + Object getMediaPlayerList(); + +} diff --git a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/zkmedia/ZLMediaKitServiceImpl.java b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/zkmedia/ZLMediaKitServiceImpl.java new file mode 100644 index 00000000..ba519235 --- /dev/null +++ b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/zkmedia/ZLMediaKitServiceImpl.java @@ -0,0 +1,248 @@ +package org.dromara.sis.sdk.zkmedia; + +import com.alibaba.fastjson2.TypeReference; +import lombok.extern.slf4j.Slf4j; +import org.dromara.sis.config.ZLMediaKitConfig; +import org.dromara.sis.sdk.zkmedia.model.AddStreamProxyResp; +import org.dromara.sis.sdk.zkmedia.model.R; +import org.dromara.sis.sdk.zkmedia.model.StartStreamProxy; +import org.dromara.sis.sdk.zkmedia.model.ThreadsLoadDelay; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Slf4j +@Service("com.parkclouds.media.service.ZLMediaKitServiceImpl") +public class ZLMediaKitServiceImpl implements ZLMediaKitService { + + @Resource + private ZLMediaKitConfig zlmConfig; + private static volatile String ZLM_REQUEST_PREFIX = null; + + public String getRequestUrl(String uri) { + if (ZLM_REQUEST_PREFIX == null) { + synchronized (ZLMediaKitServiceImpl.class) { + if (ZLM_REQUEST_PREFIX == null) { + ZLM_REQUEST_PREFIX = String.format("http://%s:%d/index/api/", zlmConfig.getIp(), zlmConfig.getHttpPort()); + } + } + } + return ZLM_REQUEST_PREFIX + uri; + } + + public Map getCommonParams() { + Map params = new HashMap<>(16); + params.put("secret", zlmConfig.getApiSecret()); + return params; + } + + @Override + public R> getWorkThreadsLoad() { + String url = getRequestUrl("getThreadsLoad"); + Map commonParams = getCommonParams(); + return HttpClientUtil.get(url, commonParams, new TypeReference>>() { + }); + } + + @Override + public Object getServerConfig() { + return null; + } + + @Override + public Object setServerConfig() { + return null; + } + + @Override + public Object restartServer() { + return null; + } + + @Override + public Object getMediaList() { + return null; + } + + @Override + public Object closeStreams() { + return null; + } + + @Override + public Object getAllSession() { + return null; + } + + @Override + public Object kickSession() { + return null; + } + + @Override + public Object kickSessions() { + return null; + } + + /** + * 获取拉流地址 + */ + private AddStreamProxyResp setPlayerUrl(String app, String streamId, AddStreamProxyResp resp) { + if (resp == null) { + resp = new AddStreamProxyResp(); + } + // RTMP 播放地址 + resp.setRtmp(String.format("rtmp://%s:%d/%s/%s", zlmConfig.getIp(), zlmConfig.getRtmpPort(), app, streamId)); + // RTSP 播放地址 + resp.setRtsp(String.format("rtsp://%s:%d/%s/%s", zlmConfig.getIp(), zlmConfig.getRtspPort(), app, streamId)); + // HTTP-FLV 播放地址 + resp.setFlv(String.format("http://%s:%d/%s/%s.live.flv", zlmConfig.getIp(), zlmConfig.getHttpPort(), app, streamId)); + resp.setWsFlv(String.format("ws://%s:%d/%s/%s.live.flv", zlmConfig.getIp(), zlmConfig.getHttpPort(), app, streamId)); + // HLS 播放地址 + resp.setHls(String.format("http://%s:%d/%s/%s/hls.m3u8", zlmConfig.getIp(), zlmConfig.getHttpPort(), app, streamId)); + // MP4 播放地址 + resp.setMp4(String.format("http://%s:%d/%s/%s.live.mp4", zlmConfig.getIp(), zlmConfig.getHttpPort(), app, streamId)); + return resp; + } + + + @Override + public AddStreamProxyResp addStreamProxy(StartStreamProxy startStreamProxy) { + Map commonParams = getCommonParams(); + commonParams.put("vhost", zlmConfig.getVhost()); + commonParams.put("app", startStreamProxy.getApp()); + commonParams.put("stream", startStreamProxy.getStream()); + commonParams.put("url", startStreamProxy.getUrl()); + commonParams.put("rtp_type", startStreamProxy.getRtpType()); + R result = HttpClientUtil.get(getRequestUrl("addStreamProxy"), commonParams, AddStreamProxyResp.class); + if (result != null) { + if (result.getCode() == 0) { + log.info("创建拉流任务成功."); + } + // 此处代表拉流任务已存在 + if (result.getCode() == -1) { + log.info("拉流任务已存在,返回播放地址。"); + } + return setPlayerUrl(startStreamProxy.getApp(), startStreamProxy.getStream(), result.getData()); + } + return null; + } + + @Override + public String delStreamProxy(StartStreamProxy startStreamProxy) { + Map commonParams = getCommonParams(); + commonParams.put("schema", "rtsp"); + commonParams.put("vhost", zlmConfig.getVhost()); + commonParams.put("app", startStreamProxy.getApp()); + commonParams.put("stream", startStreamProxy.getStream()); + commonParams.put("force", 1); + R result = HttpClientUtil.get(getRequestUrl("close_streams"), commonParams, AddStreamProxyResp.class); + if (result != null) { + String s =null; + if (result.getCode() == 0) { + s = "关闭流成功"; + } + // 此处代表拉流任务已存在 + if (result.getCode() == -1) { + s = "关闭流失败"; + } + log.info("{},关闭流数量:{}",s,result.getData()); + return s; + } + return null; + } + + @Override + public Object addFFmpegSource() { + return null; + } + + @Override + public Object delFFmpegSource() { + return null; + } + + @Override + public Object getRtpInfo() { + return null; + } + + @Override + public Object getMp4RecordFile() { + return null; + } + + @Override + public Object startRecord() { + return null; + } + + @Override + public Object stopRecord() { + return null; + } + + @Override + public Object isRecording() { + return null; + } + + @Override + public Object getSnap() { + return null; + } + + @Override + public Object openRtpServer() { + return null; + } + + @Override + public Object closeRtpServer() { + return null; + } + + @Override + public Object listRtpServer() { + return null; + } + + @Override + public Object startSendRtp() { + return null; + } + + @Override + public Object stopSendRtp() { + return null; + } + + @Override + public Object getStatistic() { + return null; + } + + @Override + public Object addStreamPusherProxy() { + return null; + } + + @Override + public Object delStreamPusherProxy() { + return null; + } + + @Override + public Object getVersion() { + return null; + } + + @Override + public Object getMediaPlayerList() { + return null; + } + +} diff --git a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/zkmedia/model/AddStreamProxy.java b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/zkmedia/model/AddStreamProxy.java new file mode 100644 index 00000000..58351c2b --- /dev/null +++ b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/zkmedia/model/AddStreamProxy.java @@ -0,0 +1,36 @@ +package org.dromara.sis.sdk.zkmedia.model; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + + +@Data +public class AddStreamProxy { + + @NotBlank + private String videoIp; + + @NotNull + private Integer videoPort; + + @NotBlank + private String factoryNo; + + @NotBlank + private String account; + + @NotBlank + private String pwd; + + @NotNull + private String channelId; + + + private String startTime; + + private String endTime; + + private String stream; + +} diff --git a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/zkmedia/model/AddStreamProxyResp.java b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/zkmedia/model/AddStreamProxyResp.java new file mode 100644 index 00000000..051e62a9 --- /dev/null +++ b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/zkmedia/model/AddStreamProxyResp.java @@ -0,0 +1,23 @@ +package org.dromara.sis.sdk.zkmedia.model; + +import lombok.Data; + +import java.io.Serializable; + +@Data +public class AddStreamProxyResp implements Serializable { + + private String key; + + private String rtsp; + + private String rtmp; + + private String flv; + private String wsFlv; + + private String mp4; + + private String hls; + +} diff --git a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/zkmedia/model/HookParam.java b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/zkmedia/model/HookParam.java new file mode 100644 index 00000000..45cacf1b --- /dev/null +++ b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/zkmedia/model/HookParam.java @@ -0,0 +1,14 @@ +package org.dromara.sis.sdk.zkmedia.model; + +import lombok.Data; + +/** + * zlm hook事件的参数 + * @author lin + */ +@Data +public class HookParam { + + private String mediaServerId; + +} diff --git a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/zkmedia/model/HookResult.java b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/zkmedia/model/HookResult.java new file mode 100644 index 00000000..8f77540a --- /dev/null +++ b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/zkmedia/model/HookResult.java @@ -0,0 +1,28 @@ +package org.dromara.sis.sdk.zkmedia.model; + +import lombok.Data; +import lombok.experimental.Accessors; + +@Data +@Accessors(chain = true) +public class HookResult { + + private int code; + private String msg; + + // 此字段在部分返回结果中用到 + private Boolean close; + + + public HookResult() { + } + + public HookResult(int code, String msg) { + this.code = code; + this.msg = msg; + } + + public static HookResult SUCCESS() { + return new HookResult(0, "success"); + } +} diff --git a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/zkmedia/model/HookResultForOnPublish.java b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/zkmedia/model/HookResultForOnPublish.java new file mode 100644 index 00000000..011dc7e4 --- /dev/null +++ b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/zkmedia/model/HookResultForOnPublish.java @@ -0,0 +1,17 @@ +package org.dromara.sis.sdk.zkmedia.model; + +import lombok.Getter; +import lombok.Setter; + +@Setter +@Getter +public class HookResultForOnPublish extends HookResult { + + private boolean enable_audio; + private boolean enable_mp4; + private int mp4_max_second; + private String mp4_save_path; + private String stream_replace; + private Integer modify_stamp; + +} diff --git a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/zkmedia/model/OnPlayHookParam.java b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/zkmedia/model/OnPlayHookParam.java new file mode 100644 index 00000000..0082bed5 --- /dev/null +++ b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/zkmedia/model/OnPlayHookParam.java @@ -0,0 +1,22 @@ +package org.dromara.sis.sdk.zkmedia.model; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * zlm hook事件中的on_play事件的参数 + * + * @author lin + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class OnPlayHookParam extends HookParam { + private String id; + private String app; + private String stream; + private String ip; + private String params; + private int port; + private String schema; + private String vhost; +} diff --git a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/zkmedia/model/OnPushParam.java b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/zkmedia/model/OnPushParam.java new file mode 100644 index 00000000..26081e0e --- /dev/null +++ b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/zkmedia/model/OnPushParam.java @@ -0,0 +1,29 @@ +package org.dromara.sis.sdk.zkmedia.model; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +@EqualsAndHashCode(callSuper = true) +@Data +public class OnPushParam extends HookParam{ + + private String app; + + private String id; + + private String ip; + + private String params; + + private Integer port; + + private String schema; + + private String stream; + + private String vhost; + + + + +} diff --git a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/zkmedia/model/OnServerKeepaliveHookParam.java b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/zkmedia/model/OnServerKeepaliveHookParam.java new file mode 100644 index 00000000..605ae9e5 --- /dev/null +++ b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/zkmedia/model/OnServerKeepaliveHookParam.java @@ -0,0 +1,20 @@ +package org.dromara.sis.sdk.zkmedia.model; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * zlm hook事件中的on_play事件的参数 + * + * @author lin + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class OnServerKeepaliveHookParam extends HookParam { + + private Object data; + + private Integer hook_index; + + +} diff --git a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/zkmedia/model/OnStreamChangedHookParam.java b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/zkmedia/model/OnStreamChangedHookParam.java new file mode 100644 index 00000000..d2ed4948 --- /dev/null +++ b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/zkmedia/model/OnStreamChangedHookParam.java @@ -0,0 +1,203 @@ +package org.dromara.sis.sdk.zkmedia.model; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.List; +import java.util.Map; + +/** + * @author lin + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class OnStreamChangedHookParam extends HookParam { + + /** + * 注册/注销 + */ + private boolean regist; + + /** + * 应用名 + */ + private String app; + + /** + * 流id + */ + private String stream; + + /** + * 推流鉴权Id + */ + private String callId; + + /** + * 观看总人数,包括hls/rtsp/rtmp/http-flv/ws-flv + */ + private int totalReaderCount; + + /** + * 协议 包括hls/rtsp/rtmp/http-flv/ws-flv + */ + private String schema; + + + /** + * 产生源类型, + * unknown = 0, + * rtmp_push=1, + * rtsp_push=2, + * rtp_push=3, + * pull=4, + * ffmpeg_pull=5, + * mp4_vod=6, + * device_chn=7 + */ + private int originType; + + /** + * 客户端和服务器网络信息,可能为null类型 + */ + private OriginSock originSock; + + /** + * 产生源类型的字符串描述 + */ + private String originTypeStr; + + /** + * 产生源的url + */ + private String originUrl; + + /** + * 服务器id + */ + private String severId; + + /** + * GMT unix系统时间戳,单位秒 + */ + private Long createStamp; + + /** + * 存活时间,单位秒 + */ + private Long aliveSecond; + + /** + * 数据产生速度,单位byte/s + */ + private Long bytesSpeed; + + /** + * 音视频轨道 + */ + private List tracks; + + /** + * 音视频轨道 + */ + private String vhost; + + /** + * 额外的参数字符串 + */ + private String params; + + /** + * 额外的参数 + */ + private Map paramMap; + + + @Data + public static class MediaTrack { + /** + * 音频通道数 + */ + private int channels; + + /** + * H264 = 0, H265 = 1, AAC = 2, G711A = 3, G711U = 4 + */ + private int codec_id; + + /** + * 编码类型名称 CodecAAC CodecH264 + */ + private String codec_id_name; + + /** + * Video = 0, Audio = 1 + */ + private int codec_type; + + /** + * 轨道是否准备就绪 + */ + private boolean ready; + + /** + * 音频采样位数 + */ + private int sample_bit; + + /** + * 音频采样率 + */ + private int sample_rate; + + /** + * 视频fps + */ + private float fps; + + /** + * 视频高 + */ + private int height; + + /** + * 视频宽 + */ + private int width; + + /** + * 帧数 + */ + private int frames; + + /** + * 关键帧数 + */ + private int key_frames; + + /** + * GOP大小 + */ + private int gop_size; + + /** + * GOP间隔时长(ms) + */ + private int gop_interval_ms; + + /** + * 丢帧率 + */ + private float loss; + } + + @Data + public static class OriginSock { + private String identifier; + private String local_ip; + private int local_port; + private String peer_ip; + private int peer_port; + + } +} diff --git a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/zkmedia/model/OnStreamNoneReaderHookParam.java b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/zkmedia/model/OnStreamNoneReaderHookParam.java new file mode 100644 index 00000000..8c1893ee --- /dev/null +++ b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/zkmedia/model/OnStreamNoneReaderHookParam.java @@ -0,0 +1,15 @@ +package org.dromara.sis.sdk.zkmedia.model; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Data +@EqualsAndHashCode(callSuper = true) +public class OnStreamNoneReaderHookParam extends HookParam{ + + private String schema; + private String app; + private String stream; + private String vhost; + +} diff --git a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/zkmedia/model/OnStreamNotFoundHookParam.java b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/zkmedia/model/OnStreamNotFoundHookParam.java new file mode 100644 index 00000000..d6547d29 --- /dev/null +++ b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/zkmedia/model/OnStreamNotFoundHookParam.java @@ -0,0 +1,21 @@ +package org.dromara.sis.sdk.zkmedia.model; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * zlm hook事件中的on_stream_not_found事件的参数 + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class OnStreamNotFoundHookParam extends HookParam { + private String id; + private String app; + private String stream; + private String ip; + private String params; + private int port; + private String schema; + private String vhost; + +} diff --git a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/zkmedia/model/R.java b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/zkmedia/model/R.java new file mode 100644 index 00000000..16bcc1d6 --- /dev/null +++ b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/zkmedia/model/R.java @@ -0,0 +1,12 @@ +package org.dromara.sis.sdk.zkmedia.model; + +import lombok.Data; + +@Data +public class R { + + private Integer code; + + private T data; + +} diff --git a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/zkmedia/model/ServerKeepaliveData.java b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/zkmedia/model/ServerKeepaliveData.java new file mode 100644 index 00000000..513420fc --- /dev/null +++ b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/zkmedia/model/ServerKeepaliveData.java @@ -0,0 +1,25 @@ +package org.dromara.sis.sdk.zkmedia.model; + +import lombok.Data; + +@Data +public class ServerKeepaliveData { + + private Integer Buffer; + private String BufferLikeString; + private Integer BufferList; + private Integer BufferRaw; + private Integer Frame; + private Integer FrameImp; + private Integer MediaSource; + private Integer MultiMediaSourceMuxer; + private Integer RtmpPacket; + private Integer RtpPacket; + private Integer Socket; + private Integer TcpClient; + private Integer TcpServer; + private Integer TcpSession; + private Integer UdpServer; + private Integer UdpSession; + +} diff --git a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/zkmedia/model/StartStreamProxy.java b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/zkmedia/model/StartStreamProxy.java new file mode 100644 index 00000000..d25813c7 --- /dev/null +++ b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/zkmedia/model/StartStreamProxy.java @@ -0,0 +1,18 @@ +package org.dromara.sis.sdk.zkmedia.model; + +import lombok.Data; + +import java.io.Serializable; + +@Data +public class StartStreamProxy implements Serializable { + + private String app = "live"; + + private String stream; + + private String url; + + private Integer rtpType = 1; + +} diff --git a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/zkmedia/model/ThreadsLoadDelay.java b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/zkmedia/model/ThreadsLoadDelay.java new file mode 100644 index 00000000..631334aa --- /dev/null +++ b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/zkmedia/model/ThreadsLoadDelay.java @@ -0,0 +1,18 @@ +package org.dromara.sis.sdk.zkmedia.model; + +import lombok.Data; + +@Data +public class ThreadsLoadDelay { + + /** + * 该线程延时 + */ + private Integer delay; + + /** + * 该线程负载,0 ~ 100 + */ + private Integer load; + +} diff --git a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/service/ISisAuthRecordService.java b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/service/ISisAuthRecordService.java index 57c24ee3..8858c71c 100644 --- a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/service/ISisAuthRecordService.java +++ b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/service/ISisAuthRecordService.java @@ -89,4 +89,11 @@ public interface ISisAuthRecordService { * @return List> */ List> authDeviceTree(); + + /** + * 根据人脸比对ID,返回授权记录 + * + * @param personId 人脸比对ID + */ + List checkAuth(Long personId); } diff --git a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/service/ISisDeviceBindRefService.java b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/service/ISisDeviceBindRefService.java index d47a2f8f..8b04d92c 100644 --- a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/service/ISisDeviceBindRefService.java +++ b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/service/ISisDeviceBindRefService.java @@ -81,7 +81,7 @@ public interface ISisDeviceBindRefService { * @param ipcAddr 设备ip * @return 返回关联关系表 */ - SisDeviceBindRef queryByDeviceIp(String ipcAddr); + List queryByDeviceIp(String ipcAddr); /** * 批量写入设备绑定关系 diff --git a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/service/ISisElevatorFloorRefService.java b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/service/ISisElevatorFloorRefService.java new file mode 100644 index 00000000..fdca3de7 --- /dev/null +++ b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/service/ISisElevatorFloorRefService.java @@ -0,0 +1,75 @@ +package org.dromara.sis.service; + +import org.dromara.sis.domain.vo.SisElevatorFloorRefVo; +import org.dromara.sis.domain.bo.SisElevatorFloorRefBo; +import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.common.mybatis.core.page.PageQuery; + +import java.util.Collection; +import java.util.List; + +/** + * 电梯⇄楼层关联Service接口 + * + * @author lsm + * @since 2025-07-15 + */ +public interface ISisElevatorFloorRefService { + + /** + * 查询电梯⇄楼层关联 + * + * @param id 主键 + * @return 电梯⇄楼层关联 + */ + SisElevatorFloorRefVo queryById(Long id); + + /** + * 分页查询电梯⇄楼层关联列表 + * + * @param bo 查询条件 + * @param pageQuery 分页参数 + * @return 电梯⇄楼层关联分页列表 + */ + TableDataInfo queryPageList(SisElevatorFloorRefBo bo, PageQuery pageQuery); + + /** + * 查询符合条件的电梯⇄楼层关联列表 + * + * @param bo 查询条件 + * @return 电梯⇄楼层关联列表 + */ + List queryList(SisElevatorFloorRefBo bo); + + /** + * 新增电梯⇄楼层关联 + * + * @param bo 电梯⇄楼层关联 + * @return 是否新增成功 + */ + Boolean insertByBo(SisElevatorFloorRefBo bo); + + /** + * 修改电梯⇄楼层关联 + * + * @param bo 电梯⇄楼层关联 + * @return 是否修改成功 + */ + Boolean updateByBo(SisElevatorFloorRefBo bo); + + /** + * 校验并批量删除电梯⇄楼层关联信息 + * + * @param ids 待删除的主键集合 + * @param isValid 是否进行有效性校验 + * @return 是否删除成功 + */ + Boolean deleteWithValidByIds(Collection ids, Boolean isValid); + + /** + * 根据电梯id,获取电梯⇄楼层关联信息 + * + * @param elevatorId 电梯id + */ + List queryByElevatorId(Long elevatorId); +} diff --git a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/service/impl/SisAuthRecordServiceImpl.java b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/service/impl/SisAuthRecordServiceImpl.java index f9f49304..e5736ad3 100644 --- a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/service/impl/SisAuthRecordServiceImpl.java +++ b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/service/impl/SisAuthRecordServiceImpl.java @@ -199,7 +199,7 @@ public class SisAuthRecordServiceImpl implements ISisAuthRecordService { */ @Override @Transactional(rollbackFor = Exception.class) - public Boolean deleteByLibId(Long libId){ + public Boolean deleteByLibId(Long libId) { LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); lqw.eq(SisAuthRecord::getLibId, libId); return baseMapper.delete(lqw) > 0; @@ -208,10 +208,10 @@ public class SisAuthRecordServiceImpl implements ISisAuthRecordService { /** * 查询所有可授权设备树 * - * @return List> + * @return List> */ @Override - public List> authDeviceTree(){ + public List> authDeviceTree() { // 暂时将所有数据放入写死的根节点中 TreeNode root = new TreeNode<>(); root.setLevel(0); @@ -238,7 +238,6 @@ public class SisAuthRecordServiceImpl implements ISisAuthRecordService { List eleVoList = elevatorInfoService.queryList(new SisElevatorInfoBo()); - List> acChildrenList = acVoList.stream().map(item -> { TreeNode node = new TreeNode<>(); node.setLevel(2); @@ -265,4 +264,14 @@ public class SisAuthRecordServiceImpl implements ISisAuthRecordService { root.setChildren(List.of(accessNode, elevatorNode)); return List.of(root); } + + /** + * 根据人脸比对ID,返回授权记录 + * + * @param personId 人脸比对ID + */ + @Override + public List checkAuth(Long personId) { + return baseMapper.checkAuth(personId); + } } diff --git a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/service/impl/SisDeviceBindRefServiceImpl.java b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/service/impl/SisDeviceBindRefServiceImpl.java index 6657674f..7c1f6bd5 100644 --- a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/service/impl/SisDeviceBindRefServiceImpl.java +++ b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/service/impl/SisDeviceBindRefServiceImpl.java @@ -138,10 +138,10 @@ public class SisDeviceBindRefServiceImpl implements ISisDeviceBindRefService { } @Override - public SisDeviceBindRef queryByDeviceIp(String ipcAddr) { + public List queryByDeviceIp(String ipcAddr) { LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(); lqw.eq(SisDeviceBindRef::getDeviceIp, ipcAddr); - return baseMapper.selectOne(lqw); + return baseMapper.selectVoList(lqw); } @Override diff --git a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/service/impl/SisElevatorFloorRefServiceImpl.java b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/service/impl/SisElevatorFloorRefServiceImpl.java new file mode 100644 index 00000000..524fae90 --- /dev/null +++ b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/service/impl/SisElevatorFloorRefServiceImpl.java @@ -0,0 +1,145 @@ +package org.dromara.sis.service.impl; + +import org.dromara.common.core.utils.MapstructUtils; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.common.mybatis.core.page.PageQuery; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.dromara.sis.domain.bo.SisElevatorFloorRefBo; +import org.dromara.sis.domain.vo.SisElevatorFloorRefVo; +import org.dromara.sis.domain.SisElevatorFloorRef; +import org.dromara.sis.mapper.SisElevatorFloorRefMapper; +import org.dromara.sis.service.ISisElevatorFloorRefService; + +import java.util.List; +import java.util.Map; +import java.util.Collection; + +/** + * 电梯⇄楼层关联Service业务层处理 + * + * @author lsm + * @date 2025-07-15 + */ +@Slf4j +@RequiredArgsConstructor +@Service +public class SisElevatorFloorRefServiceImpl implements ISisElevatorFloorRefService { + + private final SisElevatorFloorRefMapper baseMapper; + + /** + * 查询电梯⇄楼层关联 + * + * @param id 主键 + * @return 电梯⇄楼层关联 + */ + @Override + public SisElevatorFloorRefVo queryById(Long id) { + return baseMapper.selectVoById(id); + } + + /** + * 分页查询电梯⇄楼层关联列表 + * + * @param bo 查询条件 + * @param pageQuery 分页参数 + * @return 电梯⇄楼层关联分页列表 + */ + @Override + public TableDataInfo queryPageList(SisElevatorFloorRefBo bo, PageQuery pageQuery) { + LambdaQueryWrapper lqw = buildQueryWrapper(bo); + Page result = baseMapper.selectVoPage(pageQuery.build(), lqw); + return TableDataInfo.build(result); + } + + /** + * 查询符合条件的电梯⇄楼层关联列表 + * + * @param bo 查询条件 + * @return 电梯⇄楼层关联列表 + */ + @Override + public List queryList(SisElevatorFloorRefBo bo) { + LambdaQueryWrapper lqw = buildQueryWrapper(bo); + return baseMapper.selectVoList(lqw); + } + + private LambdaQueryWrapper buildQueryWrapper(SisElevatorFloorRefBo bo) { + Map params = bo.getParams(); + LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); + lqw.orderByAsc(SisElevatorFloorRef::getId); + lqw.eq(bo.getElevatorId() != null, SisElevatorFloorRef::getElevatorId, bo.getElevatorId()); + lqw.eq(bo.getLayerNum() != null, SisElevatorFloorRef::getLayerNum, bo.getLayerNum()); + return lqw; + } + + /** + * 新增电梯⇄楼层关联 + * + * @param bo 电梯⇄楼层关联 + * @return 是否新增成功 + */ + @Override + public Boolean insertByBo(SisElevatorFloorRefBo bo) { + SisElevatorFloorRef add = MapstructUtils.convert(bo, SisElevatorFloorRef.class); + validEntityBeforeSave(add); + boolean flag = baseMapper.insert(add) > 0; + if (flag) { + bo.setId(add.getId()); + } + return flag; + } + + /** + * 修改电梯⇄楼层关联 + * + * @param bo 电梯⇄楼层关联 + * @return 是否修改成功 + */ + @Override + public Boolean updateByBo(SisElevatorFloorRefBo bo) { + SisElevatorFloorRef update = MapstructUtils.convert(bo, SisElevatorFloorRef.class); + validEntityBeforeSave(update); + return baseMapper.updateById(update) > 0; + } + + /** + * 保存前的数据校验 + */ + private void validEntityBeforeSave(SisElevatorFloorRef entity) { + //TODO 做一些数据校验,如唯一约束 + } + + /** + * 校验并批量删除电梯⇄楼层关联信息 + * + * @param ids 待删除的主键集合 + * @param isValid 是否进行有效性校验 + * @return 是否删除成功 + */ + @Override + public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) { + if (isValid) { + //TODO 做一些业务上的校验,判断是否需要校验 + } + return baseMapper.deleteByIds(ids) > 0; + } + + /** + * 根据电梯id,获取电梯⇄楼层关联信息 + * + * @param elevatorId 电梯id + */ + @Override + public List queryByElevatorId(Long elevatorId) { + LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); + lqw.eq(SisElevatorFloorRef::getElevatorId, elevatorId); + return baseMapper.selectVoList(lqw); + } +} diff --git a/ruoyi-modules/Sis/src/main/resources/mapper/sis/SisAuthRecordMapper.xml b/ruoyi-modules/Sis/src/main/resources/mapper/sis/SisAuthRecordMapper.xml index 27bad1ae..91142918 100644 --- a/ruoyi-modules/Sis/src/main/resources/mapper/sis/SisAuthRecordMapper.xml +++ b/ruoyi-modules/Sis/src/main/resources/mapper/sis/SisAuthRecordMapper.xml @@ -5,10 +5,16 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"